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 "regexp" 24 "sort" 25 "strings" 26 "sync" 27 28 "github.com/google/blueprint" 29 "github.com/google/blueprint/proptools" 30 31 "android/soong/android" 32 "android/soong/dexpreopt" 33 "android/soong/etc" 34) 35 36const ( 37 sdkXmlFileSuffix = ".xml" 38) 39 40// A tag to associated a dependency with a specific api scope. 41type scopeDependencyTag struct { 42 blueprint.BaseDependencyTag 43 name string 44 apiScope *apiScope 45 46 // Function for extracting appropriate path information from the dependency. 47 depInfoExtractor func(paths *scopePaths, ctx android.ModuleContext, dep android.Module) error 48} 49 50// Extract tag specific information from the dependency. 51func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) { 52 err := tag.depInfoExtractor(paths, ctx, dep) 53 if err != nil { 54 ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error()) 55 } 56} 57 58var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil) 59 60func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool { 61 return false 62} 63 64// Provides information about an api scope, e.g. public, system, test. 65type apiScope struct { 66 // The name of the api scope, e.g. public, system, test 67 name string 68 69 // The api scope that this scope extends. 70 // 71 // This organizes the scopes into an extension hierarchy. 72 // 73 // If set this means that the API provided by this scope includes the API provided by the scope 74 // set in this field. 75 extends *apiScope 76 77 // The next api scope that a library that uses this scope can access. 78 // 79 // This organizes the scopes into an access hierarchy. 80 // 81 // If set this means that a library that can access this API can also access the API provided by 82 // the scope set in this field. 83 // 84 // A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of 85 // every java_sdk_library that it depends on. If the library does not provide an API for <scope> 86 // then it will traverse up this access hierarchy to find an API that it does provide. 87 // 88 // If this is not set then it defaults to the scope set in extends. 89 canAccess *apiScope 90 91 // The legacy enabled status for a specific scope can be dependent on other 92 // properties that have been specified on the library so it is provided by 93 // a function that can determine the status by examining those properties. 94 legacyEnabledStatus func(module *SdkLibrary) bool 95 96 // The default enabled status for non-legacy behavior, which is triggered by 97 // explicitly enabling at least one api scope. 98 defaultEnabledStatus bool 99 100 // Gets a pointer to the scope specific properties. 101 scopeSpecificProperties func(module *SdkLibrary) *ApiScopeProperties 102 103 // The name of the field in the dynamically created structure. 104 fieldName string 105 106 // The name of the property in the java_sdk_library_import 107 propertyName string 108 109 // The tag to use to depend on the prebuilt stubs library module 110 prebuiltStubsTag scopeDependencyTag 111 112 // The tag to use to depend on the everything stubs library module. 113 everythingStubsTag scopeDependencyTag 114 115 // The tag to use to depend on the exportable stubs library module. 116 exportableStubsTag scopeDependencyTag 117 118 // The tag to use to depend on the stubs source module (if separate from the API module). 119 stubsSourceTag scopeDependencyTag 120 121 // The tag to use to depend on the API file generating module (if separate from the stubs source module). 122 apiFileTag scopeDependencyTag 123 124 // The tag to use to depend on the stubs source and API module. 125 stubsSourceAndApiTag scopeDependencyTag 126 127 // The tag to use to depend on the module that provides the latest version of the API .txt file. 128 latestApiModuleTag scopeDependencyTag 129 130 // The tag to use to depend on the module that provides the latest version of the API removed.txt 131 // file. 132 latestRemovedApiModuleTag scopeDependencyTag 133 134 // The scope specific prefix to add to the api file base of "current.txt" or "removed.txt". 135 apiFilePrefix string 136 137 // The scope specific suffix to add to the sdk library module name to construct a scope specific 138 // module name. 139 moduleSuffix string 140 141 // SDK version that the stubs library is built against. Note that this is always 142 // *current. Older stubs library built with a numbered SDK version is created from 143 // the prebuilt jar. 144 sdkVersion string 145 146 // The annotation that identifies this API level, empty for the public API scope. 147 annotation string 148 149 // Extra arguments to pass to droidstubs for this scope. 150 // 151 // This is not used directly but is used to construct the droidstubsArgs. 152 extraArgs []string 153 154 // The args that must be passed to droidstubs to generate the API and stubs source 155 // for this scope, constructed dynamically by initApiScope(). 156 // 157 // The API only includes the additional members that this scope adds over the scope 158 // that it extends. 159 // 160 // The stubs source must include the definitions of everything that is in this 161 // api scope and all the scopes that this one extends. 162 droidstubsArgs []string 163 164 // Whether the api scope can be treated as unstable, and should skip compat checks. 165 unstable bool 166 167 // Represents the SDK kind of this scope. 168 kind android.SdkKind 169} 170 171// Initialize a scope, creating and adding appropriate dependency tags 172func initApiScope(scope *apiScope) *apiScope { 173 name := scope.name 174 scopeByName[name] = scope 175 allScopeNames = append(allScopeNames, name) 176 scope.propertyName = strings.ReplaceAll(name, "-", "_") 177 scope.fieldName = proptools.FieldNameForProperty(scope.propertyName) 178 scope.prebuiltStubsTag = scopeDependencyTag{ 179 name: name + "-stubs", 180 apiScope: scope, 181 depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency, 182 } 183 scope.everythingStubsTag = scopeDependencyTag{ 184 name: name + "-stubs-everything", 185 apiScope: scope, 186 depInfoExtractor: (*scopePaths).extractEverythingStubsLibraryInfoFromDependency, 187 } 188 scope.exportableStubsTag = scopeDependencyTag{ 189 name: name + "-stubs-exportable", 190 apiScope: scope, 191 depInfoExtractor: (*scopePaths).extractExportableStubsLibraryInfoFromDependency, 192 } 193 scope.stubsSourceTag = scopeDependencyTag{ 194 name: name + "-stubs-source", 195 apiScope: scope, 196 depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep, 197 } 198 scope.apiFileTag = scopeDependencyTag{ 199 name: name + "-api", 200 apiScope: scope, 201 depInfoExtractor: (*scopePaths).extractApiInfoFromDep, 202 } 203 scope.stubsSourceAndApiTag = scopeDependencyTag{ 204 name: name + "-stubs-source-and-api", 205 apiScope: scope, 206 depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider, 207 } 208 scope.latestApiModuleTag = scopeDependencyTag{ 209 name: name + "-latest-api", 210 apiScope: scope, 211 depInfoExtractor: (*scopePaths).extractLatestApiPath, 212 } 213 scope.latestRemovedApiModuleTag = scopeDependencyTag{ 214 name: name + "-latest-removed-api", 215 apiScope: scope, 216 depInfoExtractor: (*scopePaths).extractLatestRemovedApiPath, 217 } 218 219 // To get the args needed to generate the stubs source append all the args from 220 // this scope and all the scopes it extends as each set of args adds additional 221 // members to the stubs. 222 var scopeSpecificArgs []string 223 if scope.annotation != "" { 224 scopeSpecificArgs = []string{"--show-annotation", scope.annotation} 225 } 226 for s := scope; s != nil; s = s.extends { 227 scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...) 228 229 // Ensure that the generated stubs includes all the API elements from the API scope 230 // that this scope extends. 231 if s != scope && s.annotation != "" { 232 scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation) 233 } 234 } 235 236 // By default, a library that can access a scope can also access the scope it extends. 237 if scope.canAccess == nil { 238 scope.canAccess = scope.extends 239 } 240 241 // Escape any special characters in the arguments. This is needed because droidstubs 242 // passes these directly to the shell command. 243 scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs) 244 245 return scope 246} 247 248func (scope *apiScope) stubsLibraryModuleNameSuffix() string { 249 return ".stubs" + scope.moduleSuffix 250} 251 252func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string { 253 return ".stubs.exportable" + scope.moduleSuffix 254} 255 256func (scope *apiScope) apiLibraryModuleName(baseName string) string { 257 return scope.stubsLibraryModuleName(baseName) + ".from-text" 258} 259 260func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string { 261 return scope.stubsLibraryModuleName(baseName) + ".from-source" 262} 263 264func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string { 265 return scope.exportableStubsLibraryModuleName(baseName) + ".from-source" 266} 267 268func (scope *apiScope) stubsLibraryModuleName(baseName string) string { 269 return baseName + scope.stubsLibraryModuleNameSuffix() 270} 271 272func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string { 273 return baseName + scope.exportableStubsLibraryModuleNameSuffix() 274} 275 276func (scope *apiScope) stubsSourceModuleName(baseName string) string { 277 return baseName + ".stubs.source" + scope.moduleSuffix 278} 279 280func (scope *apiScope) apiModuleName(baseName string) string { 281 return baseName + ".api" + scope.moduleSuffix 282} 283 284func (scope *apiScope) String() string { 285 return scope.name 286} 287 288// snapshotRelativeDir returns the snapshot directory into which the files related to scopes will 289// be stored. 290func (scope *apiScope) snapshotRelativeDir() string { 291 return filepath.Join("sdk_library", scope.name) 292} 293 294// snapshotRelativeCurrentApiTxtPath returns the snapshot path to the API .txt file for the named 295// library. 296func (scope *apiScope) snapshotRelativeCurrentApiTxtPath(name string) string { 297 return filepath.Join(scope.snapshotRelativeDir(), name+".txt") 298} 299 300// snapshotRelativeRemovedApiTxtPath returns the snapshot path to the removed API .txt file for the 301// named library. 302func (scope *apiScope) snapshotRelativeRemovedApiTxtPath(name string) string { 303 return filepath.Join(scope.snapshotRelativeDir(), name+"-removed.txt") 304} 305 306type apiScopes []*apiScope 307 308func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string { 309 var list []string 310 for _, scope := range scopes { 311 list = append(list, accessor(scope)) 312 } 313 return list 314} 315 316// Method that maps the apiScopes properties to the index of each apiScopes elements. 317// apiScopes property to be used as the key can be specified with the input accessor. 318// Only a string property of apiScope can be used as the key of the map. 319func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int { 320 ret := make(map[string]int) 321 for i, scope := range scopes { 322 ret[accessor(scope)] = i 323 } 324 return ret 325} 326 327func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) string { 328 for _, scope := range scopes { 329 if strings.HasSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) { 330 return strings.TrimSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) + 331 scope.stubsLibraryModuleNameSuffix() 332 } 333 } 334 return name 335} 336 337var ( 338 scopeByName = make(map[string]*apiScope) 339 allScopeNames []string 340 apiScopePublic = initApiScope(&apiScope{ 341 name: "public", 342 343 // Public scope is enabled by default for both legacy and non-legacy modes. 344 legacyEnabledStatus: func(module *SdkLibrary) bool { 345 return true 346 }, 347 defaultEnabledStatus: true, 348 349 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 350 return &module.sdkLibraryProperties.Public 351 }, 352 sdkVersion: "current", 353 kind: android.SdkPublic, 354 }) 355 apiScopeSystem = initApiScope(&apiScope{ 356 name: "system", 357 extends: apiScopePublic, 358 legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault, 359 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 360 return &module.sdkLibraryProperties.System 361 }, 362 apiFilePrefix: "system-", 363 moduleSuffix: ".system", 364 sdkVersion: "system_current", 365 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)", 366 kind: android.SdkSystem, 367 }) 368 apiScopeTest = initApiScope(&apiScope{ 369 name: "test", 370 extends: apiScopeSystem, 371 legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault, 372 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 373 return &module.sdkLibraryProperties.Test 374 }, 375 apiFilePrefix: "test-", 376 moduleSuffix: ".test", 377 sdkVersion: "test_current", 378 annotation: "android.annotation.TestApi", 379 unstable: true, 380 kind: android.SdkTest, 381 }) 382 apiScopeModuleLib = initApiScope(&apiScope{ 383 name: "module-lib", 384 extends: apiScopeSystem, 385 // The module-lib scope is disabled by default in legacy mode. 386 // 387 // Enabling this would break existing usages. 388 legacyEnabledStatus: func(module *SdkLibrary) bool { 389 return false 390 }, 391 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 392 return &module.sdkLibraryProperties.Module_lib 393 }, 394 apiFilePrefix: "module-lib-", 395 moduleSuffix: ".module_lib", 396 sdkVersion: "module_current", 397 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)", 398 kind: android.SdkModule, 399 }) 400 apiScopeSystemServer = initApiScope(&apiScope{ 401 name: "system-server", 402 extends: apiScopePublic, 403 404 // The system-server scope can access the module-lib scope. 405 // 406 // A module that provides a system-server API is appended to the standard bootclasspath that is 407 // used by the system server. So, it should be able to access module-lib APIs provided by 408 // libraries on the bootclasspath. 409 canAccess: apiScopeModuleLib, 410 411 // The system-server scope is disabled by default in legacy mode. 412 // 413 // Enabling this would break existing usages. 414 legacyEnabledStatus: func(module *SdkLibrary) bool { 415 return false 416 }, 417 scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { 418 return &module.sdkLibraryProperties.System_server 419 }, 420 apiFilePrefix: "system-server-", 421 moduleSuffix: ".system_server", 422 sdkVersion: "system_server_current", 423 annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)", 424 extraArgs: []string{ 425 "--hide-annotation", "android.annotation.Hide", 426 // com.android.* classes are okay in this interface" 427 "--hide", "InternalClasses", 428 }, 429 kind: android.SdkSystemServer, 430 }) 431 AllApiScopes = apiScopes{ 432 apiScopePublic, 433 apiScopeSystem, 434 apiScopeTest, 435 apiScopeModuleLib, 436 apiScopeSystemServer, 437 } 438 apiLibraryAdditionalProperties = map[string]struct { 439 FullApiSurfaceStubLib string 440 AdditionalApiContribution string 441 }{ 442 "legacy.i18n.module.platform.api": { 443 FullApiSurfaceStubLib: "legacy.core.platform.api.stubs", 444 AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution", 445 }, 446 "stable.i18n.module.platform.api": { 447 FullApiSurfaceStubLib: "stable.core.platform.api.stubs", 448 AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution", 449 }, 450 "conscrypt.module.platform.api": { 451 FullApiSurfaceStubLib: "stable.core.platform.api.stubs", 452 AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution", 453 }, 454 } 455) 456 457var ( 458 javaSdkLibrariesLock sync.Mutex 459) 460 461// TODO: these are big features that are currently missing 462// 1) disallowing linking to the runtime shared lib 463// 2) HTML generation 464 465func init() { 466 RegisterSdkLibraryBuildComponents(android.InitRegistrationContext) 467 468 android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) { 469 javaSdkLibraries := javaSdkLibraries(ctx.Config()) 470 sort.Strings(*javaSdkLibraries) 471 ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " ")) 472 }) 473 474 // Register sdk member types. 475 android.RegisterSdkMemberType(javaSdkLibrarySdkMemberType) 476} 477 478func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) { 479 ctx.RegisterModuleType("java_sdk_library", SdkLibraryFactory) 480 ctx.RegisterModuleType("java_sdk_library_import", sdkLibraryImportFactory) 481} 482 483// Properties associated with each api scope. 484type ApiScopeProperties struct { 485 // Indicates whether the api surface is generated. 486 // 487 // If this is set for any scope then all scopes must explicitly specify if they 488 // are enabled. This is to prevent new usages from depending on legacy behavior. 489 // 490 // Otherwise, if this is not set for any scope then the default behavior is 491 // scope specific so please refer to the scope specific property documentation. 492 Enabled *bool 493 494 // The sdk_version to use for building the stubs. 495 // 496 // If not specified then it will use an sdk_version determined as follows: 497 // 498 // 1) If the sdk_version specified on the java_sdk_library is none then this 499 // will be none. This is used for java_sdk_library instances that are used 500 // to create stubs that contribute to the core_current sdk version. 501 // 2) Otherwise, it is assumed that this library extends but does not 502 // contribute directly to a specific sdk_version and so this uses the 503 // sdk_version appropriate for the api scope. e.g. public will use 504 // sdk_version: current, system will use sdk_version: system_current, etc. 505 // 506 // This does not affect the sdk_version used for either generating the stubs source 507 // or the API file. They both have to use the same sdk_version as is used for 508 // compiling the implementation library. 509 Sdk_version *string 510 511 // Extra libs used when compiling stubs for this scope. 512 Libs []string 513} 514 515type sdkLibraryProperties struct { 516 // List of source files that are needed to compile the API, but are not part of runtime library. 517 Api_srcs []string `android:"arch_variant"` 518 519 // Visibility for impl library module. If not specified then defaults to the 520 // visibility property. 521 Impl_library_visibility []string 522 523 // Visibility for stubs library modules. If not specified then defaults to the 524 // visibility property. 525 Stubs_library_visibility []string 526 527 // Visibility for stubs source modules. If not specified then defaults to the 528 // visibility property. 529 Stubs_source_visibility []string 530 531 // List of Java libraries that will be in the classpath when building the implementation lib 532 Impl_only_libs []string `android:"arch_variant"` 533 534 // List of Java libraries that will included in the implementation lib. 535 Impl_only_static_libs []string `android:"arch_variant"` 536 537 // List of Java libraries that will be in the classpath when building stubs 538 Stub_only_libs []string `android:"arch_variant"` 539 540 // List of Java libraries that will included in stub libraries 541 Stub_only_static_libs []string `android:"arch_variant"` 542 543 // list of package names that will be documented and publicized as API. 544 // This allows the API to be restricted to a subset of the source files provided. 545 // If this is unspecified then all the source files will be treated as being part 546 // of the API. 547 Api_packages []string 548 549 // list of package names that must be hidden from the API 550 Hidden_api_packages []string 551 552 // the relative path to the directory containing the api specification files. 553 // Defaults to "api". 554 Api_dir *string 555 556 // Determines whether a runtime implementation library is built; defaults to false. 557 // 558 // If true then it also prevents the module from being used as a shared module, i.e. 559 // it is as if shared_library: false, was set. 560 Api_only *bool 561 562 // local files that are used within user customized droiddoc options. 563 Droiddoc_option_files []string 564 565 // additional droiddoc options. 566 // Available variables for substitution: 567 // 568 // $(location <label>): the path to the droiddoc_option_files with name <label> 569 Droiddoc_options []string 570 571 // is set to true, Metalava will allow framework SDK to contain annotations. 572 Annotations_enabled *bool 573 574 // a list of top-level directories containing files to merge qualifier annotations 575 // (i.e. those intended to be included in the stubs written) from. 576 Merge_annotations_dirs []string 577 578 // a list of top-level directories containing Java stub files to merge show/hide annotations from. 579 Merge_inclusion_annotations_dirs []string 580 581 // If set to true then don't create dist rules. 582 No_dist *bool 583 584 // The stem for the artifacts that are copied to the dist, if not specified 585 // then defaults to the base module name. 586 // 587 // For each scope the following artifacts are copied to the apistubs/<scope> 588 // directory in the dist. 589 // * stubs impl jar -> <dist-stem>.jar 590 // * API specification file -> api/<dist-stem>.txt 591 // * Removed API specification file -> api/<dist-stem>-removed.txt 592 // 593 // Also used to construct the name of the filegroup (created by prebuilt_apis) 594 // that references the latest released API and remove API specification files. 595 // * API specification filegroup -> <dist-stem>.api.<scope>.latest 596 // * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest 597 // * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest 598 Dist_stem *string 599 600 // The subdirectory for the artifacts that are copied to the dist directory. If not specified 601 // then defaults to "unknown". Should be set to "android" for anything that should be published 602 // in the public Android SDK. 603 Dist_group *string 604 605 // A compatibility mode that allows historical API-tracking files to not exist. 606 // Do not use. 607 Unsafe_ignore_missing_latest_api bool 608 609 // indicates whether system and test apis should be generated. 610 Generate_system_and_test_apis bool `blueprint:"mutated"` 611 612 // The properties specific to the public api scope 613 // 614 // Unless explicitly specified by using public.enabled the public api scope is 615 // enabled by default in both legacy and non-legacy mode. 616 Public ApiScopeProperties 617 618 // The properties specific to the system api scope 619 // 620 // In legacy mode the system api scope is enabled by default when sdk_version 621 // is set to something other than "none". 622 // 623 // In non-legacy mode the system api scope is disabled by default. 624 System ApiScopeProperties 625 626 // The properties specific to the test api scope 627 // 628 // In legacy mode the test api scope is enabled by default when sdk_version 629 // is set to something other than "none". 630 // 631 // In non-legacy mode the test api scope is disabled by default. 632 Test ApiScopeProperties 633 634 // The properties specific to the module-lib api scope 635 // 636 // Unless explicitly specified by using module_lib.enabled the module_lib api 637 // scope is disabled by default. 638 Module_lib ApiScopeProperties 639 640 // The properties specific to the system-server api scope 641 // 642 // Unless explicitly specified by using system_server.enabled the 643 // system_server api scope is disabled by default. 644 System_server ApiScopeProperties 645 646 // Determines if the stubs are preferred over the implementation library 647 // for linking, even when the client doesn't specify sdk_version. When this 648 // is set to true, such clients are provided with the widest API surface that 649 // this lib provides. Note however that this option doesn't affect the clients 650 // that are in the same APEX as this library. In that case, the clients are 651 // always linked with the implementation library. Default is false. 652 Default_to_stubs *bool 653 654 // Properties related to api linting. 655 Api_lint struct { 656 // Enable api linting. 657 Enabled *bool 658 659 // If API lint is enabled, this flag controls whether a set of legitimate lint errors 660 // are turned off. The default is true. 661 Legacy_errors_allowed *bool 662 } 663 664 // Determines if the module contributes to any api surfaces. 665 // This property should be set to true only if the module is listed under 666 // frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp. 667 // Otherwise, this property should be set to false. 668 // Defaults to false. 669 Contribute_to_android_api *bool 670 671 // a list of aconfig_declarations module names that the stubs generated in this module 672 // depend on. 673 Aconfig_declarations []string 674 675 // TODO: determines whether to create HTML doc or not 676 // Html_doc *bool 677} 678 679// Paths to outputs from java_sdk_library and java_sdk_library_import. 680// 681// Fields that are android.Paths are always set (during GenerateAndroidBuildActions). 682// OptionalPaths are always set by java_sdk_library but may not be set by 683// java_sdk_library_import as not all instances provide that information. 684type scopePaths struct { 685 // The path (represented as Paths for convenience when returning) to the stubs header jar. 686 // 687 // That is the jar that is created by turbine. 688 stubsHeaderPath android.Paths 689 690 // The path (represented as Paths for convenience when returning) to the stubs implementation jar. 691 // 692 // This is not the implementation jar, it still only contains stubs. 693 stubsImplPath android.Paths 694 695 // The dex jar for the stubs. 696 // 697 // This is not the implementation jar, it still only contains stubs. 698 stubsDexJarPath OptionalDexJarPath 699 700 // The exportable dex jar for the stubs. 701 // This is not the implementation jar, it still only contains stubs. 702 // Includes unflagged apis and flagged apis enabled by release configurations. 703 exportableStubsDexJarPath OptionalDexJarPath 704 705 // The API specification file, e.g. system_current.txt. 706 currentApiFilePath android.OptionalPath 707 708 // The specification of API elements removed since the last release. 709 removedApiFilePath android.OptionalPath 710 711 // The stubs source jar. 712 stubsSrcJar android.OptionalPath 713 714 // Extracted annotations. 715 annotationsZip android.OptionalPath 716 717 // The path to the latest API file. 718 latestApiPaths android.Paths 719 720 // The path to the latest removed API file. 721 latestRemovedApiPaths android.Paths 722} 723 724func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 725 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 726 paths.stubsHeaderPath = lib.HeaderJars 727 paths.stubsImplPath = lib.ImplementationJars 728 729 libDep := dep.(UsesLibraryDependency) 730 paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx) 731 paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx) 732 return nil 733 } else { 734 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 735 } 736} 737 738func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 739 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 740 paths.stubsHeaderPath = lib.HeaderJars 741 if !ctx.Config().ReleaseHiddenApiExportableStubs() { 742 paths.stubsImplPath = lib.ImplementationJars 743 } 744 745 libDep := dep.(UsesLibraryDependency) 746 paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx) 747 return nil 748 } else { 749 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 750 } 751} 752 753func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { 754 if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { 755 if ctx.Config().ReleaseHiddenApiExportableStubs() { 756 paths.stubsImplPath = lib.ImplementationJars 757 } 758 759 libDep := dep.(UsesLibraryDependency) 760 paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx) 761 return nil 762 } else { 763 return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") 764 } 765} 766 767func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider) error) error { 768 if apiStubsProvider, ok := dep.(ApiStubsProvider); ok { 769 err := action(apiStubsProvider) 770 if err != nil { 771 return err 772 } 773 return nil 774 } else { 775 return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs") 776 } 777} 778 779func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error { 780 if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok { 781 err := action(apiStubsProvider) 782 if err != nil { 783 return err 784 } 785 return nil 786 } else { 787 return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs") 788 } 789} 790 791func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider, stubsType StubsType) error { 792 var annotationsZip, currentApiFilePath, removedApiFilePath android.Path 793 annotationsZip, annotationsZipErr := provider.AnnotationsZip(stubsType) 794 currentApiFilePath, currentApiFilePathErr := provider.ApiFilePath(stubsType) 795 removedApiFilePath, removedApiFilePathErr := provider.RemovedApiFilePath(stubsType) 796 797 combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr) 798 799 if combinedError == nil { 800 paths.annotationsZip = android.OptionalPathForPath(annotationsZip) 801 paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath) 802 paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath) 803 } 804 return combinedError 805} 806 807func (paths *scopePaths) extractApiInfoFromDep(ctx android.ModuleContext, dep android.Module) error { 808 return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error { 809 return paths.extractApiInfoFromApiStubsProvider(provider, Everything) 810 }) 811} 812 813func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error { 814 stubsSrcJar, err := provider.StubsSrcJar(stubsType) 815 if err == nil { 816 paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar) 817 } 818 return err 819} 820 821func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error { 822 return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error { 823 return paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything) 824 }) 825} 826 827func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error { 828 if ctx.Config().ReleaseHiddenApiExportableStubs() { 829 return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error { 830 extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Exportable) 831 extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Exportable) 832 return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr) 833 }) 834 } 835 return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error { 836 extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Everything) 837 extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything) 838 return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr) 839 }) 840} 841 842func extractOutputPaths(dep android.Module) (android.Paths, error) { 843 var paths android.Paths 844 if sourceFileProducer, ok := dep.(android.SourceFileProducer); ok { 845 paths = sourceFileProducer.Srcs() 846 return paths, nil 847 } else { 848 return nil, fmt.Errorf("module %q does not produce source files", dep) 849 } 850} 851 852func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error { 853 outputPaths, err := extractOutputPaths(dep) 854 paths.latestApiPaths = outputPaths 855 return err 856} 857 858func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error { 859 outputPaths, err := extractOutputPaths(dep) 860 paths.latestRemovedApiPaths = outputPaths 861 return err 862} 863 864type commonToSdkLibraryAndImportProperties struct { 865 // The naming scheme to use for the components that this module creates. 866 // 867 // If not specified then it defaults to "default". 868 // 869 // This is a temporary mechanism to simplify conversion from separate modules for each 870 // component that follow a different naming pattern to the default one. 871 // 872 // TODO(b/155480189) - Remove once naming inconsistencies have been resolved. 873 Naming_scheme *string 874 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 934func (m *SdkLibrary) RootLibraryName() string { 935 return m.BaseModuleName() 936} 937 938func (m *SdkLibraryImport) RootLibraryName() string { 939 // m.BaseModuleName refers to the source of the import 940 // use moduleBase.Name to get the name of the module as it appears in the .bp file 941 return m.ModuleBase.Name() 942} 943 944// Common code between sdk library and sdk library import 945type commonToSdkLibraryAndImport struct { 946 module commonSdkLibraryAndImportModule 947 948 scopePaths map[*apiScope]*scopePaths 949 950 namingScheme sdkLibraryComponentNamingScheme 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 implementation library created by the source module. 965 // Is nil if the source module does not exist. 966 implLibraryModule *Library 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(ctx android.DefaultableHookContext) bool { 979 schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default") 980 switch schemeProperty { 981 case "default": 982 c.namingScheme = &defaultNamingScheme{} 983 default: 984 ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty) 985 return false 986 } 987 988 namePtr := proptools.StringPtr(c.module.RootLibraryName()) 989 c.sdkLibraryComponentProperties.SdkLibraryName = namePtr 990 991 // Only track this sdk library if this can be used as a shared library. 992 if c.sharedLibrary() { 993 // Use the name specified in the module definition as the owner. 994 c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr 995 } 996 997 return true 998} 999 1000// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations 1001// method. 1002func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool { 1003 // A java_sdk_library that is a shared library produces an XML file that makes the shared library 1004 // usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of 1005 // the APEX and so it needs a unique variation per APEX. 1006 return c.sharedLibrary() 1007} 1008 1009func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) { 1010 c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files) 1011} 1012 1013func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library { 1014 return c.implLibraryModule 1015} 1016 1017// Module name of the runtime implementation library 1018func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string { 1019 return c.module.RootLibraryName() + ".impl" 1020} 1021 1022// Module name of the XML file for the lib 1023func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string { 1024 return c.module.RootLibraryName() + sdkXmlFileSuffix 1025} 1026 1027// Name of the java_library module that compiles the stubs source. 1028func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string { 1029 baseName := c.module.RootLibraryName() 1030 return c.namingScheme.stubsLibraryModuleName(apiScope, baseName) 1031} 1032 1033// Name of the java_library module that compiles the exportable stubs source. 1034func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string { 1035 baseName := c.module.RootLibraryName() 1036 return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName) 1037} 1038 1039// Name of the droidstubs module that generates the stubs source and may also 1040// generate/check the API. 1041func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string { 1042 baseName := c.module.RootLibraryName() 1043 return c.namingScheme.stubsSourceModuleName(apiScope, baseName) 1044} 1045 1046// Name of the java_api_library module that generates the from-text stubs source 1047// and compiles to a jar file. 1048func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string { 1049 baseName := c.module.RootLibraryName() 1050 return c.namingScheme.apiLibraryModuleName(apiScope, baseName) 1051} 1052 1053// Name of the java_library module that compiles the stubs 1054// generated from source Java files. 1055func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string { 1056 baseName := c.module.RootLibraryName() 1057 return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName) 1058} 1059 1060// Name of the java_library module that compiles the exportable stubs 1061// generated from source Java files. 1062func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string { 1063 baseName := c.module.RootLibraryName() 1064 return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName) 1065} 1066 1067// The component names for different outputs of the java_sdk_library. 1068// 1069// They are similar to the names used for the child modules it creates 1070const ( 1071 stubsSourceComponentName = "stubs.source" 1072 1073 apiTxtComponentName = "api.txt" 1074 1075 removedApiTxtComponentName = "removed-api.txt" 1076 1077 annotationsComponentName = "annotations.zip" 1078) 1079 1080// A regular expression to match tags that reference a specific stubs component. 1081// 1082// It will only match if given a valid scope and a valid component. It is verfy strict 1083// to ensure it does not accidentally match a similar looking tag that should be processed 1084// by the embedded Library. 1085var tagSplitter = func() *regexp.Regexp { 1086 // Given a list of literal string items returns a regular expression that will 1087 // match any one of the items. 1088 choice := func(items ...string) string { 1089 return `\Q` + strings.Join(items, `\E|\Q`) + `\E` 1090 } 1091 1092 // Regular expression to match one of the scopes. 1093 scopesRegexp := choice(allScopeNames...) 1094 1095 // Regular expression to match one of the components. 1096 componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName, annotationsComponentName) 1097 1098 // Regular expression to match any combination of one scope and one component. 1099 return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp)) 1100}() 1101 1102// For OutputFileProducer interface 1103// 1104// .<scope>.<component name>, for all ComponentNames (for example: .public.removed-api.txt) 1105func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) { 1106 if groups := tagSplitter.FindStringSubmatch(tag); groups != nil { 1107 scopeName := groups[1] 1108 component := groups[2] 1109 1110 if scope, ok := scopeByName[scopeName]; ok { 1111 paths := c.findScopePaths(scope) 1112 if paths == nil { 1113 return nil, fmt.Errorf("%q does not provide api scope %s", c.module.RootLibraryName(), scopeName) 1114 } 1115 1116 switch component { 1117 case stubsSourceComponentName: 1118 if paths.stubsSrcJar.Valid() { 1119 return android.Paths{paths.stubsSrcJar.Path()}, nil 1120 } 1121 1122 case apiTxtComponentName: 1123 if paths.currentApiFilePath.Valid() { 1124 return android.Paths{paths.currentApiFilePath.Path()}, nil 1125 } 1126 1127 case removedApiTxtComponentName: 1128 if paths.removedApiFilePath.Valid() { 1129 return android.Paths{paths.removedApiFilePath.Path()}, nil 1130 } 1131 1132 case annotationsComponentName: 1133 if paths.annotationsZip.Valid() { 1134 return android.Paths{paths.annotationsZip.Path()}, nil 1135 } 1136 } 1137 1138 return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName) 1139 } else { 1140 return nil, fmt.Errorf("unknown scope %s in %s", scope, tag) 1141 } 1142 1143 } else { 1144 switch tag { 1145 case ".doctags": 1146 if c.doctagPaths != nil { 1147 return c.doctagPaths, nil 1148 } else { 1149 return nil, fmt.Errorf("no doctag_files specified on %s", c.module.RootLibraryName()) 1150 } 1151 } 1152 return nil, nil 1153 } 1154} 1155 1156func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths { 1157 if c.scopePaths == nil { 1158 c.scopePaths = make(map[*apiScope]*scopePaths) 1159 } 1160 paths := c.scopePaths[scope] 1161 if paths == nil { 1162 paths = &scopePaths{} 1163 c.scopePaths[scope] = paths 1164 } 1165 1166 return paths 1167} 1168 1169func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths { 1170 if c.scopePaths == nil { 1171 return nil 1172 } 1173 1174 return c.scopePaths[scope] 1175} 1176 1177// If this does not support the requested api scope then find the closest available 1178// scope it does support. Returns nil if no such scope is available. 1179func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths { 1180 for s := scope; s != nil; s = s.canAccess { 1181 if paths := c.findScopePaths(s); paths != nil { 1182 return paths 1183 } 1184 } 1185 1186 // This should never happen outside tests as public should be the base scope for every 1187 // scope and is enabled by default. 1188 return nil 1189} 1190 1191func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { 1192 1193 // If a specific numeric version has been requested then use prebuilt versions of the sdk. 1194 if !sdkVersion.ApiLevel.IsPreview() { 1195 return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion) 1196 } 1197 1198 paths := c.selectScopePaths(ctx, sdkVersion.Kind) 1199 if paths == nil { 1200 return nil 1201 } 1202 1203 return paths.stubsHeaderPath 1204} 1205 1206// selectScopePaths returns the *scopePaths appropriate for the specific kind. 1207// 1208// If the module does not support the specific kind then it will return the *scopePaths for the 1209// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then 1210// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not. 1211func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths { 1212 apiScope := sdkKindToApiScope(kind) 1213 1214 paths := c.findClosestScopePath(apiScope) 1215 if paths == nil { 1216 var scopes []string 1217 for _, s := range AllApiScopes { 1218 if c.findScopePaths(s) != nil { 1219 scopes = append(scopes, s.name) 1220 } 1221 } 1222 ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.RootLibraryName(), scopes) 1223 return nil 1224 } 1225 1226 return paths 1227} 1228 1229// sdkKindToApiScope maps from android.SdkKind to apiScope. 1230func sdkKindToApiScope(kind android.SdkKind) *apiScope { 1231 var apiScope *apiScope 1232 switch kind { 1233 case android.SdkSystem: 1234 apiScope = apiScopeSystem 1235 case android.SdkModule: 1236 apiScope = apiScopeModuleLib 1237 case android.SdkTest: 1238 apiScope = apiScopeTest 1239 case android.SdkSystemServer: 1240 apiScope = apiScopeSystemServer 1241 default: 1242 apiScope = apiScopePublic 1243 } 1244 return apiScope 1245} 1246 1247// to satisfy SdkLibraryDependency interface 1248func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath { 1249 paths := c.selectScopePaths(ctx, kind) 1250 if paths == nil { 1251 return makeUnsetDexJarPath() 1252 } 1253 1254 return paths.stubsDexJarPath 1255} 1256 1257// to satisfy SdkLibraryDependency interface 1258func (c *commonToSdkLibraryAndImport) SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath { 1259 paths := c.selectScopePaths(ctx, kind) 1260 if paths == nil { 1261 return makeUnsetDexJarPath() 1262 } 1263 1264 return paths.exportableStubsDexJarPath 1265} 1266 1267// to satisfy SdkLibraryDependency interface 1268func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath { 1269 apiScope := sdkKindToApiScope(kind) 1270 paths := c.findScopePaths(apiScope) 1271 if paths == nil { 1272 return android.OptionalPath{} 1273 } 1274 1275 return paths.removedApiFilePath 1276} 1277 1278func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { 1279 componentProps := &struct { 1280 SdkLibraryName *string 1281 SdkLibraryToImplicitlyTrack *string 1282 }{} 1283 1284 namePtr := proptools.StringPtr(c.module.RootLibraryName()) 1285 componentProps.SdkLibraryName = namePtr 1286 1287 if c.sharedLibrary() { 1288 // Mark the stubs library as being components of this java_sdk_library so that 1289 // any app that includes code which depends (directly or indirectly) on the stubs 1290 // library will have the appropriate <uses-library> invocation inserted into its 1291 // manifest if necessary. 1292 componentProps.SdkLibraryToImplicitlyTrack = namePtr 1293 } 1294 1295 return componentProps 1296} 1297 1298func (c *commonToSdkLibraryAndImport) sharedLibrary() bool { 1299 return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true) 1300} 1301 1302// Check if the stub libraries should be compiled for dex 1303func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool { 1304 // Always compile the dex file files for the stub libraries if they will be used on the 1305 // bootclasspath. 1306 return !c.sharedLibrary() 1307} 1308 1309// Properties related to the use of a module as an component of a java_sdk_library. 1310type SdkLibraryComponentProperties struct { 1311 // The name of the java_sdk_library/_import module. 1312 SdkLibraryName *string `blueprint:"mutated"` 1313 1314 // The name of the java_sdk_library/_import to add to a <uses-library> entry 1315 // in the AndroidManifest.xml of any Android app that includes code that references 1316 // this module. If not set then no java_sdk_library/_import is tracked. 1317 SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` 1318} 1319 1320// Structure to be embedded in a module struct that needs to support the 1321// SdkLibraryComponentDependency interface. 1322type EmbeddableSdkLibraryComponent struct { 1323 sdkLibraryComponentProperties SdkLibraryComponentProperties 1324} 1325 1326func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) { 1327 module.AddProperties(&e.sdkLibraryComponentProperties) 1328} 1329 1330// to satisfy SdkLibraryComponentDependency 1331func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string { 1332 return e.sdkLibraryComponentProperties.SdkLibraryName 1333} 1334 1335// to satisfy SdkLibraryComponentDependency 1336func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *string { 1337 // For shared libraries, this is the same as the SDK library name. If a Java library or app 1338 // depends on a component library (e.g. a stub library) it still needs to know the name of the 1339 // run-time library and the corresponding module that provides the implementation. This name is 1340 // passed to manifest_fixer (to be added to AndroidManifest.xml) and added to CLC (to be used 1341 // in dexpreopt). 1342 // 1343 // For non-shared SDK (component or not) libraries this returns `nil`, as they are not 1344 // <uses-library> and should not be added to the manifest or to CLC. 1345 return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack 1346} 1347 1348// Implemented by modules that are (or possibly could be) a component of a java_sdk_library 1349// (including the java_sdk_library) itself. 1350type SdkLibraryComponentDependency interface { 1351 UsesLibraryDependency 1352 1353 // SdkLibraryName returns the name of the java_sdk_library/_import module. 1354 SdkLibraryName() *string 1355 1356 // The name of the implementation library for the optional SDK library or nil, if there isn't one. 1357 OptionalSdkLibraryImplementation() *string 1358} 1359 1360// Make sure that all the module types that are components of java_sdk_library/_import 1361// and which can be referenced (directly or indirectly) from an android app implement 1362// the SdkLibraryComponentDependency interface. 1363var _ SdkLibraryComponentDependency = (*Library)(nil) 1364var _ SdkLibraryComponentDependency = (*Import)(nil) 1365var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) 1366var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil) 1367 1368// Provides access to sdk_version related files, e.g. header and implementation jars. 1369type SdkLibraryDependency interface { 1370 SdkLibraryComponentDependency 1371 1372 // Get the header jars appropriate for the supplied sdk_version. 1373 // 1374 // These are turbine generated jars so they only change if the externals of the 1375 // class changes but it does not contain and implementation or JavaDoc. 1376 SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths 1377 1378 // SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt 1379 // java_sdk_library_import module. It is needed by the hiddenapi processing tool which 1380 // processes dex files. 1381 SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath 1382 1383 // SdkApiExportableStubDexJar returns the exportable dex jar for the stubs for 1384 // java_sdk_library module. It is needed by the hiddenapi processing tool which processes 1385 // dex files. 1386 SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath 1387 1388 // SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind. 1389 SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath 1390 1391 // sharedLibrary returns true if this can be used as a shared library. 1392 sharedLibrary() bool 1393 1394 getImplLibraryModule() *Library 1395} 1396 1397type SdkLibrary struct { 1398 Library 1399 1400 sdkLibraryProperties sdkLibraryProperties 1401 1402 // Map from api scope to the scope specific property structure. 1403 scopeToProperties map[*apiScope]*ApiScopeProperties 1404 1405 commonToSdkLibraryAndImport 1406 1407 builtInstalledForApex []dexpreopterInstall 1408} 1409 1410var _ SdkLibraryDependency = (*SdkLibrary)(nil) 1411 1412func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool { 1413 return module.sdkLibraryProperties.Generate_system_and_test_apis 1414} 1415 1416func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { 1417 if module.implLibraryModule != nil { 1418 return module.implLibraryModule.DexJarBuildPath(ctx) 1419 } 1420 return makeUnsetDexJarPath() 1421} 1422 1423func (module *SdkLibrary) DexJarInstallPath() android.Path { 1424 if module.implLibraryModule != nil { 1425 return module.implLibraryModule.DexJarInstallPath() 1426 } 1427 return nil 1428} 1429 1430func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes { 1431 // Check to see if any scopes have been explicitly enabled. If any have then all 1432 // must be. 1433 anyScopesExplicitlyEnabled := false 1434 for _, scope := range AllApiScopes { 1435 scopeProperties := module.scopeToProperties[scope] 1436 if scopeProperties.Enabled != nil { 1437 anyScopesExplicitlyEnabled = true 1438 break 1439 } 1440 } 1441 1442 var generatedScopes apiScopes 1443 enabledScopes := make(map[*apiScope]struct{}) 1444 for _, scope := range AllApiScopes { 1445 scopeProperties := module.scopeToProperties[scope] 1446 // If any scopes are explicitly enabled then ignore the legacy enabled status. 1447 // This is to ensure that any new usages of this module type do not rely on legacy 1448 // behaviour. 1449 defaultEnabledStatus := false 1450 if anyScopesExplicitlyEnabled { 1451 defaultEnabledStatus = scope.defaultEnabledStatus 1452 } else { 1453 defaultEnabledStatus = scope.legacyEnabledStatus(module) 1454 } 1455 enabled := proptools.BoolDefault(scopeProperties.Enabled, defaultEnabledStatus) 1456 if enabled { 1457 enabledScopes[scope] = struct{}{} 1458 generatedScopes = append(generatedScopes, scope) 1459 } 1460 } 1461 1462 // Now check to make sure that any scope that is extended by an enabled scope is also 1463 // enabled. 1464 for _, scope := range AllApiScopes { 1465 if _, ok := enabledScopes[scope]; ok { 1466 extends := scope.extends 1467 if extends != nil { 1468 if _, ok := enabledScopes[extends]; !ok { 1469 ctx.ModuleErrorf("enabled api scope %q depends on disabled scope %q", scope, extends) 1470 } 1471 } 1472 } 1473 } 1474 1475 return generatedScopes 1476} 1477 1478var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil) 1479 1480func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { 1481 CheckMinSdkVersion(ctx, &module.Library) 1482} 1483 1484func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { 1485 android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) { 1486 ctx.WalkDeps(func(child android.Module, parent android.Module) bool { 1487 isExternal := !module.depIsInSameApex(ctx, child) 1488 if am, ok := child.(android.ApexModule); ok { 1489 if !do(ctx, parent, am, isExternal) { 1490 return false 1491 } 1492 } 1493 return !isExternal 1494 }) 1495 }) 1496} 1497 1498type sdkLibraryComponentTag struct { 1499 blueprint.BaseDependencyTag 1500 name string 1501} 1502 1503// Mark this tag so dependencies that use it are excluded from visibility enforcement. 1504func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {} 1505 1506var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"} 1507 1508func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool { 1509 if dt, ok := depTag.(sdkLibraryComponentTag); ok { 1510 return dt == xmlPermissionsFileTag 1511 } 1512 return false 1513} 1514 1515var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"} 1516 1517var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{} 1518 1519// To satisfy the CopyDirectlyInAnyApexTag interface. Implementation library of the sdk library 1520// in an apex is considered to be directly in the apex, as if it was listed in java_libs. 1521func (t sdkLibraryComponentTag) CopyDirectlyInAnyApex() {} 1522 1523var _ android.CopyDirectlyInAnyApexTag = implLibraryTag 1524 1525func (t sdkLibraryComponentTag) InstallDepNeeded() bool { 1526 return t.name == "xml-permissions-file" || t.name == "impl-library" 1527} 1528 1529// Add the dependencies on the child modules in the component deps mutator. 1530func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 1531 for _, apiScope := range module.getGeneratedApiScopes(ctx) { 1532 // Add dependencies to the stubs library 1533 stubModuleName := module.stubsLibraryModuleName(apiScope) 1534 ctx.AddVariationDependencies(nil, apiScope.everythingStubsTag, stubModuleName) 1535 1536 exportableStubModuleName := module.exportableStubsLibraryModuleName(apiScope) 1537 ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName) 1538 1539 // Add a dependency on the stubs source in order to access both stubs source and api information. 1540 ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope)) 1541 1542 if module.compareAgainstLatestApi(apiScope) { 1543 // Add dependencies on the latest finalized version of the API .txt file. 1544 latestApiModuleName := module.latestApiModuleName(apiScope) 1545 ctx.AddDependency(module, apiScope.latestApiModuleTag, latestApiModuleName) 1546 1547 // Add dependencies on the latest finalized version of the remove API .txt file. 1548 latestRemovedApiModuleName := module.latestRemovedApiModuleName(apiScope) 1549 ctx.AddDependency(module, apiScope.latestRemovedApiModuleTag, latestRemovedApiModuleName) 1550 } 1551 } 1552 1553 if module.requiresRuntimeImplementationLibrary() { 1554 // Add dependency to the rule for generating the implementation library. 1555 ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName()) 1556 1557 if module.sharedLibrary() { 1558 // Add dependency to the rule for generating the xml permissions file 1559 ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName()) 1560 } 1561 } 1562} 1563 1564// Add other dependencies as normal. 1565func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { 1566 var missingApiModules []string 1567 for _, apiScope := range module.getGeneratedApiScopes(ctx) { 1568 if apiScope.unstable { 1569 continue 1570 } 1571 if m := module.latestApiModuleName(apiScope); !ctx.OtherModuleExists(m) { 1572 missingApiModules = append(missingApiModules, m) 1573 } 1574 if m := module.latestRemovedApiModuleName(apiScope); !ctx.OtherModuleExists(m) { 1575 missingApiModules = append(missingApiModules, m) 1576 } 1577 if m := module.latestIncompatibilitiesModuleName(apiScope); !ctx.OtherModuleExists(m) { 1578 missingApiModules = append(missingApiModules, m) 1579 } 1580 } 1581 if len(missingApiModules) != 0 && !module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api { 1582 m := module.Name() + " is missing tracking files for previously released library versions.\n" 1583 m += "You need to do one of the following:\n" 1584 m += "- Add `unsafe_ignore_missing_latest_api: true` to your blueprint (to disable compat tracking)\n" 1585 m += "- Add a set of prebuilt txt files representing the last released version of this library for compat checking.\n" 1586 m += " (the current set of API files can be used as a seed for this compatibility tracking\n" 1587 m += "\n" 1588 m += "The following filegroup modules are missing:\n " 1589 m += strings.Join(missingApiModules, "\n ") + "\n" 1590 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." 1591 ctx.ModuleErrorf(m) 1592 } 1593} 1594 1595func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { 1596 paths, err := module.commonOutputFiles(tag) 1597 if paths != nil || err != nil { 1598 return paths, err 1599 } 1600 if module.requiresRuntimeImplementationLibrary() { 1601 return module.implLibraryModule.OutputFiles(tag) 1602 } 1603 if tag == "" { 1604 return nil, nil 1605 } 1606 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 1607} 1608 1609func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1610 if disableSourceApexVariant(ctx) { 1611 // Prebuilts are active, do not create the installation rules for the source javalib. 1612 // Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules. 1613 // TODO (b/331665856): Implement a principled solution for this. 1614 module.HideFromMake() 1615 } 1616 1617 module.generateCommonBuildActions(ctx) 1618 1619 module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName()) 1620 1621 module.provideHiddenAPIPropertyInfo(ctx) 1622 1623 // Collate the components exported by this module. All scope specific modules are exported but 1624 // the impl and xml component modules are not. 1625 exportedComponents := map[string]struct{}{} 1626 1627 // Record the paths to the header jars of the library (stubs and impl). 1628 // When this java_sdk_library is depended upon from others via "libs" property, 1629 // the recorded paths will be returned depending on the link type of the caller. 1630 ctx.VisitDirectDeps(func(to android.Module) { 1631 tag := ctx.OtherModuleDependencyTag(to) 1632 1633 // Extract information from any of the scope specific dependencies. 1634 if scopeTag, ok := tag.(scopeDependencyTag); ok { 1635 apiScope := scopeTag.apiScope 1636 scopePaths := module.getScopePathsCreateIfNeeded(apiScope) 1637 1638 // Extract information from the dependency. The exact information extracted 1639 // is determined by the nature of the dependency which is determined by the tag. 1640 scopeTag.extractDepInfo(ctx, to, scopePaths) 1641 1642 exportedComponents[ctx.OtherModuleName(to)] = struct{}{} 1643 } 1644 1645 if tag == implLibraryTag { 1646 if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { 1647 module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...) 1648 module.implLibraryModule = to.(*Library) 1649 android.SetProvider(ctx, JavaInfoProvider, dep) 1650 } 1651 } 1652 }) 1653 1654 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 1655 if !apexInfo.IsForPlatform() { 1656 module.hideApexVariantFromMake = true 1657 } 1658 1659 if module.implLibraryModule != nil { 1660 if ctx.Device() { 1661 module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile} 1662 module.bootDexJarPath = module.implLibraryModule.bootDexJarPath 1663 module.uncompressDexState = module.implLibraryModule.uncompressDexState 1664 module.active = module.implLibraryModule.active 1665 } 1666 1667 module.outputFile = module.implLibraryModule.outputFile 1668 module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path()) 1669 module.headerJarFile = module.implLibraryModule.headerJarFile 1670 module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar 1671 module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex 1672 module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath 1673 module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost 1674 1675 // Properties required for Library.AndroidMkEntries 1676 module.logtagsSrcs = module.implLibraryModule.logtagsSrcs 1677 module.dexpreopter.builtInstalled = module.implLibraryModule.dexpreopter.builtInstalled 1678 module.jacocoReportClassesFile = module.implLibraryModule.jacocoReportClassesFile 1679 module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary 1680 module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip 1681 module.linter.reports = module.implLibraryModule.linter.reports 1682 1683 if !module.Host() { 1684 module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile 1685 } 1686 1687 android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()}) 1688 } 1689 1690 // Make the set of components exported by this module available for use elsewhere. 1691 exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)} 1692 android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo) 1693 1694 // Provide additional information for inclusion in an sdk's generated .info file. 1695 additionalSdkInfo := map[string]interface{}{} 1696 additionalSdkInfo["dist_stem"] = module.distStem() 1697 baseModuleName := module.distStem() 1698 scopes := map[string]interface{}{} 1699 additionalSdkInfo["scopes"] = scopes 1700 for scope, scopePaths := range module.scopePaths { 1701 scopeInfo := map[string]interface{}{} 1702 scopes[scope.name] = scopeInfo 1703 scopeInfo["current_api"] = scope.snapshotRelativeCurrentApiTxtPath(baseModuleName) 1704 scopeInfo["removed_api"] = scope.snapshotRelativeRemovedApiTxtPath(baseModuleName) 1705 if p := scopePaths.latestApiPaths; len(p) > 0 { 1706 // The last path in the list is the one that applies to this scope, the 1707 // preceding ones, if any, are for the scope(s) that it extends. 1708 scopeInfo["latest_api"] = p[len(p)-1].String() 1709 } 1710 if p := scopePaths.latestRemovedApiPaths; len(p) > 0 { 1711 // The last path in the list is the one that applies to this scope, the 1712 // preceding ones, if any, are for the scope(s) that it extends. 1713 scopeInfo["latest_removed_api"] = p[len(p)-1].String() 1714 } 1715 } 1716 android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo}) 1717} 1718 1719func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall { 1720 return module.builtInstalledForApex 1721} 1722 1723func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { 1724 if !module.requiresRuntimeImplementationLibrary() { 1725 return nil 1726 } 1727 entriesList := module.Library.AndroidMkEntries() 1728 entries := &entriesList[0] 1729 entries.Required = append(entries.Required, module.implLibraryModuleName()) 1730 if module.sharedLibrary() { 1731 entries.Required = append(entries.Required, module.xmlPermissionsModuleName()) 1732 } 1733 return entriesList 1734} 1735 1736// The dist path of the stub artifacts 1737func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string { 1738 return path.Join("apistubs", module.distGroup(), apiScope.name) 1739} 1740 1741// Get the sdk version for use when compiling the stubs library. 1742func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.EarlyModuleContext, apiScope *apiScope) string { 1743 scopeProperties := module.scopeToProperties[apiScope] 1744 if scopeProperties.Sdk_version != nil { 1745 return proptools.String(scopeProperties.Sdk_version) 1746 } 1747 1748 sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library)) 1749 if sdkDep.hasStandardLibs() { 1750 // If building against a standard sdk then use the sdk version appropriate for the scope. 1751 return apiScope.sdkVersion 1752 } else { 1753 // Otherwise, use no system module. 1754 return "none" 1755 } 1756} 1757 1758func (module *SdkLibrary) distStem() string { 1759 return proptools.StringDefault(module.sdkLibraryProperties.Dist_stem, module.BaseModuleName()) 1760} 1761 1762// distGroup returns the subdirectory of the dist path of the stub artifacts. 1763func (module *SdkLibrary) distGroup() string { 1764 return proptools.StringDefault(module.sdkLibraryProperties.Dist_group, "unknown") 1765} 1766 1767func latestPrebuiltApiModuleName(name string, apiScope *apiScope) string { 1768 return PrebuiltApiModuleName(name, apiScope.name, "latest") 1769} 1770 1771func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string { 1772 return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest") 1773} 1774 1775func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string { 1776 return ":" + module.latestApiModuleName(apiScope) 1777} 1778 1779func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string { 1780 return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope) 1781} 1782 1783func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string { 1784 return ":" + module.latestRemovedApiModuleName(apiScope) 1785} 1786 1787func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string { 1788 return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope) 1789} 1790 1791func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string { 1792 return ":" + module.latestIncompatibilitiesModuleName(apiScope) 1793} 1794 1795func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope) string { 1796 return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope) 1797} 1798 1799func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool { 1800 _, exists := c.GetApiLibraries()[module.Name()] 1801 return exists 1802} 1803 1804// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the 1805// api surface that the module contribute to. For example, the public droidstubs and java_library 1806// do not contribute to the public api surface, but contributes to the core platform api surface. 1807// This method returns the full api surface stub lib that 1808// the generated java_api_library should depend on. 1809func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string { 1810 if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok { 1811 return val.FullApiSurfaceStubLib 1812 } 1813 return "" 1814} 1815 1816// The listed modules' stubs contents do not match the corresponding txt files, 1817// but require additional api contributions to generate the full stubs. 1818// This method returns the name of the additional api contribution module 1819// for corresponding sdk_library modules. 1820func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string { 1821 if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok { 1822 return val.AdditionalApiContribution 1823 } 1824 return "" 1825} 1826 1827func childModuleVisibility(childVisibility []string) []string { 1828 if childVisibility == nil { 1829 // No child visibility set. The child will use the visibility of the sdk_library. 1830 return nil 1831 } 1832 1833 // Prepend an override to ignore the sdk_library's visibility, and rely on the child visibility. 1834 var visibility []string 1835 visibility = append(visibility, "//visibility:override") 1836 visibility = append(visibility, childVisibility...) 1837 return visibility 1838} 1839 1840// Creates the implementation java library 1841func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) { 1842 visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility) 1843 1844 props := struct { 1845 Name *string 1846 Visibility []string 1847 Libs []string 1848 Static_libs []string 1849 Apex_available []string 1850 Stem *string 1851 }{ 1852 Name: proptools.StringPtr(module.implLibraryModuleName()), 1853 Visibility: visibility, 1854 1855 Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...), 1856 1857 Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...), 1858 // Pass the apex_available settings down so that the impl library can be statically 1859 // embedded within a library that is added to an APEX. Needed for updatable-media. 1860 Apex_available: module.ApexAvailable(), 1861 1862 Stem: proptools.StringPtr(module.Name()), 1863 } 1864 1865 properties := []interface{}{ 1866 &module.properties, 1867 &module.protoProperties, 1868 &module.deviceProperties, 1869 &module.dexProperties, 1870 &module.dexpreoptProperties, 1871 &module.linter.properties, 1872 &module.overridableProperties, 1873 &props, 1874 module.sdkComponentPropertiesForChildLibrary(), 1875 } 1876 mctx.CreateModule(LibraryFactory, properties...) 1877} 1878 1879type libraryProperties struct { 1880 Name *string 1881 Visibility []string 1882 Srcs []string 1883 Installable *bool 1884 Sdk_version *string 1885 System_modules *string 1886 Patch_module *string 1887 Libs []string 1888 Static_libs []string 1889 Compile_dex *bool 1890 Java_version *string 1891 Openjdk9 struct { 1892 Srcs []string 1893 Javacflags []string 1894 } 1895 Dist struct { 1896 Targets []string 1897 Dest *string 1898 Dir *string 1899 Tag *string 1900 } 1901 Is_stubs_module *bool 1902} 1903 1904func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties { 1905 props := libraryProperties{} 1906 props.Visibility = []string{"//visibility:override", "//visibility:private"} 1907 // sources are generated from the droiddoc 1908 sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) 1909 props.Sdk_version = proptools.StringPtr(sdkVersion) 1910 props.System_modules = module.deviceProperties.System_modules 1911 props.Patch_module = module.properties.Patch_module 1912 props.Installable = proptools.BoolPtr(false) 1913 props.Libs = module.sdkLibraryProperties.Stub_only_libs 1914 props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...) 1915 props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs 1916 // The stub-annotations library contains special versions of the annotations 1917 // with CLASS retention policy, so that they're kept. 1918 if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) { 1919 props.Libs = append(props.Libs, "stub-annotations") 1920 } 1921 props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs 1922 props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags 1923 // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential 1924 // interop with older developer tools that don't support 1.9. 1925 props.Java_version = proptools.StringPtr("1.8") 1926 props.Is_stubs_module = proptools.BoolPtr(true) 1927 1928 return props 1929} 1930 1931// Creates a static java library that has API stubs 1932func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { 1933 1934 props := module.stubsLibraryProps(mctx, apiScope) 1935 props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope)) 1936 props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} 1937 1938 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 1939} 1940 1941// Create a static java library that compiles the "exportable" stubs 1942func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { 1943 props := module.stubsLibraryProps(mctx, apiScope) 1944 props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope)) 1945 props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"} 1946 1947 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 1948} 1949 1950// Creates a droidstubs module that creates stubs source files from the given full source 1951// files and also updates and checks the API specification files. 1952func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) { 1953 props := struct { 1954 Name *string 1955 Visibility []string 1956 Srcs []string 1957 Installable *bool 1958 Sdk_version *string 1959 Api_surface *string 1960 System_modules *string 1961 Libs []string 1962 Output_javadoc_comments *bool 1963 Arg_files []string 1964 Args *string 1965 Java_version *string 1966 Annotations_enabled *bool 1967 Merge_annotations_dirs []string 1968 Merge_inclusion_annotations_dirs []string 1969 Generate_stubs *bool 1970 Previous_api *string 1971 Aconfig_declarations []string 1972 Check_api struct { 1973 Current ApiToCheck 1974 Last_released ApiToCheck 1975 1976 Api_lint struct { 1977 Enabled *bool 1978 New_since *string 1979 Baseline_file *string 1980 } 1981 } 1982 Aidl struct { 1983 Include_dirs []string 1984 Local_include_dirs []string 1985 } 1986 Dists []android.Dist 1987 }{} 1988 1989 // The stubs source processing uses the same compile time classpath when extracting the 1990 // API from the implementation library as it does when compiling it. i.e. the same 1991 // * sdk version 1992 // * system_modules 1993 // * libs (static_libs/libs) 1994 1995 props.Name = proptools.StringPtr(name) 1996 props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility) 1997 props.Srcs = append(props.Srcs, module.properties.Srcs...) 1998 props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...) 1999 props.Sdk_version = module.deviceProperties.Sdk_version 2000 props.Api_surface = &apiScope.name 2001 props.System_modules = module.deviceProperties.System_modules 2002 props.Installable = proptools.BoolPtr(false) 2003 // A droiddoc module has only one Libs property and doesn't distinguish between 2004 // shared libs and static libs. So we need to add both of these libs to Libs property. 2005 props.Libs = module.properties.Libs 2006 props.Libs = append(props.Libs, module.properties.Static_libs...) 2007 props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...) 2008 props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...) 2009 props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs 2010 props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs 2011 props.Java_version = module.properties.Java_version 2012 2013 props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled 2014 props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs 2015 props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs 2016 props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations 2017 2018 droidstubsArgs := []string{} 2019 if len(module.sdkLibraryProperties.Api_packages) != 0 { 2020 droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":")) 2021 } 2022 if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 { 2023 droidstubsArgs = append(droidstubsArgs, 2024 android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package ")) 2025 } 2026 droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...) 2027 disabledWarnings := []string{"HiddenSuperclass"} 2028 if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) { 2029 disabledWarnings = append(disabledWarnings, 2030 "BroadcastBehavior", 2031 "DeprecationMismatch", 2032 "MissingPermission", 2033 "SdkConstant", 2034 "Todo", 2035 ) 2036 } 2037 droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) 2038 2039 // Output Javadoc comments for public scope. 2040 if apiScope == apiScopePublic { 2041 props.Output_javadoc_comments = proptools.BoolPtr(true) 2042 } 2043 2044 // Add in scope specific arguments. 2045 droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) 2046 props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files 2047 props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " ")) 2048 2049 // List of APIs identified from the provided source files are created. They are later 2050 // compared against to the not-yet-released (a.k.a current) list of APIs and to the 2051 // last-released (a.k.a numbered) list of API. 2052 currentApiFileName := apiScope.apiFilePrefix + "current.txt" 2053 removedApiFileName := apiScope.apiFilePrefix + "removed.txt" 2054 apiDir := module.getApiDir() 2055 currentApiFileName = path.Join(apiDir, currentApiFileName) 2056 removedApiFileName = path.Join(apiDir, removedApiFileName) 2057 2058 // check against the not-yet-release API 2059 props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) 2060 props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) 2061 2062 if module.compareAgainstLatestApi(apiScope) { 2063 // check against the latest released API 2064 latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) 2065 props.Previous_api = latestApiFilegroupName 2066 props.Check_api.Last_released.Api_file = latestApiFilegroupName 2067 props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( 2068 module.latestRemovedApiFilegroupName(apiScope)) 2069 props.Check_api.Last_released.Baseline_file = proptools.StringPtr( 2070 module.latestIncompatibilitiesFilegroupName(apiScope)) 2071 2072 if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { 2073 // Enable api lint. 2074 props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) 2075 props.Check_api.Api_lint.New_since = latestApiFilegroupName 2076 2077 // If it exists then pass a lint-baseline.txt through to droidstubs. 2078 baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") 2079 baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) 2080 paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) 2081 if err != nil { 2082 mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) 2083 } 2084 if len(paths) == 1 { 2085 props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) 2086 } else if len(paths) != 0 { 2087 mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) 2088 } 2089 } 2090 } 2091 2092 if !Bool(module.sdkLibraryProperties.No_dist) { 2093 // Dist the api txt and removed api txt artifacts for sdk builds. 2094 distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) 2095 stubsTypeTagPrefix := "" 2096 if mctx.Config().ReleaseHiddenApiExportableStubs() { 2097 stubsTypeTagPrefix = ".exportable" 2098 } 2099 for _, p := range []struct { 2100 tag string 2101 pattern string 2102 }{ 2103 // "exportable" api files are copied to the dist directory instead of the 2104 // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag 2105 // is set. Otherwise, the "everything" api files are copied to the dist directory. 2106 {tag: "%s.api.txt", pattern: "%s.txt"}, 2107 {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"}, 2108 } { 2109 props.Dists = append(props.Dists, android.Dist{ 2110 Targets: []string{"sdk", "win_sdk"}, 2111 Dir: distDir, 2112 Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())), 2113 Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)), 2114 }) 2115 } 2116 } 2117 2118 mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx) 2119} 2120 2121func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) { 2122 props := struct { 2123 Name *string 2124 Visibility []string 2125 Api_contributions []string 2126 Libs []string 2127 Static_libs []string 2128 Full_api_surface_stub *string 2129 System_modules *string 2130 Enable_validation *bool 2131 Stubs_type *string 2132 }{} 2133 2134 props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) 2135 props.Visibility = []string{"//visibility:override", "//visibility:private"} 2136 2137 apiContributions := []string{} 2138 2139 // Api surfaces are not independent of each other, but have subset relationships, 2140 // and so does the api files. To generate from-text stubs for api surfaces other than public, 2141 // all subset api domains' api_contriubtions must be added as well. 2142 scope := apiScope 2143 for scope != nil { 2144 apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution") 2145 scope = scope.extends 2146 } 2147 if apiScope == apiScopePublic { 2148 additionalApiContribution := module.apiLibraryAdditionalApiContribution() 2149 if additionalApiContribution != "" { 2150 apiContributions = append(apiContributions, additionalApiContribution) 2151 } 2152 } 2153 2154 props.Api_contributions = apiContributions 2155 props.Libs = module.properties.Libs 2156 props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...) 2157 props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...) 2158 props.Libs = append(props.Libs, "stub-annotations") 2159 props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs 2160 props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName()) 2161 if alternativeFullApiSurfaceStub != "" { 2162 props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub) 2163 } 2164 2165 // android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n. 2166 // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains. 2167 if apiScope.kind == android.SdkModule { 2168 props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text") 2169 } 2170 2171 // java_sdk_library modules that set sdk_version as none does not depend on other api 2172 // domains. Therefore, java_api_library created from such modules should not depend on 2173 // full_api_surface_stubs but create and compile stubs by the java_api_library module 2174 // itself. 2175 if module.SdkVersion(mctx).Kind == android.SdkNone { 2176 props.Full_api_surface_stub = nil 2177 } 2178 2179 props.System_modules = module.deviceProperties.System_modules 2180 props.Enable_validation = proptools.BoolPtr(true) 2181 props.Stubs_type = proptools.StringPtr("everything") 2182 2183 mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2184} 2185 2186func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties { 2187 props := libraryProperties{} 2188 2189 props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) 2190 sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) 2191 props.Sdk_version = proptools.StringPtr(sdkVersion) 2192 2193 props.System_modules = module.deviceProperties.System_modules 2194 2195 // The imports need to be compiled to dex if the java_sdk_library requests it. 2196 compileDex := module.dexProperties.Compile_dex 2197 if module.stubLibrariesCompiledForDex() { 2198 compileDex = proptools.BoolPtr(true) 2199 } 2200 props.Compile_dex = compileDex 2201 2202 if !Bool(module.sdkLibraryProperties.No_dist) && doDist { 2203 props.Dist.Targets = []string{"sdk", "win_sdk"} 2204 props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem())) 2205 props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope)) 2206 props.Dist.Tag = proptools.StringPtr(".jar") 2207 } 2208 2209 return props 2210} 2211 2212func (module *SdkLibrary) createTopLevelStubsLibrary( 2213 mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) { 2214 2215 // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false 2216 doDist := !mctx.Config().ReleaseHiddenApiExportableStubs() 2217 props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist) 2218 props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) 2219 2220 // Add the stub compiling java_library/java_api_library as static lib based on build config 2221 staticLib := module.sourceStubsLibraryModuleName(apiScope) 2222 if mctx.Config().BuildFromTextStub() && contributesToApiSurface { 2223 staticLib = module.apiLibraryModuleName(apiScope) 2224 } 2225 props.Static_libs = append(props.Static_libs, staticLib) 2226 2227 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2228} 2229 2230func (module *SdkLibrary) createTopLevelExportableStubsLibrary( 2231 mctx android.DefaultableHookContext, apiScope *apiScope) { 2232 2233 // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true 2234 doDist := mctx.Config().ReleaseHiddenApiExportableStubs() 2235 props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist) 2236 props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope)) 2237 2238 staticLib := module.exportableSourceStubsLibraryModuleName(apiScope) 2239 props.Static_libs = append(props.Static_libs, staticLib) 2240 2241 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2242} 2243 2244func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool { 2245 return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) 2246} 2247 2248// Implements android.ApexModule 2249func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool { 2250 depTag := mctx.OtherModuleDependencyTag(dep) 2251 if depTag == xmlPermissionsFileTag { 2252 return true 2253 } 2254 if dep.Name() == module.implLibraryModuleName() { 2255 return true 2256 } 2257 return module.Library.DepIsInSameApex(mctx, dep) 2258} 2259 2260// Implements android.ApexModule 2261func (module *SdkLibrary) UniqueApexVariations() bool { 2262 return module.uniqueApexVariations() 2263} 2264 2265func (module *SdkLibrary) ContributeToApi() bool { 2266 return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false) 2267} 2268 2269// Creates the xml file that publicizes the runtime library 2270func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { 2271 moduleMinApiLevel := module.Library.MinSdkVersion(mctx) 2272 var moduleMinApiLevelStr = moduleMinApiLevel.String() 2273 if moduleMinApiLevel == android.NoneApiLevel { 2274 moduleMinApiLevelStr = "current" 2275 } 2276 props := struct { 2277 Name *string 2278 Lib_name *string 2279 Apex_available []string 2280 On_bootclasspath_since *string 2281 On_bootclasspath_before *string 2282 Min_device_sdk *string 2283 Max_device_sdk *string 2284 Sdk_library_min_api_level *string 2285 Uses_libs_dependencies []string 2286 }{ 2287 Name: proptools.StringPtr(module.xmlPermissionsModuleName()), 2288 Lib_name: proptools.StringPtr(module.BaseModuleName()), 2289 Apex_available: module.ApexProperties.Apex_available, 2290 On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since, 2291 On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before, 2292 Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk, 2293 Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk, 2294 Sdk_library_min_api_level: &moduleMinApiLevelStr, 2295 Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs, 2296 } 2297 2298 mctx.CreateModule(sdkLibraryXmlFactory, &props) 2299} 2300 2301func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths { 2302 var ver android.ApiLevel 2303 var kind android.SdkKind 2304 if s.UsePrebuilt(ctx) { 2305 ver = s.ApiLevel 2306 kind = s.Kind 2307 } else { 2308 // We don't have prebuilt SDK for the specific sdkVersion. 2309 // Instead of breaking the build, fallback to use "system_current" 2310 ver = android.FutureApiLevel 2311 kind = android.SdkSystem 2312 } 2313 2314 dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String()) 2315 jar := filepath.Join(dir, baseName+".jar") 2316 jarPath := android.ExistentPathForSource(ctx, jar) 2317 if !jarPath.Valid() { 2318 if ctx.Config().AllowMissingDependencies() { 2319 return android.Paths{android.PathForSource(ctx, jar)} 2320 } else { 2321 ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar) 2322 } 2323 return nil 2324 } 2325 return android.Paths{jarPath.Path()} 2326} 2327 2328// Check to see if the other module is within the same set of named APEXes as this module. 2329// 2330// If either this or the other module are on the platform then this will return 2331// false. 2332func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool { 2333 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 2334 otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider) 2335 return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants) 2336} 2337 2338func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { 2339 // If the client doesn't set sdk_version, but if this library prefers stubs over 2340 // the impl library, let's provide the widest API surface possible. To do so, 2341 // force override sdk_version to module_current so that the closest possible API 2342 // surface could be found in selectHeaderJarsForSdkVersion 2343 if module.defaultsToStubs() && !sdkVersion.Specified() { 2344 sdkVersion = android.SdkSpecFrom(ctx, "module_current") 2345 } 2346 2347 // Only provide access to the implementation library if it is actually built. 2348 if module.requiresRuntimeImplementationLibrary() { 2349 // Check any special cases for java_sdk_library. 2350 // 2351 // Only allow access to the implementation library in the following condition: 2352 // * No sdk_version specified on the referencing module. 2353 // * The referencing module is in the same apex as this. 2354 if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) { 2355 return module.implLibraryHeaderJars 2356 } 2357 } 2358 2359 return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) 2360} 2361 2362// to satisfy SdkLibraryDependency interface 2363func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { 2364 return module.sdkJars(ctx, sdkVersion) 2365} 2366 2367var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries") 2368 2369func javaSdkLibraries(config android.Config) *[]string { 2370 return config.Once(javaSdkLibrariesKey, func() interface{} { 2371 return &[]string{} 2372 }).(*[]string) 2373} 2374 2375func (module *SdkLibrary) getApiDir() string { 2376 return proptools.StringDefault(module.sdkLibraryProperties.Api_dir, "api") 2377} 2378 2379// For a java_sdk_library module, create internal modules for stubs, docs, 2380// runtime libs and xml file. If requested, the stubs and docs are created twice 2381// once for public API level and once for system API level 2382func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) { 2383 // If the module has been disabled then don't create any child modules. 2384 if !module.Enabled(mctx) { 2385 return 2386 } 2387 2388 if len(module.properties.Srcs) == 0 { 2389 mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs") 2390 return 2391 } 2392 2393 // If this builds against standard libraries (i.e. is not part of the core libraries) 2394 // then assume it provides both system and test apis. 2395 sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library)) 2396 hasSystemAndTestApis := sdkDep.hasStandardLibs() 2397 module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis 2398 2399 missingCurrentApi := false 2400 2401 generatedScopes := module.getGeneratedApiScopes(mctx) 2402 2403 apiDir := module.getApiDir() 2404 for _, scope := range generatedScopes { 2405 for _, api := range []string{"current.txt", "removed.txt"} { 2406 path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api) 2407 p := android.ExistentPathForSource(mctx, path) 2408 if !p.Valid() { 2409 if mctx.Config().AllowMissingDependencies() { 2410 mctx.AddMissingDependencies([]string{path}) 2411 } else { 2412 mctx.ModuleErrorf("Current api file %#v doesn't exist", path) 2413 missingCurrentApi = true 2414 } 2415 } 2416 } 2417 } 2418 2419 if missingCurrentApi { 2420 script := "build/soong/scripts/gen-java-current-api-files.sh" 2421 p := android.ExistentPathForSource(mctx, script) 2422 2423 if !p.Valid() { 2424 panic(fmt.Sprintf("script file %s doesn't exist", script)) 2425 } 2426 2427 mctx.ModuleErrorf("One or more current api files are missing. "+ 2428 "You can update them by:\n"+ 2429 "%s %q %s && m update-api", 2430 script, filepath.Join(mctx.ModuleDir(), apiDir), 2431 strings.Join(generatedScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " ")) 2432 return 2433 } 2434 2435 for _, scope := range generatedScopes { 2436 // Use the stubs source name for legacy reasons. 2437 module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs) 2438 2439 module.createStubsLibrary(mctx, scope) 2440 module.createExportableStubsLibrary(mctx, scope) 2441 2442 alternativeFullApiSurfaceStubLib := "" 2443 if scope == apiScopePublic { 2444 alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib() 2445 } 2446 contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != "" 2447 if contributesToApiSurface { 2448 module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib) 2449 } 2450 2451 module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface) 2452 module.createTopLevelExportableStubsLibrary(mctx, scope) 2453 } 2454 2455 if module.requiresRuntimeImplementationLibrary() { 2456 // Create child module to create an implementation library. 2457 // 2458 // This temporarily creates a second implementation library that can be explicitly 2459 // referenced. 2460 // 2461 // TODO(b/156618935) - update comment once only one implementation library is created. 2462 module.createImplLibrary(mctx) 2463 2464 // Only create an XML permissions file that declares the library as being usable 2465 // as a shared library if required. 2466 if module.sharedLibrary() { 2467 module.createXmlFile(mctx) 2468 } 2469 2470 // record java_sdk_library modules so that they are exported to make 2471 javaSdkLibraries := javaSdkLibraries(mctx.Config()) 2472 javaSdkLibrariesLock.Lock() 2473 defer javaSdkLibrariesLock.Unlock() 2474 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName()) 2475 } 2476 2477 // Add the impl_only_libs and impl_only_static_libs *after* we're done using them in submodules. 2478 module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...) 2479 module.properties.Static_libs = append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...) 2480} 2481 2482func (module *SdkLibrary) InitSdkLibraryProperties() { 2483 module.addHostAndDeviceProperties() 2484 module.AddProperties(&module.sdkLibraryProperties) 2485 2486 module.initSdkLibraryComponent(module) 2487 2488 module.properties.Installable = proptools.BoolPtr(true) 2489 module.deviceProperties.IsSDKLibrary = true 2490} 2491 2492func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool { 2493 return !proptools.Bool(module.sdkLibraryProperties.Api_only) 2494} 2495 2496func (module *SdkLibrary) defaultsToStubs() bool { 2497 return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs) 2498} 2499 2500// Defines how to name the individual component modules the sdk library creates. 2501type sdkLibraryComponentNamingScheme interface { 2502 stubsLibraryModuleName(scope *apiScope, baseName string) string 2503 2504 stubsSourceModuleName(scope *apiScope, baseName string) string 2505 2506 apiLibraryModuleName(scope *apiScope, baseName string) string 2507 2508 sourceStubsLibraryModuleName(scope *apiScope, baseName string) string 2509 2510 exportableStubsLibraryModuleName(scope *apiScope, baseName string) string 2511 2512 exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string 2513} 2514 2515type defaultNamingScheme struct { 2516} 2517 2518func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { 2519 return scope.stubsLibraryModuleName(baseName) 2520} 2521 2522func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { 2523 return scope.stubsSourceModuleName(baseName) 2524} 2525 2526func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string { 2527 return scope.apiLibraryModuleName(baseName) 2528} 2529 2530func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string { 2531 return scope.sourceStubLibraryModuleName(baseName) 2532} 2533 2534func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string { 2535 return scope.exportableStubsLibraryModuleName(baseName) 2536} 2537 2538func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string { 2539 return scope.exportableSourceStubsLibraryModuleName(baseName) 2540} 2541 2542var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) 2543 2544func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool { 2545 return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) || 2546 strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix()) 2547} 2548 2549func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) { 2550 name = strings.TrimSuffix(name, ".from-source") 2551 2552 // This suffix-based approach is fragile and could potentially mis-trigger. 2553 // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly. 2554 if hasStubsLibrarySuffix(name, apiScopePublic) { 2555 if name == "hwbinder.stubs" || name == "libcore_private.stubs" { 2556 // Due to a previous bug, these modules were not considered stubs, so we retain that. 2557 return false, javaPlatform 2558 } 2559 return true, javaSdk 2560 } 2561 if hasStubsLibrarySuffix(name, apiScopeSystem) { 2562 return true, javaSystem 2563 } 2564 if hasStubsLibrarySuffix(name, apiScopeModuleLib) { 2565 return true, javaModule 2566 } 2567 if hasStubsLibrarySuffix(name, apiScopeTest) { 2568 return true, javaSystem 2569 } 2570 if hasStubsLibrarySuffix(name, apiScopeSystemServer) { 2571 return true, javaSystemServer 2572 } 2573 return false, javaPlatform 2574} 2575 2576// java_sdk_library is a special Java library that provides optional platform APIs to apps. 2577// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients 2578// are linked against to, 2) droiddoc module that internally generates API stubs source files, 2579// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding 2580// the runtime lib to the classpath at runtime if requested via <uses-library>. 2581func SdkLibraryFactory() android.Module { 2582 module := &SdkLibrary{} 2583 2584 // Initialize information common between source and prebuilt. 2585 module.initCommon(module) 2586 2587 module.InitSdkLibraryProperties() 2588 android.InitApexModule(module) 2589 InitJavaModule(module, android.HostAndDeviceSupported) 2590 2591 // Initialize the map from scope to scope specific properties. 2592 scopeToProperties := make(map[*apiScope]*ApiScopeProperties) 2593 for _, scope := range AllApiScopes { 2594 scopeToProperties[scope] = scope.scopeSpecificProperties(module) 2595 } 2596 module.scopeToProperties = scopeToProperties 2597 2598 // Add the properties containing visibility rules so that they are checked. 2599 android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility) 2600 android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility) 2601 android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) 2602 2603 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { 2604 // If no implementation is required then it cannot be used as a shared library 2605 // either. 2606 if !module.requiresRuntimeImplementationLibrary() { 2607 // If shared_library has been explicitly set to true then it is incompatible 2608 // with api_only: true. 2609 if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) { 2610 ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true") 2611 } 2612 // Set shared_library: false. 2613 module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false) 2614 } 2615 2616 if module.initCommonAfterDefaultsApplied(ctx) { 2617 module.CreateInternalModules(ctx) 2618 } 2619 }) 2620 return module 2621} 2622 2623// 2624// SDK library prebuilts 2625// 2626 2627// Properties associated with each api scope. 2628type sdkLibraryScopeProperties struct { 2629 Jars []string `android:"path"` 2630 2631 Sdk_version *string 2632 2633 // List of shared java libs that this module has dependencies to 2634 Libs []string 2635 2636 // The stubs source. 2637 Stub_srcs []string `android:"path"` 2638 2639 // The current.txt 2640 Current_api *string `android:"path"` 2641 2642 // The removed.txt 2643 Removed_api *string `android:"path"` 2644 2645 // Annotation zip 2646 Annotations *string `android:"path"` 2647} 2648 2649type sdkLibraryImportProperties struct { 2650 // List of shared java libs, common to all scopes, that this module has 2651 // dependencies to 2652 Libs []string 2653 2654 // If set to true, compile dex files for the stubs. Defaults to false. 2655 Compile_dex *bool 2656 2657 // If not empty, classes are restricted to the specified packages and their sub-packages. 2658 Permitted_packages []string 2659 2660 // Name of the source soong module that gets shadowed by this prebuilt 2661 // If unspecified, follows the naming convention that the source module of 2662 // the prebuilt is Name() without "prebuilt_" prefix 2663 Source_module_name *string 2664} 2665 2666type SdkLibraryImport struct { 2667 android.ModuleBase 2668 android.DefaultableModuleBase 2669 prebuilt android.Prebuilt 2670 android.ApexModuleBase 2671 2672 hiddenAPI 2673 dexpreopter 2674 2675 properties sdkLibraryImportProperties 2676 2677 // Map from api scope to the scope specific property structure. 2678 scopeProperties map[*apiScope]*sdkLibraryScopeProperties 2679 2680 commonToSdkLibraryAndImport 2681 2682 // The reference to the xml permissions module created by the source module. 2683 // Is nil if the source module does not exist. 2684 xmlPermissionsFileModule *sdkLibraryXml 2685 2686 // Build path to the dex implementation jar obtained from the prebuilt_apex, if any. 2687 dexJarFile OptionalDexJarPath 2688 dexJarFileErr error 2689 2690 // Expected install file path of the source module(sdk_library) 2691 // or dex implementation jar obtained from the prebuilt_apex, if any. 2692 installFile android.Path 2693} 2694 2695var _ SdkLibraryDependency = (*SdkLibraryImport)(nil) 2696 2697// The type of a structure that contains a field of type sdkLibraryScopeProperties 2698// for each apiscope in allApiScopes, e.g. something like: 2699// 2700// struct { 2701// Public sdkLibraryScopeProperties 2702// System sdkLibraryScopeProperties 2703// ... 2704// } 2705var allScopeStructType = createAllScopePropertiesStructType() 2706 2707// Dynamically create a structure type for each apiscope in allApiScopes. 2708func createAllScopePropertiesStructType() reflect.Type { 2709 var fields []reflect.StructField 2710 for _, apiScope := range AllApiScopes { 2711 field := reflect.StructField{ 2712 Name: apiScope.fieldName, 2713 Type: reflect.TypeOf(sdkLibraryScopeProperties{}), 2714 } 2715 fields = append(fields, field) 2716 } 2717 2718 return reflect.StructOf(fields) 2719} 2720 2721// Create an instance of the scope specific structure type and return a map 2722// from apiscope to a pointer to each scope specific field. 2723func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProperties) { 2724 allScopePropertiesPtr := reflect.New(allScopeStructType) 2725 allScopePropertiesStruct := allScopePropertiesPtr.Elem() 2726 scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties) 2727 2728 for _, apiScope := range AllApiScopes { 2729 field := allScopePropertiesStruct.FieldByName(apiScope.fieldName) 2730 scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties) 2731 } 2732 2733 return allScopePropertiesPtr.Interface(), scopeProperties 2734} 2735 2736// java_sdk_library_import imports a prebuilt java_sdk_library. 2737func sdkLibraryImportFactory() android.Module { 2738 module := &SdkLibraryImport{} 2739 2740 allScopeProperties, scopeToProperties := createPropertiesInstance() 2741 module.scopeProperties = scopeToProperties 2742 module.AddProperties(&module.properties, allScopeProperties, &module.importDexpreoptProperties) 2743 2744 // Initialize information common between source and prebuilt. 2745 module.initCommon(module) 2746 2747 android.InitPrebuiltModule(module, &[]string{""}) 2748 android.InitApexModule(module) 2749 InitJavaModule(module, android.HostAndDeviceSupported) 2750 2751 module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { 2752 if module.initCommonAfterDefaultsApplied(mctx) { 2753 module.createInternalModules(mctx) 2754 } 2755 }) 2756 return module 2757} 2758 2759var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil) 2760 2761func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string { 2762 return module.properties.Permitted_packages 2763} 2764 2765func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt { 2766 return &module.prebuilt 2767} 2768 2769func (module *SdkLibraryImport) Name() string { 2770 return module.prebuilt.Name(module.ModuleBase.Name()) 2771} 2772 2773func (module *SdkLibraryImport) BaseModuleName() string { 2774 return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name()) 2775} 2776 2777func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) { 2778 2779 // If the build is configured to use prebuilts then force this to be preferred. 2780 if mctx.Config().AlwaysUsePrebuiltSdks() { 2781 module.prebuilt.ForcePrefer() 2782 } 2783 2784 for apiScope, scopeProperties := range module.scopeProperties { 2785 if len(scopeProperties.Jars) == 0 { 2786 continue 2787 } 2788 2789 module.createJavaImportForStubs(mctx, apiScope, scopeProperties) 2790 2791 if len(scopeProperties.Stub_srcs) > 0 { 2792 module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties) 2793 } 2794 2795 if scopeProperties.Current_api != nil { 2796 module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties) 2797 } 2798 } 2799 2800 javaSdkLibraries := javaSdkLibraries(mctx.Config()) 2801 javaSdkLibrariesLock.Lock() 2802 defer javaSdkLibrariesLock.Unlock() 2803 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName()) 2804} 2805 2806func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { 2807 // Creates a java import for the jar with ".stubs" suffix 2808 props := struct { 2809 Name *string 2810 Source_module_name *string 2811 Created_by_java_sdk_library_name *string 2812 Sdk_version *string 2813 Libs []string 2814 Jars []string 2815 Compile_dex *bool 2816 Is_stubs_module *bool 2817 2818 android.UserSuppliedPrebuiltProperties 2819 }{} 2820 props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) 2821 props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName())) 2822 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) 2823 props.Sdk_version = scopeProperties.Sdk_version 2824 // Prepend any of the libs from the legacy public properties to the libs for each of the 2825 // scopes to avoid having to duplicate them in each scope. 2826 props.Libs = append(module.properties.Libs, scopeProperties.Libs...) 2827 props.Jars = scopeProperties.Jars 2828 2829 // The imports are preferred if the java_sdk_library_import is preferred. 2830 props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) 2831 2832 // The imports need to be compiled to dex if the java_sdk_library_import requests it. 2833 compileDex := module.properties.Compile_dex 2834 if module.stubLibrariesCompiledForDex() { 2835 compileDex = proptools.BoolPtr(true) 2836 } 2837 props.Compile_dex = compileDex 2838 props.Is_stubs_module = proptools.BoolPtr(true) 2839 2840 mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2841} 2842 2843func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { 2844 props := struct { 2845 Name *string 2846 Source_module_name *string 2847 Created_by_java_sdk_library_name *string 2848 Srcs []string 2849 2850 android.UserSuppliedPrebuiltProperties 2851 }{} 2852 props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope)) 2853 props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName())) 2854 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) 2855 props.Srcs = scopeProperties.Stub_srcs 2856 2857 // The stubs source is preferred if the java_sdk_library_import is preferred. 2858 props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) 2859 2860 mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2861} 2862 2863func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { 2864 api_file := scopeProperties.Current_api 2865 api_surface := &apiScope.name 2866 2867 props := struct { 2868 Name *string 2869 Source_module_name *string 2870 Created_by_java_sdk_library_name *string 2871 Api_surface *string 2872 Api_file *string 2873 Visibility []string 2874 }{} 2875 2876 props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution") 2877 props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution") 2878 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) 2879 props.Api_surface = api_surface 2880 props.Api_file = api_file 2881 props.Visibility = []string{"//visibility:override", "//visibility:public"} 2882 2883 mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) 2884} 2885 2886// Add the dependencies on the child module in the component deps mutator so that it 2887// creates references to the prebuilt and not the source modules. 2888func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 2889 for apiScope, scopeProperties := range module.scopeProperties { 2890 if len(scopeProperties.Jars) == 0 { 2891 continue 2892 } 2893 2894 // Add dependencies to the prebuilt stubs library 2895 ctx.AddVariationDependencies(nil, apiScope.prebuiltStubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope))) 2896 2897 if len(scopeProperties.Stub_srcs) > 0 { 2898 // Add dependencies to the prebuilt stubs source library 2899 ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope))) 2900 } 2901 } 2902} 2903 2904// Add other dependencies as normal. 2905func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) { 2906 2907 implName := module.implLibraryModuleName() 2908 if ctx.OtherModuleExists(implName) { 2909 ctx.AddVariationDependencies(nil, implLibraryTag, implName) 2910 2911 xmlPermissionsModuleName := module.xmlPermissionsModuleName() 2912 if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) { 2913 // Add dependency to the rule for generating the xml permissions file 2914 ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName) 2915 } 2916 } 2917} 2918 2919var _ android.ApexModule = (*SdkLibraryImport)(nil) 2920 2921// Implements android.ApexModule 2922func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool { 2923 depTag := mctx.OtherModuleDependencyTag(dep) 2924 if depTag == xmlPermissionsFileTag { 2925 return true 2926 } 2927 2928 // None of the other dependencies of the java_sdk_library_import are in the same apex 2929 // as the one that references this module. 2930 return false 2931} 2932 2933// Implements android.ApexModule 2934func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, 2935 sdkVersion android.ApiLevel) error { 2936 // we don't check prebuilt modules for sdk_version 2937 return nil 2938} 2939 2940// Implements android.ApexModule 2941func (module *SdkLibraryImport) UniqueApexVariations() bool { 2942 return module.uniqueApexVariations() 2943} 2944 2945// MinSdkVersion - Implements hiddenAPIModule 2946func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 2947 return android.NoneApiLevel 2948} 2949 2950var _ hiddenAPIModule = (*SdkLibraryImport)(nil) 2951 2952func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) { 2953 paths, err := module.commonOutputFiles(tag) 2954 if paths != nil || err != nil { 2955 return paths, err 2956 } 2957 if module.implLibraryModule != nil { 2958 return module.implLibraryModule.OutputFiles(tag) 2959 } else { 2960 return nil, nil 2961 } 2962} 2963 2964func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { 2965 module.generateCommonBuildActions(ctx) 2966 2967 // Assume that source module(sdk_library) is installed in /<sdk_library partition>/framework 2968 module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar") 2969 2970 // Record the paths to the prebuilt stubs library and stubs source. 2971 ctx.VisitDirectDeps(func(to android.Module) { 2972 tag := ctx.OtherModuleDependencyTag(to) 2973 2974 // Extract information from any of the scope specific dependencies. 2975 if scopeTag, ok := tag.(scopeDependencyTag); ok { 2976 apiScope := scopeTag.apiScope 2977 scopePaths := module.getScopePathsCreateIfNeeded(apiScope) 2978 2979 // Extract information from the dependency. The exact information extracted 2980 // is determined by the nature of the dependency which is determined by the tag. 2981 scopeTag.extractDepInfo(ctx, to, scopePaths) 2982 } else if tag == implLibraryTag { 2983 if implLibrary, ok := to.(*Library); ok { 2984 module.implLibraryModule = implLibrary 2985 } else { 2986 ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to) 2987 } 2988 } else if tag == xmlPermissionsFileTag { 2989 if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok { 2990 module.xmlPermissionsFileModule = xmlPermissionsFileModule 2991 } else { 2992 ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to) 2993 } 2994 } 2995 }) 2996 2997 // Populate the scope paths with information from the properties. 2998 for apiScope, scopeProperties := range module.scopeProperties { 2999 if len(scopeProperties.Jars) == 0 { 3000 continue 3001 } 3002 3003 paths := module.getScopePathsCreateIfNeeded(apiScope) 3004 paths.annotationsZip = android.OptionalPathForModuleSrc(ctx, scopeProperties.Annotations) 3005 paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api) 3006 paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api) 3007 } 3008 3009 if ctx.Device() { 3010 // If this is a variant created for a prebuilt_apex then use the dex implementation jar 3011 // obtained from the associated deapexer module. 3012 ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 3013 if ai.ForPrebuiltApex { 3014 // Get the path of the dex implementation jar from the `deapexer` module. 3015 di, err := android.FindDeapexerProviderForModule(ctx) 3016 if err != nil { 3017 // An error was found, possibly due to multiple apexes in the tree that export this library 3018 // Defer the error till a client tries to call DexJarBuildPath 3019 module.dexJarFileErr = err 3020 module.initHiddenAPIError(err) 3021 return 3022 } 3023 dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName()) 3024 if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { 3025 dexJarFile := makeDexJarPathFromPath(dexOutputPath) 3026 module.dexJarFile = dexJarFile 3027 installPath := android.PathForModuleInPartitionInstall( 3028 ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative) 3029 module.installFile = installPath 3030 module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) 3031 3032 module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath) 3033 module.dexpreopter.isSDKLibrary = true 3034 module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter) 3035 3036 if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil { 3037 module.dexpreopter.inputProfilePathOnHost = profilePath 3038 } 3039 } else { 3040 // This should never happen as a variant for a prebuilt_apex is only created if the 3041 // prebuilt_apex has been configured to export the java library dex file. 3042 ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName()) 3043 } 3044 } 3045 } 3046} 3047 3048func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths { 3049 3050 // For consistency with SdkLibrary make the implementation jar available to libraries that 3051 // are within the same APEX. 3052 implLibraryModule := module.implLibraryModule 3053 if implLibraryModule != nil && withinSameApexesAs(ctx, module) { 3054 if headerJars { 3055 return implLibraryModule.HeaderJars() 3056 } else { 3057 return implLibraryModule.ImplementationJars() 3058 } 3059 } 3060 3061 return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) 3062} 3063 3064// to satisfy SdkLibraryDependency interface 3065func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { 3066 // This module is just a wrapper for the prebuilt stubs. 3067 return module.sdkJars(ctx, sdkVersion, true) 3068} 3069 3070// to satisfy UsesLibraryDependency interface 3071func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { 3072 // The dex implementation jar extracted from the .apex file should be used in preference to the 3073 // source. 3074 if module.dexJarFileErr != nil { 3075 ctx.ModuleErrorf(module.dexJarFileErr.Error()) 3076 } 3077 if module.dexJarFile.IsSet() { 3078 return module.dexJarFile 3079 } 3080 if module.implLibraryModule == nil { 3081 return makeUnsetDexJarPath() 3082 } else { 3083 return module.implLibraryModule.DexJarBuildPath(ctx) 3084 } 3085} 3086 3087// to satisfy UsesLibraryDependency interface 3088func (module *SdkLibraryImport) DexJarInstallPath() android.Path { 3089 return module.installFile 3090} 3091 3092// to satisfy UsesLibraryDependency interface 3093func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { 3094 return nil 3095} 3096 3097// to satisfy apex.javaDependency interface 3098func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path { 3099 if module.implLibraryModule == nil { 3100 return nil 3101 } else { 3102 return module.implLibraryModule.JacocoReportClassesFile() 3103 } 3104} 3105 3106// to satisfy apex.javaDependency interface 3107func (module *SdkLibraryImport) LintDepSets() LintDepSets { 3108 if module.implLibraryModule == nil { 3109 return LintDepSets{} 3110 } else { 3111 return module.implLibraryModule.LintDepSets() 3112 } 3113} 3114 3115func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool { 3116 if module.implLibraryModule == nil { 3117 return false 3118 } else { 3119 return module.implLibraryModule.GetStrictUpdatabilityLinting() 3120 } 3121} 3122 3123func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) { 3124 if module.implLibraryModule != nil { 3125 module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting) 3126 } 3127} 3128 3129// to satisfy apex.javaDependency interface 3130func (module *SdkLibraryImport) Stem() string { 3131 return module.BaseModuleName() 3132} 3133 3134var _ ApexDependency = (*SdkLibraryImport)(nil) 3135 3136// to satisfy java.ApexDependency interface 3137func (module *SdkLibraryImport) HeaderJars() android.Paths { 3138 if module.implLibraryModule == nil { 3139 return nil 3140 } else { 3141 return module.implLibraryModule.HeaderJars() 3142 } 3143} 3144 3145// to satisfy java.ApexDependency interface 3146func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths { 3147 if module.implLibraryModule == nil { 3148 return nil 3149 } else { 3150 return module.implLibraryModule.ImplementationAndResourcesJars() 3151 } 3152} 3153 3154// to satisfy java.DexpreopterInterface interface 3155func (module *SdkLibraryImport) IsInstallable() bool { 3156 return true 3157} 3158 3159var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil) 3160 3161func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { 3162 name := module.BaseModuleName() 3163 return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter) 3164} 3165 3166func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool { 3167 return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided) 3168} 3169 3170// java_sdk_library_xml 3171type sdkLibraryXml struct { 3172 android.ModuleBase 3173 android.DefaultableModuleBase 3174 android.ApexModuleBase 3175 3176 properties sdkLibraryXmlProperties 3177 3178 outputFilePath android.OutputPath 3179 installDirPath android.InstallPath 3180 3181 hideApexVariantFromMake bool 3182} 3183 3184type sdkLibraryXmlProperties struct { 3185 // canonical name of the lib 3186 Lib_name *string 3187 3188 // Signals that this shared library is part of the bootclasspath starting 3189 // on the version indicated in this attribute. 3190 // 3191 // This will make platforms at this level and above to ignore 3192 // <uses-library> tags with this library name because the library is already 3193 // available 3194 On_bootclasspath_since *string 3195 3196 // Signals that this shared library was part of the bootclasspath before 3197 // (but not including) the version indicated in this attribute. 3198 // 3199 // The system will automatically add a <uses-library> tag with this library to 3200 // apps that target any SDK less than the version indicated in this attribute. 3201 On_bootclasspath_before *string 3202 3203 // Indicates that PackageManager should ignore this shared library if the 3204 // platform is below the version indicated in this attribute. 3205 // 3206 // This means that the device won't recognise this library as installed. 3207 Min_device_sdk *string 3208 3209 // Indicates that PackageManager should ignore this shared library if the 3210 // platform is above the version indicated in this attribute. 3211 // 3212 // This means that the device won't recognise this library as installed. 3213 Max_device_sdk *string 3214 3215 // The SdkLibrary's min api level as a string 3216 // 3217 // This value comes from the ApiLevel of the MinSdkVersion property. 3218 Sdk_library_min_api_level *string 3219 3220 // Uses-libs dependencies that the shared library requires to work correctly. 3221 // 3222 // This will add dependency="foo:bar" to the <library> section. 3223 Uses_libs_dependencies []string 3224} 3225 3226// java_sdk_library_xml builds the permission xml file for a java_sdk_library. 3227// Not to be used directly by users. java_sdk_library internally uses this. 3228func sdkLibraryXmlFactory() android.Module { 3229 module := &sdkLibraryXml{} 3230 3231 module.AddProperties(&module.properties) 3232 3233 android.InitApexModule(module) 3234 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 3235 3236 return module 3237} 3238 3239func (module *sdkLibraryXml) UniqueApexVariations() bool { 3240 // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the 3241 // mounted APEX, which contains the name of the APEX. 3242 return true 3243} 3244 3245// from android.PrebuiltEtcModule 3246func (module *sdkLibraryXml) BaseDir() string { 3247 return "etc" 3248} 3249 3250// from android.PrebuiltEtcModule 3251func (module *sdkLibraryXml) SubDir() string { 3252 return "permissions" 3253} 3254 3255var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil) 3256 3257// from android.ApexModule 3258func (module *sdkLibraryXml) AvailableFor(what string) bool { 3259 return true 3260} 3261 3262func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { 3263 // do nothing 3264} 3265 3266var _ android.ApexModule = (*sdkLibraryXml)(nil) 3267 3268// Implements android.ApexModule 3269func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, 3270 sdkVersion android.ApiLevel) error { 3271 // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked 3272 return nil 3273} 3274 3275// File path to the runtime implementation library 3276func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string { 3277 implName := proptools.String(module.properties.Lib_name) 3278 if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() { 3279 // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name. 3280 // In most cases, this works fine. But when apex_name is set or override_apex is used 3281 // this can be wrong. 3282 return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName) 3283 } 3284 partition := "system" 3285 if module.SocSpecific() { 3286 partition = "vendor" 3287 } else if module.DeviceSpecific() { 3288 partition = "odm" 3289 } else if module.ProductSpecific() { 3290 partition = "product" 3291 } else if module.SystemExtSpecific() { 3292 partition = "system_ext" 3293 } 3294 return "/" + partition + "/framework/" + implName + ".jar" 3295} 3296 3297func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string { 3298 if value == nil { 3299 return "" 3300 } 3301 apiLevel, err := android.ApiLevelFromUser(ctx, *value) 3302 if err != nil { 3303 // attributes in bp files have underscores but in the xml have dashes. 3304 ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error()) 3305 return "" 3306 } 3307 if apiLevel.IsCurrent() { 3308 // passing "current" would always mean a future release, never the current (or the current in 3309 // progress) which means some conditions would never be triggered. 3310 ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), 3311 `"current" is not an allowed value for this attribute`) 3312 return "" 3313 } 3314 // "safeValue" is safe because it translates finalized codenames to a string 3315 // with their SDK int. 3316 safeValue := apiLevel.String() 3317 return formattedOptionalAttribute(attrName, &safeValue) 3318} 3319 3320// formats an attribute for the xml permissions file if the value is not null 3321// returns empty string otherwise 3322func formattedOptionalAttribute(attrName string, value *string) string { 3323 if value == nil { 3324 return "" 3325 } 3326 return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value) 3327} 3328 3329func formattedDependenciesAttribute(dependencies []string) string { 3330 if dependencies == nil { 3331 return "" 3332 } 3333 return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":")) 3334} 3335 3336func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string { 3337 libName := proptools.String(module.properties.Lib_name) 3338 libNameAttr := formattedOptionalAttribute("name", &libName) 3339 filePath := module.implPath(ctx) 3340 filePathAttr := formattedOptionalAttribute("file", &filePath) 3341 implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since) 3342 implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before) 3343 minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk) 3344 maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk) 3345 dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies) 3346 // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that). 3347 // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T 3348 var libraryTag string 3349 if module.properties.Min_device_sdk != nil { 3350 libraryTag = " <apex-library\n" 3351 } else { 3352 libraryTag = " <library\n" 3353 } 3354 3355 return strings.Join([]string{ 3356 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", 3357 "<!-- Copyright (C) 2018 The Android Open Source Project\n", 3358 "\n", 3359 " Licensed under the Apache License, Version 2.0 (the \"License\");\n", 3360 " you may not use this file except in compliance with the License.\n", 3361 " You may obtain a copy of the License at\n", 3362 "\n", 3363 " http://www.apache.org/licenses/LICENSE-2.0\n", 3364 "\n", 3365 " Unless required by applicable law or agreed to in writing, software\n", 3366 " distributed under the License is distributed on an \"AS IS\" BASIS,\n", 3367 " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", 3368 " See the License for the specific language governing permissions and\n", 3369 " limitations under the License.\n", 3370 "-->\n", 3371 "<permissions>\n", 3372 libraryTag, 3373 libNameAttr, 3374 filePathAttr, 3375 implicitFromAttr, 3376 implicitUntilAttr, 3377 minSdkAttr, 3378 maxSdkAttr, 3379 dependenciesAttr, 3380 " />\n", 3381 "</permissions>\n", 3382 }, "") 3383} 3384 3385func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) { 3386 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 3387 module.hideApexVariantFromMake = !apexInfo.IsForPlatform() 3388 3389 libName := proptools.String(module.properties.Lib_name) 3390 module.selfValidate(ctx) 3391 xmlContent := module.permissionsContents(ctx) 3392 3393 module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath 3394 android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent) 3395 3396 module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir()) 3397 ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath) 3398 3399 ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "") 3400} 3401 3402func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries { 3403 if module.hideApexVariantFromMake { 3404 return []android.AndroidMkEntries{{ 3405 Disabled: true, 3406 }} 3407 } 3408 3409 return []android.AndroidMkEntries{{ 3410 Class: "ETC", 3411 OutputFile: android.OptionalPathForPath(module.outputFilePath), 3412 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 3413 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 3414 entries.SetString("LOCAL_MODULE_TAGS", "optional") 3415 entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String()) 3416 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base()) 3417 }, 3418 }, 3419 }} 3420} 3421 3422func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) { 3423 module.validateAtLeastTAttributes(ctx) 3424 module.validateMinAndMaxDeviceSdk(ctx) 3425 module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx) 3426 module.validateOnBootclasspathBeforeRequirements(ctx) 3427} 3428 3429func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) { 3430 t := android.ApiLevelOrPanic(ctx, "Tiramisu") 3431 module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk") 3432 module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk") 3433 module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before") 3434 module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since") 3435} 3436 3437func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) { 3438 if attr != nil { 3439 if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil { 3440 // we will inform the user of invalid inputs when we try to write the 3441 // permissions xml file so we don't need to do it here 3442 if t.GreaterThan(level) { 3443 ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T") 3444 } 3445 } 3446 } 3447} 3448 3449func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) { 3450 if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil { 3451 min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk) 3452 max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk) 3453 if minErr == nil && maxErr == nil { 3454 // we will inform the user of invalid inputs when we try to write the 3455 // permissions xml file so we don't need to do it here 3456 if min.GreaterThan(max) { 3457 ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk") 3458 } 3459 } 3460 } 3461} 3462 3463func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) { 3464 moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level) 3465 if module.properties.Min_device_sdk != nil { 3466 api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk) 3467 if err == nil { 3468 if moduleMinApi.GreaterThan(api) { 3469 ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi) 3470 } 3471 } 3472 } 3473 if module.properties.Max_device_sdk != nil { 3474 api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk) 3475 if err == nil { 3476 if moduleMinApi.GreaterThan(api) { 3477 ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi) 3478 } 3479 } 3480 } 3481} 3482 3483func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) { 3484 moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level) 3485 if module.properties.On_bootclasspath_before != nil { 3486 t := android.ApiLevelOrPanic(ctx, "Tiramisu") 3487 // if we use the attribute, then we need to do this validation 3488 if moduleMinApi.LessThan(t) { 3489 // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+) 3490 if module.properties.Min_device_sdk == nil { 3491 ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T") 3492 } 3493 } 3494 } 3495} 3496 3497type sdkLibrarySdkMemberType struct { 3498 android.SdkMemberTypeBase 3499} 3500 3501func (s *sdkLibrarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) { 3502 ctx.AddVariationDependencies(nil, dependencyTag, names...) 3503} 3504 3505func (s *sdkLibrarySdkMemberType) IsInstance(module android.Module) bool { 3506 _, ok := module.(*SdkLibrary) 3507 return ok 3508} 3509 3510func (s *sdkLibrarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { 3511 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_sdk_library_import") 3512} 3513 3514func (s *sdkLibrarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { 3515 return &sdkLibrarySdkMemberProperties{} 3516} 3517 3518var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{ 3519 android.SdkMemberTypeBase{ 3520 PropertyName: "java_sdk_libs", 3521 SupportsSdk: true, 3522 }, 3523} 3524 3525type sdkLibrarySdkMemberProperties struct { 3526 android.SdkMemberPropertiesBase 3527 3528 // Stem name for files in the sdk snapshot. 3529 // 3530 // This is used to construct the path names of various sdk library files in the sdk snapshot to 3531 // make sure that they match the finalized versions of those files in prebuilts/sdk. 3532 // 3533 // This property is marked as keep so that it will be kept in all instances of this struct, will 3534 // not be cleared but will be copied to common structs. That is needed because this field is used 3535 // to construct many file names for other parts of this struct and so it needs to be present in 3536 // all structs. If it was not marked as keep then it would be cleared in some structs and so would 3537 // be unavailable for generating file names if there were other properties that were still set. 3538 Stem string `sdk:"keep"` 3539 3540 // Scope to per scope properties. 3541 Scopes map[*apiScope]*scopeProperties 3542 3543 // The Java stubs source files. 3544 Stub_srcs []string 3545 3546 // The naming scheme. 3547 Naming_scheme *string 3548 3549 // True if the java_sdk_library_import is for a shared library, false 3550 // otherwise. 3551 Shared_library *bool 3552 3553 // True if the stub imports should produce dex jars. 3554 Compile_dex *bool 3555 3556 // The paths to the doctag files to add to the prebuilt. 3557 Doctag_paths android.Paths 3558 3559 Permitted_packages []string 3560 3561 // Signals that this shared library is part of the bootclasspath starting 3562 // on the version indicated in this attribute. 3563 // 3564 // This will make platforms at this level and above to ignore 3565 // <uses-library> tags with this library name because the library is already 3566 // available 3567 On_bootclasspath_since *string 3568 3569 // Signals that this shared library was part of the bootclasspath before 3570 // (but not including) the version indicated in this attribute. 3571 // 3572 // The system will automatically add a <uses-library> tag with this library to 3573 // apps that target any SDK less than the version indicated in this attribute. 3574 On_bootclasspath_before *string 3575 3576 // Indicates that PackageManager should ignore this shared library if the 3577 // platform is below the version indicated in this attribute. 3578 // 3579 // This means that the device won't recognise this library as installed. 3580 Min_device_sdk *string 3581 3582 // Indicates that PackageManager should ignore this shared library if the 3583 // platform is above the version indicated in this attribute. 3584 // 3585 // This means that the device won't recognise this library as installed. 3586 Max_device_sdk *string 3587 3588 DexPreoptProfileGuided *bool `supported_build_releases:"UpsideDownCake+"` 3589} 3590 3591type scopeProperties struct { 3592 Jars android.Paths 3593 StubsSrcJar android.Path 3594 CurrentApiFile android.Path 3595 RemovedApiFile android.Path 3596 AnnotationsZip android.Path `supported_build_releases:"Tiramisu+"` 3597 SdkVersion string 3598} 3599 3600func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { 3601 sdk := variant.(*SdkLibrary) 3602 3603 // Copy the stem name for files in the sdk snapshot. 3604 s.Stem = sdk.distStem() 3605 3606 s.Scopes = make(map[*apiScope]*scopeProperties) 3607 for _, apiScope := range AllApiScopes { 3608 paths := sdk.findScopePaths(apiScope) 3609 if paths == nil { 3610 continue 3611 } 3612 3613 jars := paths.stubsImplPath 3614 if len(jars) > 0 { 3615 properties := scopeProperties{} 3616 properties.Jars = jars 3617 properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope) 3618 properties.StubsSrcJar = paths.stubsSrcJar.Path() 3619 if paths.currentApiFilePath.Valid() { 3620 properties.CurrentApiFile = paths.currentApiFilePath.Path() 3621 } 3622 if paths.removedApiFilePath.Valid() { 3623 properties.RemovedApiFile = paths.removedApiFilePath.Path() 3624 } 3625 // The annotations zip is only available for modules that set annotations_enabled: true. 3626 if paths.annotationsZip.Valid() { 3627 properties.AnnotationsZip = paths.annotationsZip.Path() 3628 } 3629 s.Scopes[apiScope] = &properties 3630 } 3631 } 3632 3633 s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme 3634 s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary()) 3635 s.Compile_dex = sdk.dexProperties.Compile_dex 3636 s.Doctag_paths = sdk.doctagPaths 3637 s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars() 3638 s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since 3639 s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before 3640 s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk 3641 s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk 3642 3643 implLibrary := sdk.getImplLibraryModule() 3644 if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { 3645 s.DexPreoptProfileGuided = proptools.BoolPtr(true) 3646 } 3647} 3648 3649func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { 3650 if s.Naming_scheme != nil { 3651 propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme)) 3652 } 3653 if s.Shared_library != nil { 3654 propertySet.AddProperty("shared_library", *s.Shared_library) 3655 } 3656 if s.Compile_dex != nil { 3657 propertySet.AddProperty("compile_dex", *s.Compile_dex) 3658 } 3659 if len(s.Permitted_packages) > 0 { 3660 propertySet.AddProperty("permitted_packages", s.Permitted_packages) 3661 } 3662 dexPreoptSet := propertySet.AddPropertySet("dex_preopt") 3663 if s.DexPreoptProfileGuided != nil { 3664 dexPreoptSet.AddProperty("profile_guided", proptools.Bool(s.DexPreoptProfileGuided)) 3665 } 3666 3667 stem := s.Stem 3668 3669 for _, apiScope := range AllApiScopes { 3670 if properties, ok := s.Scopes[apiScope]; ok { 3671 scopeSet := propertySet.AddPropertySet(apiScope.propertyName) 3672 3673 scopeDir := apiScope.snapshotRelativeDir() 3674 3675 var jars []string 3676 for _, p := range properties.Jars { 3677 dest := filepath.Join(scopeDir, stem+"-stubs.jar") 3678 ctx.SnapshotBuilder().CopyToSnapshot(p, dest) 3679 jars = append(jars, dest) 3680 } 3681 scopeSet.AddProperty("jars", jars) 3682 3683 if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") { 3684 // Copy the stubs source jar into the snapshot zip as is. 3685 srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar") 3686 ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath) 3687 scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath}) 3688 } else { 3689 // Merge the stubs source jar into the snapshot zip so that when it is unpacked 3690 // the source files are also unpacked. 3691 snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources") 3692 ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir) 3693 scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir}) 3694 } 3695 3696 if properties.CurrentApiFile != nil { 3697 currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem) 3698 ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath) 3699 scopeSet.AddProperty("current_api", currentApiSnapshotPath) 3700 } 3701 3702 if properties.RemovedApiFile != nil { 3703 removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem) 3704 ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath) 3705 scopeSet.AddProperty("removed_api", removedApiSnapshotPath) 3706 } 3707 3708 if properties.AnnotationsZip != nil { 3709 annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip") 3710 ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath) 3711 scopeSet.AddProperty("annotations", annotationsSnapshotPath) 3712 } 3713 3714 if properties.SdkVersion != "" { 3715 scopeSet.AddProperty("sdk_version", properties.SdkVersion) 3716 } 3717 } 3718 } 3719 3720 if len(s.Doctag_paths) > 0 { 3721 dests := []string{} 3722 for _, p := range s.Doctag_paths { 3723 dest := filepath.Join("doctags", p.Rel()) 3724 ctx.SnapshotBuilder().CopyToSnapshot(p, dest) 3725 dests = append(dests, dest) 3726 } 3727 propertySet.AddProperty("doctag_files", dests) 3728 } 3729} 3730