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