1// Copyright 2018 Google Inc. All rights reserved. 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 "errors" 19 "fmt" 20 "path" 21 "path/filepath" 22 "reflect" 23 "sort" 24 "strings" 25 "sync" 26 27 "github.com/google/blueprint" 28 "github.com/google/blueprint/proptools" 29 30 "android/soong/android" 31 "android/soong/dexpreopt" 32) 33 34// A tag to associated a dependency with a specific api scope. 35type scopeDependencyTag struct { 36 blueprint.BaseDependencyTag 37 name string 38 apiScope *apiScope 39 40 // Function for extracting appropriate path information from the dependency. 41 depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.Module) error 42} 43 44// Extract tag specific information from the dependency. 45func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) { 46 err := tag.depInfoExtractor(paths, ctx, dep) 47 if err != nil { 48 ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error()) 49 } 50} 51 52var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil) 53 54func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool { 55 return false 56} 57 58// Provides information about an api scope, e.g. public, system, test. 59type apiScope struct { 60 // The name of the api scope, e.g. public, system, test 61 name string 62 63 // The api scope that this scope extends. 64 // 65 // This organizes the scopes into an extension hierarchy. 66 // 67 // If set this means that the API provided by this scope includes the API provided by the scope 68 // set in this field. 69 extends *apiScope 70 71 // The next api scope that a library that uses this scope can access. 72 // 73 // This organizes the scopes into an access hierarchy. 74 // 75 // If set this means that a library that can access this API can also access the API provided by 76 // the scope set in this field. 77 // 78 // A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of 79 // every java_sdk_library that it depends on. If the library does not provide an API for <scope> 80 // then it will traverse up this access hierarchy to find an API that it does provide. 81 // 82 // If this is not set then it defaults to the scope set in extends. 83 canAccess *apiScope 84 85 // The legacy enabled status for a specific scope can be dependent on other 86 // properties that have been specified on the library so it is provided by 87 // a function that can determine the status by examining those properties. 88 legacyEnabledStatus func(module *SdkLibrary) bool 89 90 // The default enabled status for non-legacy behavior, which is triggered by 91 // explicitly enabling at least one api scope. 92 defaultEnabledStatus bool 93 94 // Gets a pointer to the scope specific properties. 95 scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties 96 97 // The name of the field in the dynamically created structure. 98 fieldName string 99 100 // The name of the property in the java_sdk_library_import 101 propertyName string 102 103 // The tag to use to depend on the prebuilt stubs library module 104 prebuiltStubsTag scopeDependencyTag 105 106 // The tag to use to depend on the everything stubs library module. 107 everythingStubsTag scopeDependencyTag 108 109 // The tag to use to depend on the exportable stubs library module. 110 exportableStubsTag scopeDependencyTag 111 112 // The tag to use to depend on the stubs source module (if separate from the API module). 113 stubsSourceTag scopeDependencyTag 114 115 // The tag to use to depend on the stubs source and API module. 116 stubsSourceAndApiTag scopeDependencyTag 117 118 // The tag to use to depend on the module that provides the latest version of the API .txt file. 119 latestApiModuleTag scopeDependencyTag 120 121 // The tag to use to depend on the module that provides the latest version of the API removed.txt 122 // file. 123 latestRemovedApiModuleTag scopeDependencyTag 124 125 // The scope specific prefix to add to the api file base of "current.txt" or "removed.txt". 126 apiFilePrefix string 127 128 // The scope specific suffix to add to the sdk library module name to construct a scope specific 129 // module name. 130 moduleSuffix string 131 132 // SDK version that the stubs library is built against. Note that this is always 133 // *current. Older stubs library built with a numbered SDK version is created from 134 // the prebuilt jar. 135 sdkVersion string 136 137 // The annotation that identifies this API level, empty for the public API scope. 138 annotation string 139 140 // Extra arguments to pass to droidstubs for this scope. 141 // 142 // This is not used directly but is used to construct the droidstubsArgs. 143 extraArgs []string 144 145 // The args that must be passed to droidstubs to generate the API and stubs source 146 // for this scope, constructed dynamically by initApiScope(). 147 // 148 // The API only includes the additional members that this scope adds over the scope 149 // that it extends. 150 // 151 // The stubs source must include the definitions of everything that is in this 152 // api scope and all the scopes that this one extends. 153 droidstubsArgs []string 154 155 // Whether the api scope can be treated as unstable, and should skip compat checks. 156 unstable bool 157 158 // Represents the SDK kind of this scope. 159 kind android.SdkKind 160} 161 162// Initialize a scope, creating and adding appropriate dependency tags 163func initApiScope(scope *apiScope) *apiScope { 164 name := scope.name 165 scopeByName[name] = scope 166 allScopeNames = append(allScopeNames, name) 167 scope.propertyName = strings.ReplaceAll(name, "-", "_") 168 scope.fieldName = proptools.FieldNameForProperty(scope.propertyName) 169 scope.prebuiltStubsTag = scopeDependencyTag{ 170 name: name + "-stubs", 171 apiScope: scope, 172 depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency, 173 } 174 scope.everythingStubsTag = scopeDependencyTag{ 175 name: name + "-stubs-everything", 176 apiScope: scope, 177 depInfoExtractor: (*scopePaths).extractEverythingStubsLibraryInfoFromDependency, 178 } 179 scope.exportableStubsTag = scopeDependencyTag{ 180 name: name + "-stubs-exportable", 181 apiScope: scope, 182 depInfoExtractor: (*scopePaths).extractExportableStubsLibraryInfoFromDependency, 183 } 184 scope.stubsSourceTag = scopeDependencyTag{ 185 name: name + "-stubs-source", 186 apiScope: scope, 187 depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep, 188 } 189 scope.stubsSourceAndApiTag = scopeDependencyTag{ 190 name: name + "-stubs-source-and-api", 191 apiScope: scope, 192 depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider, 193 } 194 scope.latestApiModuleTag = scopeDependencyTag{ 195 name: name + "-latest-api", 196 apiScope: scope, 197 depInfoExtractor: (*scopePaths).extractLatestApiPath, 198 } 199 scope.latestRemovedApiModuleTag = scopeDependencyTag{ 200 name: name + "-latest-removed-api", 201 apiScope: scope, 202 depInfoExtractor: (*scopePaths).extractLatestRemovedApiPath, 203 } 204 205 // To get the args needed to generate the stubs source append all the args from 206 // this scope and all the scopes it extends as each set of args adds additional 207 // members to the stubs. 208 var scopeSpecificArgs []string 209 if scope.annotation != "" { 210 scopeSpecificArgs = []string{"--show-annotation", scope.annotation} 211 } 212 for s := scope; s != nil; s = s.extends { 213 scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...) 214 215 // Ensure that the generated stubs includes all the API elements from the API scope 216 // that this scope extends. 217 if s != scope && s.annotation != "" { 218 scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation) 219 } 220 } 221 222 // By default, a library that can access a scope can also access the scope it extends. 223 if scope.canAccess == nil { 224 scope.canAccess = scope.extends 225 } 226 227 // Escape any special characters in the arguments. This is needed because droidstubs 228 // passes these directly to the shell command. 229 scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs) 230 231 return scope 232} 233 234func (scope *apiScope) stubsLibraryModuleNameSuffix() string { 235 return ".stubs" + scope.moduleSuffix 236} 237 238func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string { 239 return ".stubs.exportable" + scope.moduleSuffix 240} 241 242func (scope *apiScope) apiLibraryModuleName(baseName string) string { 243 return scope.stubsLibraryModuleName(baseName) + ".from-text" 244} 245 246func (scope *apiScope) sourceStubsLibraryModuleName(baseName string) string { 247 return scope.stubsLibraryModuleName(baseName) + ".from-source" 248} 249 250func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string { 251 return scope.exportableStubsLibraryModuleName(baseName) + ".from-source" 252} 253 254func (scope *apiScope) stubsLibraryModuleName(baseName string) string { 255 return baseName + scope.stubsLibraryModuleNameSuffix() 256} 257 258func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string { 259 return baseName + scope.exportableStubsLibraryModuleNameSuffix() 260} 261 262func (scope *apiScope) stubsSourceModuleName(baseName string) string { 263 return baseName + ".stubs.source" + scope.moduleSuffix 264} 265 266func (scope *apiScope) String() string { 267 return scope.name 268} 269 270// snapshotRelativeDir returns the snapshot directory into which the files related to scopes will 271// be stored. 272func (scope *apiScope) snapshotRelativeDir() string { 273 return filepath.Join("sdk_library", scope.name) 274} 275 276// snapshotRelativeCurrentApiTxtPath returns the snapshot path to the API .txt file for the named 277// library. 278func (scope *apiScope) snapshotRelativeCurrentApiTxtPath(name string) string { 279 return filepath.Join(scope.snapshotRelativeDir(), name+".txt") 280} 281 282// snapshotRelativeRemovedApiTxtPath returns the snapshot path to the removed API .txt file for the 283// named library. 284func (scope *apiScope) snapshotRelativeRemovedApiTxtPath(name string) string { 285 return filepath.Join(scope.snapshotRelativeDir(), name+"-removed.txt") 286} 287 288type apiScopes []*apiScope 289 290func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string { 291 var list []string 292 for _, scope := range scopes { 293 list = append(list, accessor(scope)) 294 } 295 return list 296} 297 298// Method that maps the apiScopes properties to the index of each apiScopes elements. 299// apiScopes property to be used as the key can be specified with the input accessor. 300// Only a string property of apiScope can be used as the key of the map. 301func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int { 302 ret := make(map[string]int) 303 for i, scope := range scopes { 304 ret[accessor(scope)] = i 305 } 306 return ret 307} 308 309func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) string { 310 for _, scope := range scopes { 311 if strings.HasSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) { 312 return strings.TrimSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) + 313 scope.stubsLibraryModuleNameSuffix() 314 } 315 } 316 return name 317} 318 319func (scopes apiScopes) matchingScopeFromSdkKind(kind android.SdkKind) *apiScope { 320 for _, scope := range scopes { 321 if scope.kind == kind { 322 return scope 323 } 324 } 325 return nil 326} 327 328var ( 329 scopeByName = make(map[string]*apiScope) 330 allScopeNames []string 331 apiScopePublic = initApiScope(&apiScope{ 332 name: "public", 333 334 // Public scope is enabled by default for both legacy and non-legacy modes. 335 legacyEnabledStatus: func(module *SdkLibrary) bool { 336 return true 337 }, 338 defaultEnabledStatus: true, 339 340 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 341 return &module.sdkLibraryProperties.Public 342 }, 343 sdkVersion: "current", 344 kind: android.SdkPublic, 345 }) 346 apiScopeSystem = initApiScope(&apiScope{ 347 name: "system", 348 extends: apiScopePublic, 349 legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault, 350 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 351 return &module.sdkLibraryProperties.System 352 }, 353 apiFilePrefix: "system-", 354 moduleSuffix: ".system", 355 sdkVersion: "system_current", 356 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)", 357 kind: android.SdkSystem, 358 }) 359 apiScopeTest = initApiScope(&apiScope{ 360 name: "test", 361 extends: apiScopeSystem, 362 legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault, 363 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 364 return &module.sdkLibraryProperties.Test 365 }, 366 apiFilePrefix: "test-", 367 moduleSuffix: ".test", 368 sdkVersion: "test_current", 369 annotation: "android.annotation.TestApi", 370 unstable: true, 371 kind: android.SdkTest, 372 }) 373 apiScopeModuleLib = initApiScope(&apiScope{ 374 name: "module-lib", 375 extends: apiScopeSystem, 376 // The module-lib scope is disabled by default in legacy mode. 377 // 378 // Enabling this would break existing usages. 379 legacyEnabledStatus: func(module *SdkLibrary) bool { 380 return false 381 }, 382 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 383 return &module.sdkLibraryProperties.Module_lib 384 }, 385 apiFilePrefix: "module-lib-", 386 moduleSuffix: ".module_lib", 387 sdkVersion: "module_current", 388 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)", 389 kind: android.SdkModule, 390 }) 391 apiScopeSystemServer = initApiScope(&apiScope{ 392 name: "system-server", 393 extends: apiScopePublic, 394 395 // The system-server scope can access the module-lib scope. 396 // 397 // A module that provides a system-server API is appended to the standard bootclasspath that is 398 // used by the system server. So, it should be able to access module-lib APIs provided by 399 // libraries on the bootclasspath. 400 canAccess: apiScopeModuleLib, 401 402 // The system-server scope is disabled by default in legacy mode. 403 // 404 // Enabling this would break existing usages. 405 legacyEnabledStatus: func(module *SdkLibrary) bool { 406 return false 407 }, 408 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 409 return &module.sdkLibraryProperties.System_server 410 }, 411 apiFilePrefix: "system-server-", 412 moduleSuffix: ".system_server", 413 sdkVersion: "system_server_current", 414 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)", 415 extraArgs: []string{ 416 "--hide-annotation", "android.annotation.Hide", 417 // com.android.* classes are okay in this interface" 418 "--hide", "InternalClasses", 419 }, 420 kind: android.SdkSystemServer, 421 }) 422 AllApiScopes = apiScopes{ 423 apiScopePublic, 424 apiScopeSystem, 425 apiScopeTest, 426 apiScopeModuleLib, 427 apiScopeSystemServer, 428 } 429 apiLibraryAdditionalProperties = map[string]string{ 430 "legacy.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution", 431 "stable.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution", 432 "conscrypt.module.platform.api": "conscrypt.module.public.api.stubs.source.api.contribution", 433 } 434) 435 436var ( 437 javaSdkLibrariesLock sync.Mutex 438) 439 440// TODO: these are big features that are currently missing 441// 1) disallowing linking to the runtime shared lib 442// 2) HTML generation 443 444func init() { 445 RegisterSdkLibraryBuildComponents(android.InitRegistrationContext) 446 447 android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) { 448 javaSdkLibraries := javaSdkLibraries(ctx.Config()) 449 sort.Strings(*javaSdkLibraries) 450 ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " ")) 451 }) 452 453 // Register sdk member types. 454 android.RegisterSdkMemberType(javaSdkLibrarySdkMemberType) 455} 456 457func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) { 458 ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory) 459 ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory) 460} 461 462// Properties associated with each api scope. 463type ApiScopeProperties struct { 464 // Indicates whether the api surface is generated. 465 // 466 // If this is set for any scope then all scopes must explicitly specify if they 467 // are enabled. This is to prevent new usages from depending on legacy behavior. 468 // 469 // Otherwise, if this is not set for any scope then the default behavior is 470 // scope specific so please refer to the scope specific property documentation. 471 Enabled *bool 472 473 // The sdk_version to use for building the stubs. 474 // 475 // If not specified then it will use an sdk_version determined as follows: 476 // 477 // 1) If the sdk_version specified on the java_sdk_library is none then this 478 // will be none. This is used for java_sdk_library instances that are used 479 // to create stubs that contribute to the core_current sdk version. 480 // 2) Otherwise, it is assumed that this library extends but does not 481 // contribute directly to a specific sdk_version and so this uses the 482 // sdk_version appropriate for the api scope. e.g. public will use 483 // sdk_version: current, system will use sdk_version: system_current, etc. 484 // 485 // This does not affect the sdk_version used for either generating the stubs source 486 // or the API file. They both have to use the same sdk_version as is used for 487 // compiling the implementation library. 488 Sdk_version *string 489 490 // Extra libs used when compiling stubs for this scope. 491 Libs []string 492 493 // Name to override the api_surface that is passed down to droidstubs. 494 Api_surface *string 495} 496 497type sdkLibraryProperties struct { 498 // List of source files that are needed to compile the API, but are not part of runtime library. 499 Api_srcs []string `android:"arch_variant"` 500 501 // Visibility for impl library module. If not specified then defaults to the 502 // visibility property. 503 Impl_library_visibility []string 504 505 // Visibility for stubs library modules. If not specified then defaults to the 506 // visibility property. 507 Stubs_library_visibility []string 508 509 // Visibility for stubs source modules. If not specified then defaults to the 510 // visibility property. 511 Stubs_source_visibility []string 512 513 // List of Java libraries that will be in the classpath when building the implementation lib 514 Impl_only_libs []string `android:"arch_variant"` 515 516 // List of Java libraries that will included in the implementation lib. 517 Impl_only_static_libs []string `android:"arch_variant"` 518 519 // List of Java libraries that will be in the classpath when building stubs 520 Stub_only_libs []string `android:"arch_variant"` 521 522 // List of Java libraries that will included in stub libraries 523 Stub_only_static_libs []string `android:"arch_variant"` 524 525 // list of package names that will be documented and publicized as API. 526 // This allows the API to be restricted to a subset of the source files provided. 527 // If this is unspecified then all the source files will be treated as being part 528 // of the API. 529 Api_packages []string 530 531 // the relative path to the directory containing the api specification files. 532 // Defaults to "api". 533 Api_dir *string 534 535 // Determines whether a runtime implementation library is built; defaults to false. 536 // 537 // If true then it also prevents the module from being used as a shared module, i.e. 538 // it is as if shared_library: false, was set. 539 Api_only *bool 540 541 // local files that are used within user customized droiddoc options. 542 Droiddoc_option_files []string 543 544 // additional droiddoc options. 545 // Available variables for substitution: 546 // 547 // $(location <label>): the path to the droiddoc_option_files with name <label> 548 Droiddoc_options []string 549 550 // is set to true, Metalava will allow framework SDK to contain annotations. 551 Annotations_enabled *bool 552 553 // a list of top-level directories containing files to merge qualifier annotations 554 // (i.e. those intended to be included in the stubs written) from. 555 Merge_annotations_dirs []string 556 557 // a list of top-level directories containing Java stub files to merge show/hide annotations from. 558 Merge_inclusion_annotations_dirs []string 559 560 // If set to true then don't create dist rules. 561 No_dist *bool 562 563 // The stem for the artifacts that are copied to the dist, if not specified 564 // then defaults to the base module name. 565 // 566 // For each scope the following artifacts are copied to the apistubs/<scope> 567 // directory in the dist. 568 // * stubs impl jar -> <dist-stem>.jar 569 // * API specification file -> api/<dist-stem>.txt 570 // * Removed API specification file -> api/<dist-stem>-removed.txt 571 // 572 // Also used to construct the name of the filegroup (created by prebuilt_apis) 573 // that references the latest released API and remove API specification files. 574 // * API specification filegroup -> <dist-stem>.api.<scope>.latest 575 // * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest 576 // * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest 577 Dist_stem *string 578 579 // The subdirectory for the artifacts that are copied to the dist directory. If not specified 580 // then defaults to "unknown". Should be set to "android" for anything that should be published 581 // in the public Android SDK. 582 Dist_group *string 583 584 // A compatibility mode that allows historical API-tracking files to not exist. 585 // Do not use. 586 Unsafe_ignore_missing_latest_api bool 587 588 // indicates whether system and test apis should be generated. 589 Generate_system_and_test_apis bool `blueprint:"mutated"` 590 591 // The properties specific to the public api scope 592 // 593 // Unless explicitly specified by using public.enabled the public api scope is 594 // enabled by default in both legacy and non-legacy mode. 595 Public ApiScopeProperties 596 597 // The properties specific to the system api scope 598 // 599 // In legacy mode the system api scope is enabled by default when sdk_version 600 // is set to something other than "none". 601 // 602 // In non-legacy mode the system api scope is disabled by default. 603 System ApiScopeProperties 604 605 // The properties specific to the test api scope 606 // 607 // In legacy mode the test api scope is enabled by default when sdk_version 608 // is set to something other than "none". 609 // 610 // In non-legacy mode the test api scope is disabled by default. 611 Test ApiScopeProperties 612 613 // The properties specific to the module-lib api scope 614 // 615 // Unless explicitly specified by using module_lib.enabled the module_lib api 616 // scope is disabled by default. 617 Module_lib ApiScopeProperties 618 619 // The properties specific to the system-server api scope 620 // 621 // Unless explicitly specified by using system_server.enabled the 622 // system_server api scope is disabled by default. 623 System_server ApiScopeProperties 624 625 // Determines if the stubs are preferred over the implementation library 626 // for linking, even when the client doesn't specify sdk_version. When this 627 // is set to true, such clients are provided with the widest API surface that 628 // this lib provides. Note however that this option doesn't affect the clients 629 // that are in the same APEX as this library. In that case, the clients are 630 // always linked with the implementation library. Default is false. 631 Default_to_stubs *bool 632 633 // Properties related to api linting. 634 Api_lint struct { 635 // Enable api linting. 636 Enabled *bool 637 638 // If API lint is enabled, this flag controls whether a set of legitimate lint errors 639 // are turned off. The default is true. 640 Legacy_errors_allowed *bool 641 } 642 643 // a list of aconfig_declarations module names that the stubs generated in this module 644 // depend on. 645 Aconfig_declarations []string 646 647 // Determines if the module generates the stubs from the api signature files 648 // instead of the source Java files. Defaults to true. 649 Build_from_text_stub *bool 650 651 // TODO: determines whether to create HTML doc or not 652 // Html_doc *bool 653} 654 655// Paths to outputs from java_sdk_library and java_sdk_library_import. 656// 657// Fields that are android.Paths are always set (during GenerateAndroidBuildActions). 658// OptionalPaths are always set by java_sdk_library but may not be set by 659// java_sdk_library_import as not all instances provide that information. 660type scopePaths struct { 661 // The path (represented as Paths for convenience when returning) to the stubs header jar. 662 // 663 // That is the jar that is created by turbine. 664 stubsHeaderPath android.Paths 665 666 // The path (represented as Paths for convenience when returning) to the stubs implementation jar. 667 // 668 // This is not the implementation jar, it still only contains stubs. 669 stubsImplPath android.Paths 670 671 // The dex jar for the stubs. 672 // 673 // This is not the implementation jar, it still only contains stubs. 674 stubsDexJarPath OptionalDexJarPath 675 676 // The exportable dex jar for the stubs. 677 // This is not the implementation jar, it still only contains stubs. 678 // Includes unflagged apis and flagged apis enabled by release configurations. 679 exportableStubsDexJarPath OptionalDexJarPath 680 681 // The API specification file, e.g. system_current.txt. 682 currentApiFilePath android.OptionalPath 683 684 // The specification of API elements removed since the last release. 685 removedApiFilePath android.OptionalPath 686 687 // The stubs source jar. 688 stubsSrcJar android.OptionalPath 689 690 // Extracted annotations. 691 annotationsZip android.OptionalPath 692 693 // The path to the latest API file. 694 latestApiPaths android.Paths 695 696 // The path to the latest removed API file. 697 latestRemovedApiPaths android.Paths 698} 699 700func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 701 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 702 paths.stubsHeaderPath = lib.HeaderJars 703 paths.stubsImplPath = lib.ImplementationJars 704 705 libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider) 706 paths.stubsDexJarPath = libDep.DexJarBuildPath 707 paths.exportableStubsDexJarPath = libDep.DexJarBuildPath 708 return nil 709 } else { 710 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 711 } 712} 713 714func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 715 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 716 paths.stubsHeaderPath = lib.HeaderJars 717 if !ctx.Config().ReleaseHiddenApiExportableStubs() { 718 paths.stubsImplPath = lib.ImplementationJars 719 } 720 721 libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider) 722 paths.stubsDexJarPath = libDep.DexJarBuildPath 723 return nil 724 } else { 725 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 726 } 727} 728 729func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 730 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 731 if ctx.Config().ReleaseHiddenApiExportableStubs() { 732 paths.stubsImplPath = lib.ImplementationJars 733 } 734 735 libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider) 736 paths.exportableStubsDexJarPath = libDep.DexJarBuildPath 737 return nil 738 } else { 739 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 740 } 741} 742 743func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, dep android.Module, 744 action func(*DroidStubsInfo, *StubsSrcInfo) error) error { 745 apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider) 746 if !ok { 747 return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs") 748 } 749 750 apiStubsSrcProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider) 751 if !ok { 752 return fmt.Errorf("expected module that provides StubsSrcInfo, e.g. droidstubs") 753 } 754 return action(&apiStubsProvider, &apiStubsSrcProvider) 755} 756 757func (paths *scopePaths) treatDepAsApiStubsSrcProvider( 758 ctx android.ModuleContext, dep android.Module, action func(provider *StubsSrcInfo) error) error { 759 if apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider); ok { 760 err := action(&apiStubsProvider) 761 if err != nil { 762 return err 763 } 764 return nil 765 } else { 766 return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs") 767 } 768} 769 770func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider *DroidStubsInfo, stubsType StubsType) error { 771 var currentApiFilePathErr, removedApiFilePathErr error 772 info, err := getStubsInfoForType(provider, stubsType) 773 if err != nil { 774 return err 775 } 776 if info.ApiFile == nil { 777 currentApiFilePathErr = fmt.Errorf("expected module that provides ApiFile") 778 } 779 if info.RemovedApiFile == nil { 780 removedApiFilePathErr = fmt.Errorf("expected module that provides RemovedApiFile") 781 } 782 combinedError := errors.Join(currentApiFilePathErr, removedApiFilePathErr) 783 784 if combinedError == nil { 785 paths.annotationsZip = android.OptionalPathForPath(info.AnnotationsZip) 786 paths.currentApiFilePath = android.OptionalPathForPath(info.ApiFile) 787 paths.removedApiFilePath = android.OptionalPathForPath(info.RemovedApiFile) 788 } 789 return combinedError 790} 791 792func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider *StubsSrcInfo, stubsType StubsType) error { 793 path, err := getStubsSrcInfoForType(provider, stubsType) 794 if err == nil { 795 paths.stubsSrcJar = android.OptionalPathForPath(path) 796 } 797 return err 798} 799 800func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error { 801 stubsType := Everything 802 if ctx.Config().ReleaseHiddenApiExportableStubs() { 803 stubsType = Exportable 804 } 805 return paths.treatDepAsApiStubsSrcProvider(ctx, dep, func(provider *StubsSrcInfo) error { 806 return paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType) 807 }) 808} 809 810func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error { 811 stubsType := Everything 812 if ctx.Config().ReleaseHiddenApiExportableStubs() { 813 stubsType = Exportable 814 } 815 return paths.treatDepAsApiStubsProvider(ctx, dep, func(apiStubsProvider *DroidStubsInfo, apiStubsSrcProvider *StubsSrcInfo) error { 816 extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(apiStubsProvider, stubsType) 817 extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(apiStubsSrcProvider, stubsType) 818 return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr) 819 }) 820} 821 822func extractOutputPaths(ctx android.ModuleContext, dep android.Module) (android.Paths, error) { 823 var paths android.Paths 824 if sourceFileProducer, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok { 825 paths = sourceFileProducer.Srcs 826 return paths, nil 827 } else { 828 return nil, fmt.Errorf("module %q does not produce source files", dep) 829 } 830} 831 832func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error { 833 outputPaths, err := extractOutputPaths(ctx, dep) 834 paths.latestApiPaths = outputPaths 835 return err 836} 837 838func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error { 839 outputPaths, err := extractOutputPaths(ctx, dep) 840 paths.latestRemovedApiPaths = outputPaths 841 return err 842} 843 844func getStubsInfoForType(info *DroidStubsInfo, stubsType StubsType) (ret *StubsInfo, err error) { 845 switch stubsType { 846 case Everything: 847 ret, err = &info.EverythingStubsInfo, nil 848 case Exportable: 849 ret, err = &info.ExportableStubsInfo, nil 850 default: 851 ret, err = nil, fmt.Errorf("stubs info not supported for the stub type %s", stubsType.String()) 852 } 853 if ret == nil && err == nil { 854 err = fmt.Errorf("stubs info is null for the stub type %s", stubsType.String()) 855 } 856 return ret, err 857} 858 859func getStubsSrcInfoForType(info *StubsSrcInfo, stubsType StubsType) (ret android.Path, err error) { 860 switch stubsType { 861 case Everything: 862 ret, err = info.EverythingStubsSrcJar, nil 863 case Exportable: 864 ret, err = info.ExportableStubsSrcJar, nil 865 default: 866 ret, err = nil, fmt.Errorf("stubs src info not supported for the stub type %s", stubsType.String()) 867 } 868 if ret == nil && err == nil { 869 err = fmt.Errorf("stubs src info is null for the stub type %s", stubsType.String()) 870 } 871 return ret, err 872} 873 874type commonToSdkLibraryAndImportProperties struct { 875 // Specifies whether this module can be used as an Android shared library; defaults 876 // to true. 877 // 878 // An Android shared library is one that can be referenced in a <uses-library> element 879 // in an AndroidManifest.xml. 880 Shared_library *bool 881 882 // Files containing information about supported java doc tags. 883 Doctag_files []string `android:"path"` 884 885 // Signals that this shared library is part of the bootclasspath starting 886 // on the version indicated in this attribute. 887 // 888 // This will make platforms at this level and above to ignore 889 // <uses-library> tags with this library name because the library is already 890 // available 891 On_bootclasspath_since *string 892 893 // Signals that this shared library was part of the bootclasspath before 894 // (but not including) the version indicated in this attribute. 895 // 896 // The system will automatically add a <uses-library> tag with this library to 897 // apps that target any SDK less than the version indicated in this attribute. 898 On_bootclasspath_before *string 899 900 // Indicates that PackageManager should ignore this shared library if the 901 // platform is below the version indicated in this attribute. 902 // 903 // This means that the device won't recognise this library as installed. 904 Min_device_sdk *string 905 906 // Indicates that PackageManager should ignore this shared library if the 907 // platform is above the version indicated in this attribute. 908 // 909 // This means that the device won't recognise this library as installed. 910 Max_device_sdk *string 911} 912 913// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that 914// embeds the commonToSdkLibraryAndImport struct. 915type commonSdkLibraryAndImportModule interface { 916 android.Module 917 918 // Returns the name of the root java_sdk_library that creates the child stub libraries 919 // This is the `name` as it appears in Android.bp, and not the name in Soong's build graph 920 // (with the prebuilt_ prefix) 921 // 922 // e.g. in the following java_sdk_library_import 923 // java_sdk_library_import { 924 // name: "framework-foo.v1", 925 // source_module_name: "framework-foo", 926 // } 927 // the values returned by 928 // 1. Name(): prebuilt_framework-foo.v1 # unique 929 // 2. BaseModuleName(): framework-foo # the source 930 // 3. RootLibraryName: framework-foo.v1 # the undecordated `name` from Android.bp 931 RootLibraryName() string 932} 933 934var _ android.ApexModule = (*SdkLibrary)(nil) 935 936func (m *SdkLibrary) RootLibraryName() string { 937 return m.BaseModuleName() 938} 939 940func (m *SdkLibraryImport) RootLibraryName() string { 941 // m.BaseModuleName refers to the source of the import 942 // use moduleBase.Name to get the name of the module as it appears in the .bp file 943 return m.ModuleBase.Name() 944} 945 946// Common code between sdk library and sdk library import 947type commonToSdkLibraryAndImport struct { 948 module commonSdkLibraryAndImportModule 949 950 scopePaths map[*apiScope]*scopePaths 951 952 commonSdkLibraryProperties commonToSdkLibraryAndImportProperties 953 954 // Paths to commonSdkLibraryProperties.Doctag_files 955 doctagPaths android.Paths 956 957 // Functionality related to this being used as a component of a java_sdk_library. 958 EmbeddableSdkLibraryComponent 959 960 // Path to the header jars of the implementation library 961 // This is non-empty only when api_only is false. 962 implLibraryHeaderJars android.Paths 963 964 // The reference to the JavaInfo provided by implementation library created by 965 // the source module. Is nil if the source module does not exist. 966 implLibraryInfo *JavaInfo 967} 968 969func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) { 970 c.module = module 971 972 module.AddProperties(&c.commonSdkLibraryProperties) 973 974 // Initialize this as an sdk library component. 975 c.initSdkLibraryComponent(module) 976} 977 978func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied() bool { 979 namePtr := proptools.StringPtr(c.module.RootLibraryName()) 980 c.sdkLibraryComponentProperties.SdkLibraryName = namePtr 981 982 // Only track this sdk library if this can be used as a shared library. 983 if c.sharedLibrary() { 984 // Use the name specified in the module definition as the owner. 985 c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr 986 } 987 988 return true 989} 990 991// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations 992// method. 993func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool { 994 // A java_sdk_library that is a shared library produces an XML file that makes the shared library 995 // usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of 996 // the APEX and so it needs a unique variation per APEX. 997 return c.sharedLibrary() 998} 999 1000func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) SdkLibraryInfo { 1001 c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files) 1002 1003 everythingStubPaths := make(map[android.SdkKind]OptionalDexJarPath) 1004 exportableStubPaths := make(map[android.SdkKind]OptionalDexJarPath) 1005 removedApiFilePaths := make(map[android.SdkKind]android.OptionalPath) 1006 for kind := android.SdkNone; kind <= android.SdkPrivate; kind += 1 { 1007 everythingStubPath := makeUnsetDexJarPath() 1008 exportableStubPath := makeUnsetDexJarPath() 1009 removedApiFilePath := android.OptionalPath{} 1010 if scopePath := c.findClosestScopePath(sdkKindToApiScope(kind)); scopePath != nil { 1011 everythingStubPath = scopePath.stubsDexJarPath 1012 exportableStubPath = scopePath.exportableStubsDexJarPath 1013 removedApiFilePath = scopePath.removedApiFilePath 1014 } 1015 everythingStubPaths[kind] = everythingStubPath 1016 exportableStubPaths[kind] = exportableStubPath 1017 removedApiFilePaths[kind] = removedApiFilePath 1018 } 1019 1020 return SdkLibraryInfo{ 1021 EverythingStubDexJarPaths: everythingStubPaths, 1022 ExportableStubDexJarPaths: exportableStubPaths, 1023 RemovedTxtFiles: removedApiFilePaths, 1024 SharedLibrary: c.sharedLibrary(), 1025 } 1026} 1027 1028// The component names for different outputs of the java_sdk_library. 1029// 1030// They are similar to the names used for the child modules it creates 1031const ( 1032 stubsSourceComponentName = "stubs.source" 1033 1034 apiTxtComponentName = "api.txt" 1035 1036 removedApiTxtComponentName = "removed-api.txt" 1037 1038 annotationsComponentName = "annotations.zip" 1039) 1040 1041func (module *commonToSdkLibraryAndImport) setOutputFiles(ctx android.ModuleContext) { 1042 if module.doctagPaths != nil { 1043 ctx.SetOutputFiles(module.doctagPaths, ".doctags") 1044 } 1045 for _, scopeName := range android.SortedKeys(scopeByName) { 1046 paths := module.findScopePaths(scopeByName[scopeName]) 1047 if paths == nil { 1048 continue 1049 } 1050 componentToOutput := map[string]android.OptionalPath{ 1051 stubsSourceComponentName: paths.stubsSrcJar, 1052 apiTxtComponentName: paths.currentApiFilePath, 1053 removedApiTxtComponentName: paths.removedApiFilePath, 1054 annotationsComponentName: paths.annotationsZip, 1055 } 1056 for _, component := range android.SortedKeys(componentToOutput) { 1057 if componentToOutput[component].Valid() { 1058 ctx.SetOutputFiles(android.Paths{componentToOutput[component].Path()}, "."+scopeName+"."+component) 1059 } 1060 } 1061 } 1062} 1063 1064func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths { 1065 if c.scopePaths == nil { 1066 c.scopePaths = make(map[*apiScope]*scopePaths) 1067 } 1068 paths := c.scopePaths[scope] 1069 if paths == nil { 1070 paths = &scopePaths{} 1071 c.scopePaths[scope] = paths 1072 } 1073 1074 return paths 1075} 1076 1077func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths { 1078 if c.scopePaths == nil { 1079 return nil 1080 } 1081 1082 return c.scopePaths[scope] 1083} 1084 1085// If this does not support the requested api scope then find the closest available 1086// scope it does support. Returns nil if no such scope is available. 1087func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths { 1088 for s := scope; s != nil; s = s.canAccess { 1089 if paths := c.findScopePaths(s); paths != nil { 1090 return paths 1091 } 1092 } 1093 1094 // This should never happen outside tests as public should be the base scope for every 1095 // scope and is enabled by default. 1096 return nil 1097} 1098 1099// sdkKindToApiScope maps from android.SdkKind to apiScope. 1100func sdkKindToApiScope(kind android.SdkKind) *apiScope { 1101 var apiScope *apiScope 1102 switch kind { 1103 case android.SdkSystem: 1104 apiScope = apiScopeSystem 1105 case android.SdkModule: 1106 apiScope = apiScopeModuleLib 1107 case android.SdkTest: 1108 apiScope = apiScopeTest 1109 case android.SdkSystemServer: 1110 apiScope = apiScopeSystemServer 1111 default: 1112 apiScope = apiScopePublic 1113 } 1114 return apiScope 1115} 1116 1117func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { 1118 componentProps := &struct { 1119 SdkLibraryName *string 1120 SdkLibraryToImplicitlyTrack *string 1121 }{} 1122 1123 namePtr := proptools.StringPtr(c.module.RootLibraryName()) 1124 componentProps.SdkLibraryName = namePtr 1125 1126 if c.sharedLibrary() { 1127 // Mark the stubs library as being components of this java_sdk_library so that 1128 // any app that includes code which depends (directly or indirectly) on the stubs 1129 // library will have the appropriate <uses-library> invocation inserted into its 1130 // manifest if necessary. 1131 componentProps.SdkLibraryToImplicitlyTrack = namePtr 1132 } 1133 1134 return componentProps 1135} 1136 1137func (c *commonToSdkLibraryAndImport) sharedLibrary() bool { 1138 return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true) 1139} 1140 1141// Check if the stub libraries should be compiled for dex 1142func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool { 1143 // Always compile the dex file files for the stub libraries if they will be used on the 1144 // bootclasspath. 1145 return !c.sharedLibrary() 1146} 1147 1148// Properties related to the use of a module as an component of a java_sdk_library. 1149type SdkLibraryComponentProperties struct { 1150 // The name of the java_sdk_library/_import module. 1151 SdkLibraryName *string `blueprint:"mutated"` 1152 1153 // The name of the java_sdk_library/_import to add to a <uses-library> entry 1154 // in the AndroidManifest.xml of any Android app that includes code that references 1155 // this module. If not set then no java_sdk_library/_import is tracked. 1156 SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` 1157} 1158 1159// Structure to be embedded in a module struct that needs to support the 1160// SdkLibraryComponentDependency interface. 1161type EmbeddableSdkLibraryComponent struct { 1162 sdkLibraryComponentProperties SdkLibraryComponentProperties 1163} 1164 1165func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) { 1166 module.AddProperties(&e.sdkLibraryComponentProperties) 1167} 1168 1169// to satisfy SdkLibraryComponentDependency 1170func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string { 1171 return e.sdkLibraryComponentProperties.SdkLibraryName 1172} 1173 1174// to satisfy SdkLibraryComponentDependency 1175func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string { 1176 // For shared libraries, this is the same as the SDK library name. If a Java library or app 1177 // depends on a component library (e.g. a stub library) it still needs to know the name of the 1178 // run-time library and the corresponding module that provides the implementation. This name is 1179 // passed to manifest_fixer (to be added to AndroidManifest.xml) and added to CLC (to be used 1180 // in dexpreopt). 1181 // 1182 // For non-shared SDK (component or not) libraries this returns `nil`, as they are not 1183 // <uses-library> and should not be added to the manifest or to CLC. 1184 return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack 1185} 1186 1187// Implemented by modules that are (or possibly could be) a component of a java_sdk_library 1188// (including the java_sdk_library) itself. 1189type SdkLibraryComponentDependency interface { 1190 UsesLibraryDependency 1191 1192 // SdkLibraryName returns the name of the java_sdk_library/_import module. 1193 SdkLibraryName() *string 1194 1195 // The name of the implementation library for the optional SDK library or nil, if there isn't one. 1196 OptionalSdkLibraryImplementation() *string 1197} 1198 1199// Make sure that all the module types that are components of java_sdk_library/_import 1200// and which can be referenced (directly or indirectly) from an android app implement 1201// the SdkLibraryComponentDependency interface. 1202var _ SdkLibraryComponentDependency = (*Library)(nil) 1203var _ SdkLibraryComponentDependency = (*Import)(nil) 1204var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) 1205var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil) 1206 1207type SdkLibraryInfo struct { 1208 // GeneratingLibs is the names of the library modules that this sdk library 1209 // generates. Note that this only includes the name of the modules that other modules can 1210 // depend on, and is not a holistic list of generated modules. 1211 GeneratingLibs []string 1212 1213 // Map of sdk kind to the dex jar for the "everything" stubs. 1214 // It is needed by the hiddenapi processing tool which processes dex files. 1215 EverythingStubDexJarPaths map[android.SdkKind]OptionalDexJarPath 1216 1217 // Map of sdk kind to the dex jar for the "exportable" stubs. 1218 // It is needed by the hiddenapi processing tool which processes dex files. 1219 ExportableStubDexJarPaths map[android.SdkKind]OptionalDexJarPath 1220 1221 // Map of sdk kind to the optional path to the removed.txt file. 1222 RemovedTxtFiles map[android.SdkKind]android.OptionalPath 1223 1224 // Whether if this can be used as a shared library. 1225 SharedLibrary bool 1226 1227 Prebuilt bool 1228} 1229 1230var SdkLibraryInfoProvider = blueprint.NewProvider[SdkLibraryInfo]() 1231 1232func getGeneratingLibs(ctx android.ModuleContext, sdkVersion android.SdkSpec, sdkLibraryModuleName string, sdkInfo SdkLibraryInfo) []string { 1233 apiLevel := sdkVersion.ApiLevel 1234 if apiLevel.IsPreview() { 1235 return sdkInfo.GeneratingLibs 1236 } 1237 1238 generatingPrebuilts := []string{} 1239 for _, apiScope := range AllApiScopes { 1240 scopePrebuiltModuleName := prebuiltApiModuleName("sdk", sdkLibraryModuleName, apiScope.name, apiLevel.String()) 1241 if ctx.OtherModuleExists(scopePrebuiltModuleName) { 1242 generatingPrebuilts = append(generatingPrebuilts, scopePrebuiltModuleName) 1243 } 1244 } 1245 return generatingPrebuilts 1246} 1247 1248type SdkLibrary struct { 1249 Library 1250 1251 sdkLibraryProperties sdkLibraryProperties 1252 1253 // Map from api scope to the scope specific property structure. 1254 scopeToProperties map[*apiScope]*ApiScopeProperties 1255 1256 commonToSdkLibraryAndImport 1257 1258 apexSystemServerDexpreoptInstalls []DexpreopterInstall 1259 apexSystemServerDexJars android.Paths 1260} 1261 1262func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool { 1263 return module.sdkLibraryProperties.Generate_system_and_test_apis 1264} 1265 1266var _ UsesLibraryDependency = (*SdkLibrary)(nil) 1267 1268// To satisfy the UsesLibraryDependency interface 1269func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { 1270 if module.implLibraryInfo != nil { 1271 return module.implLibraryInfo.DexJarFile 1272 } 1273 return makeUnsetDexJarPath() 1274} 1275 1276// To satisfy the UsesLibraryDependency interface 1277func (module *SdkLibrary) DexJarInstallPath() android.Path { 1278 if module.implLibraryInfo != nil { 1279 return module.implLibraryInfo.InstallFile 1280 } 1281 return nil 1282} 1283 1284func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes { 1285 // Check to see if any scopes have been explicitly enabled. If any have then all 1286 // must be. 1287 anyScopesExplicitlyEnabled := false 1288 for _, scope := range AllApiScopes { 1289 scopeProperties := module.scopeToProperties[scope] 1290 if scopeProperties.Enabled != nil { 1291 anyScopesExplicitlyEnabled = true 1292 break 1293 } 1294 } 1295 1296 var generatedScopes apiScopes 1297 enabledScopes := make(map[*apiScope]struct{}) 1298 for _, scope := range AllApiScopes { 1299 scopeProperties := module.scopeToProperties[scope] 1300 // If any scopes are explicitly enabled then ignore the legacy enabled status. 1301 // This is to ensure that any new usages of this module type do not rely on legacy 1302 // behaviour. 1303 defaultEnabledStatus := false 1304 if anyScopesExplicitlyEnabled { 1305 defaultEnabledStatus = scope.defaultEnabledStatus 1306 } else { 1307 defaultEnabledStatus = scope.legacyEnabledStatus(module) 1308 } 1309 enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus) 1310 if enabled { 1311 enabledScopes[scope] = struct{}{} 1312 generatedScopes = append(generatedScopes, scope) 1313 } 1314 } 1315 1316 // Now check to make sure that any scope that is extended by an enabled scope is also 1317 // enabled. 1318 for _, scope := range AllApiScopes { 1319 if _, ok := enabledScopes[scope]; ok { 1320 extends := scope.extends 1321 if extends != nil { 1322 if _, ok := enabledScopes[extends]; !ok { 1323 ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends) 1324 } 1325 } 1326 } 1327 } 1328 1329 return generatedScopes 1330} 1331 1332var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil) 1333 1334func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { 1335 CheckMinSdkVersion(ctx, &module.Library) 1336} 1337 1338func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { 1339 android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) { 1340 ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { 1341 isExternal := !android.IsDepInSameApex(ctx, module, child) 1342 if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule { 1343 if !do(ctx, parent, child, isExternal) { 1344 return false 1345 } 1346 } 1347 return !isExternal 1348 }) 1349 }) 1350} 1351 1352type sdkLibraryComponentTag struct { 1353 blueprint.BaseDependencyTag 1354 name string 1355} 1356 1357// Mark this tag so dependencies that use it are excluded from visibility enforcement. 1358func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {} 1359 1360var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"} 1361 1362func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { 1363 if dt, ok := depTag.(sdkLibraryComponentTag); ok { 1364 return dt == xmlPermissionsFileTag 1365 } 1366 return false 1367} 1368 1369var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"} 1370 1371var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{} 1372 1373func (t sdkLibraryComponentTag) InstallDepNeeded() bool { 1374 return t.name == "xml-permissions-file" || t.name == "impl-library" 1375} 1376 1377// Add the dependencies on the child modules in the component deps mutator. 1378func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 1379 for _, apiScope := range module.getGeneratedApiScopes(ctx) { 1380 // Add dependencies to the stubs library 1381 stubModuleName := module.stubsLibraryModuleName(apiScope) 1382 ctx.AddVariationDependencies(nil, apiScope.everythingStubsTag, stubModuleName) 1383 1384 exportableStubModuleName := module.exportableStubsLibraryModuleName(apiScope) 1385 ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName) 1386 1387 // Add a dependency on the stubs source in order to access both stubs source and api information. 1388 ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.droidstubsModuleName(apiScope)) 1389 1390 if module.compareAgainstLatestApi(apiScope) { 1391 // Add dependencies on the latest finalized version of the API .txt file. 1392 latestApiModuleName := module.latestApiModuleName(apiScope) 1393 ctx.AddDependency(module, apiScope.latestApiModuleTag, latestApiModuleName) 1394 1395 // Add dependencies on the latest finalized version of the remove API .txt file. 1396 latestRemovedApiModuleName := module.latestRemovedApiModuleName(apiScope) 1397 ctx.AddDependency(module, apiScope.latestRemovedApiModuleTag, latestRemovedApiModuleName) 1398 } 1399 } 1400 1401 if module.requiresRuntimeImplementationLibrary() { 1402 // Add dependency to the rule for generating the implementation library. 1403 ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName()) 1404 1405 if module.sharedLibrary() { 1406 // Add dependency to the rule for generating the xml permissions file 1407 ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName()) 1408 } 1409 } 1410} 1411 1412// Add other dependencies as normal. 1413func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { 1414 // If the module does not create an implementation library or defaults to stubs, 1415 // mark the top level sdk library as stubs module as the module will provide stubs via 1416 // "magic" when listed as a dependency in the Android.bp files. 1417 notCreateImplLib := proptools.Bool(module.sdkLibraryProperties.Api_only) 1418 preferStubs := proptools.Bool(module.sdkLibraryProperties.Default_to_stubs) 1419 module.properties.Is_stubs_module = proptools.BoolPtr(notCreateImplLib || preferStubs) 1420 1421 var missingApiModules []string 1422 for _, apiScope := range module.getGeneratedApiScopes(ctx) { 1423 if apiScope.unstable { 1424 continue 1425 } 1426 if m := module.latestApiModuleName(apiScope); !ctx.OtherModuleExists(m) { 1427 missingApiModules = append(missingApiModules, m) 1428 } 1429 if m := module.latestRemovedApiModuleName(apiScope); !ctx.OtherModuleExists(m) { 1430 missingApiModules = append(missingApiModules, m) 1431 } 1432 if m := module.latestIncompatibilitiesModuleName(apiScope); !ctx.OtherModuleExists(m) { 1433 missingApiModules = append(missingApiModules, m) 1434 } 1435 } 1436 if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api { 1437 m := module.Name() + " is missing tracking files for previously released library versions.\n" 1438 m += "You need to do one of the following:\n" 1439 m += "- Add `unsafe_ignore_missing_latest_api: true` to your blueprint (to disable compat tracking)\n" 1440 m += "- Add a set of prebuilt txt files representing the last released version of this library for compat checking.\n" 1441 m += " (the current set of API files can be used as a seed for this compatibility tracking\n" 1442 m += "\n" 1443 m += "The following filegroup modules are missing:\n " 1444 m += strings.Join(missingApiModules, "\n ") + "\n" 1445 m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these." 1446 ctx.ModuleErrorf(m) 1447 } 1448} 1449 1450func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1451 if disableSourceApexVariant(ctx) { 1452 // Prebuilts are active, do not create the installation rules for the source javalib. 1453 // Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules. 1454 // TODO (b/331665856): Implement a principled solution for this. 1455 module.HideFromMake() 1456 module.SkipInstall() 1457 } 1458 1459 module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName()) 1460 1461 module.provideHiddenAPIPropertyInfo(ctx) 1462 1463 // Collate the components exported by this module. All scope specific modules are exported but 1464 // the impl and xml component modules are not. 1465 exportedComponents := map[string]struct{}{} 1466 var implLib android.ModuleProxy 1467 // Record the paths to the header jars of the library (stubs and impl). 1468 // When this java_sdk_library is depended upon from others via "libs" property, 1469 // the recorded paths will be returned depending on the link type of the caller. 1470 ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) { 1471 tag := ctx.OtherModuleDependencyTag(to) 1472 1473 // Extract information from any of the scope specific dependencies. 1474 if scopeTag, ok := tag.(scopeDependencyTag); ok { 1475 apiScope := scopeTag.apiScope 1476 scopePaths := module.getScopePathsCreateIfNeeded(apiScope) 1477 1478 // Extract information from the dependency. The exact information extracted 1479 // is determined by the nature of the dependency which is determined by the tag. 1480 scopeTag.extractDepInfo(ctx, to, scopePaths) 1481 1482 exportedComponents[ctx.OtherModuleName(to)] = struct{}{} 1483 1484 ctx.Phony(ctx.ModuleName(), scopePaths.stubsHeaderPath...) 1485 } 1486 1487 if tag == implLibraryTag { 1488 if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { 1489 module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...) 1490 module.implLibraryInfo = dep 1491 implLib = to 1492 } 1493 } 1494 }) 1495 1496 sdkLibInfo := module.generateCommonBuildActions(ctx) 1497 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 1498 if !apexInfo.IsForPlatform() { 1499 module.hideApexVariantFromMake = true 1500 } 1501 1502 if module.implLibraryInfo != nil { 1503 if ctx.Device() { 1504 module.classesJarPaths = module.implLibraryInfo.ImplementationJars 1505 module.bootDexJarPath = module.implLibraryInfo.BootDexJarPath 1506 module.uncompressDexState = module.implLibraryInfo.UncompressDexState 1507 module.active = module.implLibraryInfo.Active 1508 } 1509 1510 module.outputFile = module.implLibraryInfo.OutputFile 1511 module.dexJarFile = makeDexJarPathFromPath(module.implLibraryInfo.DexJarFile.Path()) 1512 module.headerJarFile = module.implLibraryInfo.HeaderJars[0] 1513 module.implementationAndResourcesJar = module.implLibraryInfo.ImplementationAndResourcesJars[0] 1514 module.apexSystemServerDexpreoptInstalls = module.implLibraryInfo.DexpreopterInfo.ApexSystemServerDexpreoptInstalls 1515 module.apexSystemServerDexJars = module.implLibraryInfo.DexpreopterInfo.ApexSystemServerDexJars 1516 module.dexpreopter.configPath = module.implLibraryInfo.ConfigPath 1517 module.dexpreopter.outputProfilePathOnHost = module.implLibraryInfo.DexpreopterInfo.OutputProfilePathOnHost 1518 1519 // Properties required for Library.AndroidMkEntries 1520 module.logtagsSrcs = module.implLibraryInfo.LogtagsSrcs 1521 module.dexpreopter.builtInstalled = module.implLibraryInfo.BuiltInstalled 1522 module.jacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile 1523 module.dexer.proguardDictionary = module.implLibraryInfo.ProguardDictionary 1524 module.dexer.proguardUsageZip = module.implLibraryInfo.ProguardUsageZip 1525 module.linter.reports = module.implLibraryInfo.LinterReports 1526 1527 if lintInfo, ok := android.OtherModuleProvider(ctx, implLib, LintProvider); ok { 1528 android.SetProvider(ctx, LintProvider, lintInfo) 1529 } 1530 1531 if !module.Host() { 1532 module.hostdexInstallFile = module.implLibraryInfo.HostdexInstallFile 1533 } 1534 1535 if installFilesInfo, ok := android.OtherModuleProvider(ctx, implLib, android.InstallFilesProvider); ok { 1536 if installFilesInfo.CheckbuildTarget != nil { 1537 ctx.CheckbuildFile(installFilesInfo.CheckbuildTarget) 1538 } 1539 } 1540 } 1541 1542 // Make the set of components exported by this module available for use elsewhere. 1543 exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)} 1544 android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo) 1545 1546 // Provide additional information for inclusion in an sdk's generated .info file. 1547 additionalSdkInfo := map[string]interface{}{} 1548 additionalSdkInfo["dist_stem"] = module.distStem() 1549 baseModuleName := module.distStem() 1550 scopes := map[string]interface{}{} 1551 additionalSdkInfo["scopes"] = scopes 1552 for scope, scopePaths := range module.scopePaths { 1553 scopeInfo := map[string]interface{}{} 1554 scopes[scope.name] = scopeInfo 1555 scopeInfo["current_api"] = scope.snapshotRelativeCurrentApiTxtPath(baseModuleName) 1556 scopeInfo["removed_api"] = scope.snapshotRelativeRemovedApiTxtPath(baseModuleName) 1557 if p := scopePaths.latestApiPaths; len(p) > 0 { 1558 // The last path in the list is the one that applies to this scope, the 1559 // preceding ones, if any, are for the scope(s) that it extends. 1560 scopeInfo["latest_api"] = p[len(p)-1].String() 1561 } 1562 if p := scopePaths.latestRemovedApiPaths; len(p) > 0 { 1563 // The last path in the list is the one that applies to this scope, the 1564 // preceding ones, if any, are for the scope(s) that it extends. 1565 scopeInfo["latest_removed_api"] = p[len(p)-1].String() 1566 } 1567 } 1568 android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo}) 1569 module.setOutputFiles(ctx) 1570 1571 var generatingLibs []string 1572 for _, apiScope := range AllApiScopes { 1573 if _, ok := module.scopePaths[apiScope]; ok { 1574 generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope)) 1575 } 1576 } 1577 1578 if module.requiresRuntimeImplementationLibrary() && module.implLibraryInfo != nil { 1579 generatingLibs = append(generatingLibs, module.implLibraryModuleName()) 1580 setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo) 1581 } 1582 1583 javaInfo := &JavaInfo{ 1584 JacocoReportClassesFile: module.jacocoReportClassesFile, 1585 } 1586 setExtraJavaInfo(ctx, ctx.Module(), javaInfo) 1587 android.SetProvider(ctx, JavaInfoProvider, javaInfo) 1588 1589 sdkLibInfo.GeneratingLibs = generatingLibs 1590 sdkLibInfo.Prebuilt = false 1591 android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo) 1592} 1593 1594func setOutputFilesFromJavaInfo(ctx android.ModuleContext, info *JavaInfo) { 1595 ctx.SetOutputFiles(append(android.PathsIfNonNil(info.OutputFile), info.ExtraOutputFiles...), "") 1596 ctx.SetOutputFiles(android.PathsIfNonNil(info.OutputFile), android.DefaultDistTag) 1597 ctx.SetOutputFiles(info.ImplementationAndResourcesJars, ".jar") 1598 ctx.SetOutputFiles(info.HeaderJars, ".hjar") 1599 if info.ProguardDictionary.Valid() { 1600 ctx.SetOutputFiles(android.Paths{info.ProguardDictionary.Path()}, ".proguard_map") 1601 } 1602 ctx.SetOutputFiles(info.GeneratedSrcjars, ".generated_srcjars") 1603} 1604 1605func (module *SdkLibrary) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall { 1606 return module.apexSystemServerDexpreoptInstalls 1607} 1608 1609func (module *SdkLibrary) ApexSystemServerDexJars() android.Paths { 1610 return module.apexSystemServerDexJars 1611} 1612 1613func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { 1614 if !module.requiresRuntimeImplementationLibrary() { 1615 return nil 1616 } 1617 entriesList := module.Library.AndroidMkEntries() 1618 entries := &entriesList[0] 1619 entries.Required = append(entries.Required, module.implLibraryModuleName()) 1620 if module.sharedLibrary() { 1621 entries.Required = append(entries.Required, module.xmlPermissionsModuleName()) 1622 } 1623 return entriesList 1624} 1625 1626// The dist path of the stub artifacts 1627func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string { 1628 return path.Join("apistubs", module.distGroup(), apiScope.name) 1629} 1630 1631// Get the sdk version for use when compiling the stubs library. 1632func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string { 1633 scopeProperties := module.scopeToProperties[apiScope] 1634 if scopeProperties.Sdk_version != nil { 1635 return proptools.String(scopeProperties.Sdk_version) 1636 } 1637 1638 sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library)) 1639 if sdkDep.hasStandardLibs() { 1640 // If building against a standard sdk then use the sdk version appropriate for the scope. 1641 return apiScope.sdkVersion 1642 } else { 1643 // Otherwise, use no system module. 1644 return "none" 1645 } 1646} 1647 1648func (module *SdkLibrary) distStem() string { 1649 return proptools.StringDefault(module.sdkLibraryProperties.Dist_stem, module.BaseModuleName()) 1650} 1651 1652// distGroup returns the subdirectory of the dist path of the stub artifacts. 1653func (module *SdkLibrary) distGroup() string { 1654 return proptools.StringDefault(module.sdkLibraryProperties.Dist_group, "unknown") 1655} 1656 1657func latestPrebuiltApiModuleName(name string, apiScope *apiScope) string { 1658 return PrebuiltApiModuleName(name, apiScope.name, "latest") 1659} 1660 1661func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string { 1662 return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest") 1663} 1664 1665func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string { 1666 return ":" + module.latestApiModuleName(apiScope) 1667} 1668 1669func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string { 1670 return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope) 1671} 1672 1673func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string { 1674 return ":" + module.latestRemovedApiModuleName(apiScope) 1675} 1676 1677func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string { 1678 return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope) 1679} 1680 1681func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string { 1682 return ":" + module.latestIncompatibilitiesModuleName(apiScope) 1683} 1684 1685func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope) string { 1686 return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope) 1687} 1688 1689// The listed modules' stubs contents do not match the corresponding txt files, 1690// but require additional api contributions to generate the full stubs. 1691// This method returns the name of the additional api contribution module 1692// for corresponding sdk_library modules. 1693func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string { 1694 if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok { 1695 return val 1696 } 1697 return "" 1698} 1699 1700func childModuleVisibility(childVisibility []string) []string { 1701 if childVisibility == nil { 1702 // No child visibility set. The child will use the visibility of the sdk_library. 1703 return nil 1704 } 1705 1706 // Prepend an override to ignore the sdk_library's visibility, and rely on the child visibility. 1707 var visibility []string 1708 visibility = append(visibility, "//visibility:override") 1709 visibility = append(visibility, childVisibility...) 1710 return visibility 1711} 1712 1713func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool { 1714 return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) 1715} 1716 1717// Implements android.ApexModule 1718func (m *SdkLibrary) GetDepInSameApexChecker() android.DepInSameApexChecker { 1719 return SdkLibraryDepInSameApexChecker{} 1720} 1721 1722type SdkLibraryDepInSameApexChecker struct { 1723 android.BaseDepInSameApexChecker 1724} 1725 1726func (m SdkLibraryDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { 1727 if tag == xmlPermissionsFileTag { 1728 return true 1729 } 1730 if tag == implLibraryTag { 1731 return true 1732 } 1733 return depIsInSameApex(tag) 1734} 1735 1736// Implements android.ApexModule 1737func (module *SdkLibrary) UniqueApexVariations() bool { 1738 return module.uniqueApexVariations() 1739} 1740 1741func (module *SdkLibrary) ModuleBuildFromTextStubs() bool { 1742 return proptools.BoolDefault(module.sdkLibraryProperties.Build_from_text_stub, true) 1743} 1744 1745var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries") 1746 1747func javaSdkLibraries(config android.Config) *[]string { 1748 return config.Once(javaSdkLibrariesKey, func() interface{} { 1749 return &[]string{} 1750 }).(*[]string) 1751} 1752 1753func (module *SdkLibrary) getApiDir() string { 1754 return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api") 1755} 1756 1757// For a java_sdk_library module, create internal modules for stubs, docs, 1758// runtime libs and xml file. If requested, the stubs and docs are created twice 1759// once for public API level and once for system API level 1760func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) { 1761 if len(module.properties.Srcs) == 0 { 1762 mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs") 1763 return 1764 } 1765 1766 // If this builds against standard libraries (i.e. is not part of the core libraries) 1767 // then assume it provides both system and test apis. 1768 sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library)) 1769 hasSystemAndTestApis := sdkDep.hasStandardLibs() 1770 module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis 1771 1772 missingCurrentApi := false 1773 1774 generatedScopes := module.getGeneratedApiScopes(mctx) 1775 1776 apiDir := module.getApiDir() 1777 for _, scope := range generatedScopes { 1778 for _, api := range []string{"current.txt", "removed.txt"} { 1779 path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api) 1780 p := android.ExistentPathForSource(mctx, path) 1781 if !p.Valid() { 1782 if mctx.Config().AllowMissingDependencies() { 1783 mctx.AddMissingDependencies([]string{path}) 1784 } else { 1785 mctx.ModuleErrorf("Current api file %#v doesn't exist", path) 1786 missingCurrentApi = true 1787 } 1788 } 1789 } 1790 } 1791 1792 if missingCurrentApi { 1793 script := "build/soong/scripts/gen-java-current-api-files.sh" 1794 p := android.ExistentPathForSource(mctx, script) 1795 1796 if !p.Valid() { 1797 panic(fmt.Sprintf("script file %s doesn't exist", script)) 1798 } 1799 1800 mctx.ModuleErrorf("One or more current api files are missing. "+ 1801 "You can update them by:\n"+ 1802 "%s %q %s && m update-api", 1803 script, filepath.Join(mctx.ModuleDir(), apiDir), 1804 strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " ")) 1805 return 1806 } 1807 1808 for _, scope := range generatedScopes { 1809 // Use the stubs source name for legacy reasons. 1810 module.createDroidstubs(mctx, scope, module.droidstubsModuleName(scope), scope.droidstubsArgs) 1811 1812 module.createFromSourceStubsLibrary(mctx, scope) 1813 module.createExportableFromSourceStubsLibrary(mctx, scope) 1814 1815 if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() { 1816 module.createApiLibrary(mctx, scope) 1817 } 1818 module.createTopLevelStubsLibrary(mctx, scope) 1819 module.createTopLevelExportableStubsLibrary(mctx, scope) 1820 } 1821 1822 if module.requiresRuntimeImplementationLibrary() { 1823 // Create child module to create an implementation library. 1824 // 1825 // This temporarily creates a second implementation library that can be explicitly 1826 // referenced. 1827 // 1828 // TODO(b/156618935) - update comment once only one implementation library is created. 1829 module.createImplLibrary(mctx) 1830 1831 // Only create an XML permissions file that declares the library as being usable 1832 // as a shared library if required. 1833 if module.sharedLibrary() { 1834 module.createXmlFile(mctx) 1835 } 1836 1837 // record java_sdk_library modules so that they are exported to make 1838 javaSdkLibraries := javaSdkLibraries(mctx.Config()) 1839 javaSdkLibrariesLock.Lock() 1840 defer javaSdkLibrariesLock.Unlock() 1841 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName()) 1842 } 1843 1844 // Add the impl_only_libs and impl_only_static_libs *after* we're done using them in submodules. 1845 module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...) 1846 module.properties.Static_libs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs) 1847} 1848 1849func (module *SdkLibrary) InitSdkLibraryProperties() { 1850 module.addHostAndDeviceProperties() 1851 module.AddProperties(&module.sdkLibraryProperties) 1852 1853 module.initSdkLibraryComponent(module) 1854 1855 module.properties.Installable = proptools.BoolPtr(true) 1856 module.deviceProperties.IsSDKLibrary = true 1857} 1858 1859func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool { 1860 return !proptools.Bool(module.sdkLibraryProperties.Api_only) 1861} 1862 1863func moduleStubLinkType(j *Module) (stub bool, ret sdkLinkType) { 1864 kind := android.ToSdkKind(proptools.String(j.properties.Stub_contributing_api)) 1865 switch kind { 1866 case android.SdkPublic: 1867 return true, javaSdk 1868 case android.SdkSystem: 1869 return true, javaSystem 1870 case android.SdkModule: 1871 return true, javaModule 1872 case android.SdkTest: 1873 return true, javaSystem 1874 case android.SdkSystemServer: 1875 return true, javaSystemServer 1876 // Default value for all modules other than java_sdk_library-generated stub submodules 1877 case android.SdkInvalid: 1878 return false, javaPlatform 1879 default: 1880 panic(fmt.Sprintf("stub_contributing_api set as an unsupported sdk kind %s", kind.String())) 1881 } 1882} 1883 1884// java_sdk_library is a special Java library that provides optional platform APIs to apps. 1885// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients 1886// are linked against to, 2) droiddoc module that internally generates API stubs source files, 1887// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding 1888// the runtime lib to the classpath at runtime if requested via <uses-library>. 1889func SdkLibraryFactory() android.Module { 1890 module := &SdkLibrary{} 1891 1892 // Initialize information common between source and prebuilt. 1893 module.initCommon(module) 1894 1895 module.InitSdkLibraryProperties() 1896 android.InitApexModule(module) 1897 InitJavaModule(module, android.HostAndDeviceSupported) 1898 1899 // Initialize the map from scope to scope specific properties. 1900 scopeToProperties := make(map[*apiScope]*ApiScopeProperties) 1901 for _, scope := range AllApiScopes { 1902 scopeToProperties[scope] = scope.scopeSpecificProperties(module) 1903 } 1904 module.scopeToProperties = scopeToProperties 1905 1906 // Add the properties containing visibility rules so that they are checked. 1907 android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility) 1908 android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility) 1909 android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) 1910 1911 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { 1912 // If no implementation is required then it cannot be used as a shared library 1913 // either. 1914 if !module.requiresRuntimeImplementationLibrary() { 1915 // If shared_library has been explicitly set to true then it is incompatible 1916 // with api_only: true. 1917 if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) { 1918 ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true") 1919 } 1920 // Set shared_library: false. 1921 module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false) 1922 } 1923 1924 if module.initCommonAfterDefaultsApplied() { 1925 module.CreateInternalModules(ctx) 1926 } 1927 }) 1928 return module 1929} 1930 1931// 1932// SDK library prebuilts 1933// 1934 1935// Properties associated with each api scope. 1936type sdkLibraryScopeProperties struct { 1937 Jars []string `android:"path"` 1938 1939 Sdk_version *string 1940 1941 // List of shared java libs that this module has dependencies to 1942 Libs []string 1943 1944 // The stubs source. 1945 Stub_srcs []string `android:"path"` 1946 1947 // The current.txt 1948 Current_api *string `android:"path"` 1949 1950 // The removed.txt 1951 Removed_api *string `android:"path"` 1952 1953 // Annotation zip 1954 Annotations *string `android:"path"` 1955} 1956 1957type sdkLibraryImportProperties struct { 1958 // List of shared java libs, common to all scopes, that this module has 1959 // dependencies to 1960 Libs []string 1961 1962 // If set to true, compile dex files for the stubs. Defaults to false. 1963 Compile_dex *bool 1964 1965 // If not empty, classes are restricted to the specified packages and their sub-packages. 1966 Permitted_packages []string 1967 1968 // Name of the source soong module that gets shadowed by this prebuilt 1969 // If unspecified, follows the naming convention that the source module of 1970 // the prebuilt is Name() without "prebuilt_" prefix 1971 Source_module_name *string 1972} 1973 1974type SdkLibraryImport struct { 1975 android.ModuleBase 1976 android.DefaultableModuleBase 1977 prebuilt android.Prebuilt 1978 android.ApexModuleBase 1979 1980 hiddenAPI 1981 dexpreopter 1982 1983 properties sdkLibraryImportProperties 1984 1985 // Map from api scope to the scope specific property structure. 1986 scopeProperties map[*apiScope]*sdkLibraryScopeProperties 1987 1988 commonToSdkLibraryAndImport 1989 1990 // Build path to the dex implementation jar obtained from the prebuilt_apex, if any. 1991 dexJarFile OptionalDexJarPath 1992 dexJarFileErr error 1993 1994 // Expected install file path of the source module(sdk_library) 1995 // or dex implementation jar obtained from the prebuilt_apex, if any. 1996 installFile android.Path 1997} 1998 1999// The type of a structure that contains a field of type sdkLibraryScopeProperties 2000// for each apiscope in allApiScopes, e.g. something like: 2001// 2002// struct { 2003// Public sdkLibraryScopeProperties 2004// System sdkLibraryScopeProperties 2005// ... 2006// } 2007var allScopeStructType = createAllScopePropertiesStructType() 2008 2009// Dynamically create a structure type for each apiscope in allApiScopes. 2010func createAllScopePropertiesStructType() reflect.Type { 2011 var fields []reflect.StructField 2012 for _, apiScope := range AllApiScopes { 2013 field := reflect.StructField{ 2014 Name: apiScope.fieldName, 2015 Type: reflect.TypeOf(sdkLibraryScopeProperties{}), 2016 } 2017 fields = append(fields, field) 2018 } 2019 2020 return reflect.StructOf(fields) 2021} 2022 2023// Create an instance of the scope specific structure type and return a map 2024// from apiscope to a pointer to each scope specific field. 2025func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProperties) { 2026 allScopePropertiesPtr := reflect.New(allScopeStructType) 2027 allScopePropertiesStruct := allScopePropertiesPtr.Elem() 2028 scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties) 2029 2030 for _, apiScope := range AllApiScopes { 2031 field := allScopePropertiesStruct.FieldByName(apiScope.fieldName) 2032 scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties) 2033 } 2034 2035 return allScopePropertiesPtr.Interface(), scopeProperties 2036} 2037 2038// java_sdk_library_import imports a prebuilt java_sdk_library. 2039func sdkLibraryImportFactory() android.Module { 2040 module := &SdkLibraryImport{} 2041 2042 allScopeProperties, scopeToProperties := createPropertiesInstance() 2043 module.scopeProperties = scopeToProperties 2044 module.AddProperties(&module.properties, allScopeProperties, &module.importDexpreoptProperties) 2045 2046 // Initialize information common between source and prebuilt. 2047 module.initCommon(module) 2048 2049 android.InitPrebuiltModule(module, &[]string{""}) 2050 android.InitApexModule(module) 2051 InitJavaModule(module, android.HostAndDeviceSupported) 2052 2053 module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { 2054 if module.initCommonAfterDefaultsApplied() { 2055 module.createInternalModules(mctx) 2056 } 2057 }) 2058 return module 2059} 2060 2061var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil) 2062 2063func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string { 2064 return module.properties.Permitted_packages 2065} 2066 2067func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt { 2068 return &module.prebuilt 2069} 2070 2071func (module *SdkLibraryImport) Name() string { 2072 return module.prebuilt.Name(module.ModuleBase.Name()) 2073} 2074 2075func (module *SdkLibraryImport) BaseModuleName() string { 2076 return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name()) 2077} 2078 2079func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) { 2080 2081 // If the build is configured to use prebuilts then force this to be preferred. 2082 if mctx.Config().AlwaysUsePrebuiltSdks() { 2083 module.prebuilt.ForcePrefer() 2084 } 2085 2086 for apiScope, scopeProperties := range module.scopeProperties { 2087 if len(scopeProperties.Jars) == 0 { 2088 continue 2089 } 2090 2091 module.createJavaImportForStubs(mctx, apiScope, scopeProperties) 2092 2093 if len(scopeProperties.Stub_srcs) > 0 { 2094 module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties) 2095 } 2096 2097 if scopeProperties.Current_api != nil { 2098 module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties) 2099 } 2100 } 2101 2102 javaSdkLibraries := javaSdkLibraries(mctx.Config()) 2103 javaSdkLibrariesLock.Lock() 2104 defer javaSdkLibrariesLock.Unlock() 2105 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName()) 2106} 2107 2108// Add the dependencies on the child module in the component deps mutator so that it 2109// creates references to the prebuilt and not the source modules. 2110func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 2111 for apiScope, scopeProperties := range module.scopeProperties { 2112 if len(scopeProperties.Jars) == 0 { 2113 continue 2114 } 2115 2116 // Add dependencies to the prebuilt stubs library 2117 ctx.AddVariationDependencies(nil, apiScope.prebuiltStubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope))) 2118 2119 if len(scopeProperties.Stub_srcs) > 0 { 2120 // Add dependencies to the prebuilt stubs source library 2121 ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.droidstubsModuleName(apiScope))) 2122 } 2123 } 2124} 2125 2126// Add other dependencies as normal. 2127func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { 2128 2129 implName := module.implLibraryModuleName() 2130 if ctx.OtherModuleExists(implName) { 2131 ctx.AddVariationDependencies(nil, implLibraryTag, implName) 2132 2133 xmlPermissionsModuleName := module.xmlPermissionsModuleName() 2134 if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) { 2135 // Add dependency to the rule for generating the xml permissions file 2136 ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName) 2137 } 2138 } 2139} 2140 2141var _ android.ApexModule = (*SdkLibraryImport)(nil) 2142 2143// Implements android.ApexModule 2144func (m *SdkLibraryImport) GetDepInSameApexChecker() android.DepInSameApexChecker { 2145 return SdkLibraryImportDepIsInSameApexChecker{} 2146} 2147 2148type SdkLibraryImportDepIsInSameApexChecker struct { 2149 android.BaseDepInSameApexChecker 2150} 2151 2152func (m SdkLibraryImportDepIsInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { 2153 if tag == xmlPermissionsFileTag { 2154 return true 2155 } 2156 2157 // None of the other dependencies of the java_sdk_library_import are in the same apex 2158 // as the one that references this module. 2159 return false 2160} 2161 2162// Implements android.ApexModule 2163func (m *SdkLibraryImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { 2164 return android.MinApiLevel 2165} 2166 2167func (module *SdkLibraryImport) UniqueApexVariations() bool { 2168 return module.uniqueApexVariations() 2169} 2170 2171// MinSdkVersion - Implements hiddenAPIModule 2172func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2173 return android.NoneApiLevel 2174} 2175 2176var _ hiddenAPIModule = (*SdkLibraryImport)(nil) 2177 2178func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { 2179 // Assume that source module(sdk_library) is installed in /<sdk_library partition>/framework 2180 module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar") 2181 2182 // Record the paths to the prebuilt stubs library and stubs source. 2183 ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) { 2184 tag := ctx.OtherModuleDependencyTag(to) 2185 2186 // Extract information from any of the scope specific dependencies. 2187 if scopeTag, ok := tag.(scopeDependencyTag); ok { 2188 apiScope := scopeTag.apiScope 2189 scopePaths := module.getScopePathsCreateIfNeeded(apiScope) 2190 2191 // Extract information from the dependency. The exact information extracted 2192 // is determined by the nature of the dependency which is determined by the tag. 2193 scopeTag.extractDepInfo(ctx, to, scopePaths) 2194 } else if tag == implLibraryTag { 2195 if implInfo, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { 2196 module.implLibraryInfo = implInfo 2197 } else { 2198 ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to) 2199 } 2200 } 2201 }) 2202 sdkLibInfo := module.generateCommonBuildActions(ctx) 2203 2204 // Populate the scope paths with information from the properties. 2205 for apiScope, scopeProperties := range module.scopeProperties { 2206 if len(scopeProperties.Jars) == 0 { 2207 continue 2208 } 2209 2210 paths := module.getScopePathsCreateIfNeeded(apiScope) 2211 paths.annotationsZip = android.OptionalPathForModuleSrc(ctx, scopeProperties.Annotations) 2212 paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api) 2213 paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api) 2214 } 2215 2216 if ctx.Device() { 2217 // Shared libraries deapexed from prebuilt apexes are no longer supported. 2218 // Set the dexJarBuildPath to a fake path. 2219 // This allows soong analysis pass, but will be an error during ninja execution if there are 2220 // any rdeps. 2221 ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 2222 if ai.ForPrebuiltApex { 2223 module.dexJarFile = makeDexJarPathFromPath(android.PathForModuleInstall(ctx, "intentionally_no_longer_supported")) 2224 module.initHiddenAPI(ctx, module.dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) 2225 } 2226 } 2227 2228 var generatingLibs []string 2229 for _, apiScope := range AllApiScopes { 2230 if scopeProperties, ok := module.scopeProperties[apiScope]; ok { 2231 if len(scopeProperties.Jars) == 0 { 2232 continue 2233 } 2234 generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope)) 2235 } 2236 } 2237 2238 module.setOutputFiles(ctx) 2239 if module.implLibraryInfo != nil { 2240 generatingLibs = append(generatingLibs, module.implLibraryModuleName()) 2241 setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo) 2242 } 2243 2244 javaInfo := &JavaInfo{} 2245 if module.implLibraryInfo != nil { 2246 javaInfo.JacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile 2247 } 2248 2249 setExtraJavaInfo(ctx, ctx.Module(), javaInfo) 2250 android.SetProvider(ctx, JavaInfoProvider, javaInfo) 2251 2252 sdkLibInfo.GeneratingLibs = generatingLibs 2253 sdkLibInfo.Prebuilt = true 2254 android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo) 2255} 2256 2257var _ UsesLibraryDependency = (*SdkLibraryImport)(nil) 2258 2259// to satisfy UsesLibraryDependency interface 2260func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { 2261 // The dex implementation jar extracted from the .apex file should be used in preference to the 2262 // source. 2263 if module.dexJarFileErr != nil { 2264 ctx.ModuleErrorf(module.dexJarFileErr.Error()) 2265 } 2266 if module.dexJarFile.IsSet() { 2267 return module.dexJarFile 2268 } 2269 if module.implLibraryInfo == nil { 2270 return makeUnsetDexJarPath() 2271 } else { 2272 return module.implLibraryInfo.DexJarFile 2273 } 2274} 2275 2276// to satisfy UsesLibraryDependency interface 2277func (module *SdkLibraryImport) DexJarInstallPath() android.Path { 2278 return module.installFile 2279} 2280 2281// to satisfy UsesLibraryDependency interface 2282func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { 2283 return nil 2284} 2285 2286// to satisfy apex.javaDependency interface 2287func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path { 2288 if module.implLibraryInfo == nil { 2289 return nil 2290 } else { 2291 return module.implLibraryInfo.JacocoReportClassesFile 2292 } 2293} 2294 2295// to satisfy apex.javaDependency interface 2296func (module *SdkLibraryImport) Stem() string { 2297 return module.BaseModuleName() 2298} 2299 2300var _ ApexDependency = (*SdkLibraryImport)(nil) 2301 2302// to satisfy java.ApexDependency interface 2303func (module *SdkLibraryImport) HeaderJars() android.Paths { 2304 if module.implLibraryInfo == nil { 2305 return nil 2306 } else { 2307 return module.implLibraryInfo.HeaderJars 2308 } 2309} 2310 2311// to satisfy java.ApexDependency interface 2312func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths { 2313 if module.implLibraryInfo == nil { 2314 return nil 2315 } else { 2316 return module.implLibraryInfo.ImplementationAndResourcesJars 2317 } 2318} 2319 2320// to satisfy java.DexpreopterInterface interface 2321func (module *SdkLibraryImport) IsInstallable() bool { 2322 return true 2323} 2324 2325var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil) 2326 2327func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { 2328 name := module.BaseModuleName() 2329 return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter) 2330} 2331 2332func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool { 2333 return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided) 2334} 2335 2336type sdkLibrarySdkMemberType struct { 2337 android.SdkMemberTypeBase 2338} 2339 2340func (s *sdkLibrarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) { 2341 ctx.AddVariationDependencies(nil, dependencyTag, names...) 2342} 2343 2344func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool { 2345 _, ok := module.(*SdkLibrary) 2346 return ok 2347} 2348 2349func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { 2350 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_sdk_library_import") 2351} 2352 2353func (s *sdkLibrarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { 2354 return &sdkLibrarySdkMemberProperties{} 2355} 2356 2357var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{ 2358 android.SdkMemberTypeBase{ 2359 PropertyName: "java_sdk_libs", 2360 SupportsSdk: true, 2361 }, 2362} 2363 2364type sdkLibrarySdkMemberProperties struct { 2365 android.SdkMemberPropertiesBase 2366 2367 // Stem name for files in the sdk snapshot. 2368 // 2369 // This is used to construct the path names of various sdk library files in the sdk snapshot to 2370 // make sure that they match the finalized versions of those files in prebuilts/sdk. 2371 // 2372 // This property is marked as keep so that it will be kept in all instances of this struct, will 2373 // not be cleared but will be copied to common structs. That is needed because this field is used 2374 // to construct many file names for other parts of this struct and so it needs to be present in 2375 // all structs. If it was not marked as keep then it would be cleared in some structs and so would 2376 // be unavailable for generating file names if there were other properties that were still set. 2377 Stem string `sdk:"keep"` 2378 2379 // Scope to per scope properties. 2380 Scopes map[*apiScope]*scopeProperties 2381 2382 // The Java stubs source files. 2383 Stub_srcs []string 2384 2385 // The naming scheme. 2386 Naming_scheme *string 2387 2388 // True if the java_sdk_library_import is for a shared library, false 2389 // otherwise. 2390 Shared_library *bool 2391 2392 // True if the stub imports should produce dex jars. 2393 Compile_dex *bool 2394 2395 // The paths to the doctag files to add to the prebuilt. 2396 Doctag_paths android.Paths 2397 2398 Permitted_packages []string 2399 2400 // Signals that this shared library is part of the bootclasspath starting 2401 // on the version indicated in this attribute. 2402 // 2403 // This will make platforms at this level and above to ignore 2404 // <uses-library> tags with this library name because the library is already 2405 // available 2406 On_bootclasspath_since *string 2407 2408 // Signals that this shared library was part of the bootclasspath before 2409 // (but not including) the version indicated in this attribute. 2410 // 2411 // The system will automatically add a <uses-library> tag with this library to 2412 // apps that target any SDK less than the version indicated in this attribute. 2413 On_bootclasspath_before *string 2414 2415 // Indicates that PackageManager should ignore this shared library if the 2416 // platform is below the version indicated in this attribute. 2417 // 2418 // This means that the device won't recognise this library as installed. 2419 Min_device_sdk *string 2420 2421 // Indicates that PackageManager should ignore this shared library if the 2422 // platform is above the version indicated in this attribute. 2423 // 2424 // This means that the device won't recognise this library as installed. 2425 Max_device_sdk *string 2426 2427 DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"` 2428} 2429 2430type scopeProperties struct { 2431 Jars android.Paths 2432 StubsSrcJar android.Path 2433 CurrentApiFile android.Path 2434 RemovedApiFile android.Path 2435 AnnotationsZip android.Path `supported_build_releases:"Tiramisu+"` 2436 SdkVersion string 2437} 2438 2439func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { 2440 sdk := variant.(*SdkLibrary) 2441 2442 // Copy the stem name for files in the sdk snapshot. 2443 s.Stem = sdk.distStem() 2444 2445 s.Scopes = make(map[*apiScope]*scopeProperties) 2446 for _, apiScope := range AllApiScopes { 2447 paths := sdk.findScopePaths(apiScope) 2448 if paths == nil { 2449 continue 2450 } 2451 2452 jars := paths.stubsImplPath 2453 if len(jars) > 0 { 2454 properties := scopeProperties{} 2455 properties.Jars = jars 2456 properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope) 2457 properties.StubsSrcJar = paths.stubsSrcJar.Path() 2458 if paths.currentApiFilePath.Valid() { 2459 properties.CurrentApiFile = paths.currentApiFilePath.Path() 2460 } 2461 if paths.removedApiFilePath.Valid() { 2462 properties.RemovedApiFile = paths.removedApiFilePath.Path() 2463 } 2464 // The annotations zip is only available for modules that set annotations_enabled: true. 2465 if paths.annotationsZip.Valid() { 2466 properties.AnnotationsZip = paths.annotationsZip.Path() 2467 } 2468 s.Scopes[apiScope] = &properties 2469 } 2470 } 2471 2472 s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary()) 2473 s.Compile_dex = sdk.dexProperties.Compile_dex 2474 s.Doctag_paths = sdk.doctagPaths 2475 s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars() 2476 s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since 2477 s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before 2478 s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk 2479 s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk 2480 2481 if sdk.implLibraryInfo != nil && sdk.implLibraryInfo.ProfileGuided { 2482 s.DexPreoptProfileGuided = proptools.BoolPtr(true) 2483 } 2484} 2485 2486func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { 2487 if s.Naming_scheme != nil { 2488 propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme)) 2489 } 2490 if s.Shared_library != nil { 2491 propertySet.AddProperty("shared_library", *s.Shared_library) 2492 } 2493 if s.Compile_dex != nil { 2494 propertySet.AddProperty("compile_dex", *s.Compile_dex) 2495 } 2496 if len(s.Permitted_packages) > 0 { 2497 propertySet.AddProperty("permitted_packages", s.Permitted_packages) 2498 } 2499 dexPreoptSet := propertySet.AddPropertySet("dex_preopt") 2500 if s.DexPreoptProfileGuided != nil { 2501 dexPreoptSet.AddProperty("profile_guided", proptools.Bool(s.DexPreoptProfileGuided)) 2502 } 2503 2504 stem := s.Stem 2505 2506 for _, apiScope := range AllApiScopes { 2507 if properties, ok := s.Scopes[apiScope]; ok { 2508 scopeSet := propertySet.AddPropertySet(apiScope.propertyName) 2509 2510 scopeDir := apiScope.snapshotRelativeDir() 2511 2512 var jars []string 2513 for _, p := range properties.Jars { 2514 dest := filepath.Join(scopeDir, stem+"-stubs.jar") 2515 ctx.SnapshotBuilder().CopyToSnapshot(p, dest) 2516 jars = append(jars, dest) 2517 } 2518 scopeSet.AddProperty("jars", jars) 2519 2520 if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") { 2521 // Copy the stubs source jar into the snapshot zip as is. 2522 srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar") 2523 ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath) 2524 scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath}) 2525 } else { 2526 // Merge the stubs source jar into the snapshot zip so that when it is unpacked 2527 // the source files are also unpacked. 2528 snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources") 2529 ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir) 2530 scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir}) 2531 } 2532 2533 if properties.CurrentApiFile != nil { 2534 currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem) 2535 ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath) 2536 scopeSet.AddProperty("current_api", currentApiSnapshotPath) 2537 } 2538 2539 if properties.RemovedApiFile != nil { 2540 removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem) 2541 ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath) 2542 scopeSet.AddProperty("removed_api", removedApiSnapshotPath) 2543 } 2544 2545 if properties.AnnotationsZip != nil { 2546 annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip") 2547 ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath) 2548 scopeSet.AddProperty("annotations", annotationsSnapshotPath) 2549 } 2550 2551 if properties.SdkVersion != "" { 2552 scopeSet.AddProperty("sdk_version", properties.SdkVersion) 2553 } 2554 } 2555 } 2556 2557 if len(s.Doctag_paths) > 0 { 2558 dests := []string{} 2559 for _, p := range s.Doctag_paths { 2560 dest := filepath.Join("doctags", p.Rel()) 2561 ctx.SnapshotBuilder().CopyToSnapshot(p, dest) 2562 dests = append(dests, dest) 2563 } 2564 propertySet.AddProperty("doctag_files", dests) 2565 } 2566} 2567