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