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