1// Copyright (C) 2021 The Android Open Source Project 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 api 16 17import ( 18 "fmt" 19 "sort" 20 "strings" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/genrule" 26 "android/soong/java" 27) 28 29const art = "art.module.public.api" 30const conscrypt = "conscrypt.module.public.api" 31const i18n = "i18n.module.public.api" 32const virtualization = "framework-virtualization" 33const location = "framework-location" 34 35var core_libraries_modules = []string{art, conscrypt, i18n} 36 37// List of modules that are not yet updatable, and hence they can still compile 38// against hidden APIs. These modules are filtered out when building the 39// updatable-framework-module-impl (because updatable-framework-module-impl is 40// built against module_current SDK). Instead they are directly statically 41// linked into the all-framework-module-lib, which is building against hidden 42// APIs. 43// In addition, the modules in this list are allowed to contribute to test APIs 44// stubs. 45var non_updatable_modules = []string{virtualization, location} 46 47// The intention behind this soong plugin is to generate a number of "merged" 48// API-related modules that would otherwise require a large amount of very 49// similar Android.bp boilerplate to define. For example, the merged current.txt 50// API definitions (created by merging the non-updatable current.txt with all 51// the module current.txts). This simplifies the addition of new android 52// modules, by reducing the number of genrules etc a new module must be added to. 53 54// The properties of the combined_apis module type. 55type CombinedApisProperties struct { 56 // Module libraries in the bootclasspath 57 Bootclasspath []string 58 // Module libraries on the bootclasspath if include_nonpublic_framework_api is true. 59 Conditional_bootclasspath []string 60 // Module libraries in system server 61 System_server_classpath []string 62} 63 64type CombinedApis struct { 65 android.ModuleBase 66 android.DefaultableModuleBase 67 68 properties CombinedApisProperties 69} 70 71func init() { 72 registerBuildComponents(android.InitRegistrationContext) 73} 74 75func registerBuildComponents(ctx android.RegistrationContext) { 76 ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory) 77 ctx.RegisterModuleType("combined_apis_defaults", CombinedApisModuleDefaultsFactory) 78} 79 80var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents) 81 82func (a *CombinedApis) apiFingerprintStubDeps() []string { 83 ret := []string{} 84 ret = append( 85 ret, 86 transformArray(a.properties.Bootclasspath, "", ".stubs")..., 87 ) 88 ret = append( 89 ret, 90 transformArray(a.properties.Bootclasspath, "", ".stubs.system")..., 91 ) 92 ret = append( 93 ret, 94 transformArray(a.properties.Bootclasspath, "", ".stubs.module_lib")..., 95 ) 96 ret = append( 97 ret, 98 transformArray(a.properties.System_server_classpath, "", ".stubs.system_server")..., 99 ) 100 return ret 101} 102 103func (a *CombinedApis) DepsMutator(ctx android.BottomUpMutatorContext) { 104 ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps()...) 105} 106 107func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) { 108 ctx.WalkDeps(func(child, parent android.Module) bool { 109 if _, ok := child.(java.AndroidLibraryDependency); ok && child.Name() != "framework-res" { 110 // Stubs of BCP and SSCP libraries should not have any dependencies on apps 111 // This check ensures that we do not run into circular dependencies when UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT=true 112 ctx.ModuleErrorf( 113 "Module %s is not a valid dependency of the stub library %s\n."+ 114 "If this dependency has been added via `libs` of java_sdk_library, please move it to `impl_only_libs`\n", 115 child.Name(), parent.Name()) 116 return false // error detected 117 } 118 return true 119 }) 120 121} 122 123type genruleProps struct { 124 Name *string 125 Cmd *string 126 Dists []android.Dist 127 Out []string 128 Srcs []string 129 Tools []string 130 Visibility []string 131} 132 133type libraryProps struct { 134 Name *string 135 Sdk_version *string 136 Static_libs []string 137 Visibility []string 138 Defaults []string 139 Is_stubs_module *bool 140} 141 142type fgProps struct { 143 Name *string 144 Srcs []string 145 Visibility []string 146} 147 148type defaultsProps struct { 149 Name *string 150 Api_surface *string 151 Api_contributions []string 152 Defaults_visibility []string 153 Previous_api *string 154} 155 156// Struct to pass parameters for the various merged [current|removed].txt file modules we create. 157type MergedTxtDefinition struct { 158 // "current.txt" or "removed.txt" 159 TxtFilename string 160 // Filename in the new dist dir. "android.txt" or "android-removed.txt" 161 DistFilename string 162 // The module for the non-updatable / non-module part of the api. 163 BaseTxt string 164 // The list of modules that are relevant for this merged txt. 165 Modules []string 166 // The output tag for each module to use.e.g. {.public.api.txt} for current.txt 167 ModuleTag string 168 // public, system, module-lib or system-server 169 Scope string 170} 171 172func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition, stubsTypeSuffix string, doDist bool) { 173 metalavaCmd := "$(location metalava)" 174 // Silence reflection warnings. See b/168689341 175 metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED " 176 metalavaCmd += " --quiet merge-signatures --format=v2 " 177 178 filename := txt.TxtFilename 179 if txt.Scope != "public" { 180 filename = txt.Scope + "-" + filename 181 } 182 moduleName := ctx.ModuleName() + stubsTypeSuffix + filename 183 184 props := genruleProps{} 185 props.Name = proptools.StringPtr(moduleName) 186 props.Tools = []string{"metalava"} 187 props.Out = []string{filename} 188 props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)") 189 props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...) 190 if doDist { 191 props.Dists = []android.Dist{ 192 { 193 Targets: []string{"droidcore"}, 194 Dir: proptools.StringPtr("api"), 195 Dest: proptools.StringPtr(filename), 196 }, 197 { 198 Targets: []string{"api_txt", "sdk"}, 199 Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"), 200 Dest: proptools.StringPtr(txt.DistFilename), 201 }, 202 } 203 } 204 props.Visibility = []string{"//visibility:public"} 205 ctx.CreateModule(genrule.GenRuleFactory, &props) 206} 207 208func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) { 209 for _, i := range []struct { 210 name string 211 tag string 212 modules []string 213 }{ 214 { 215 name: "all-modules-public-annotations", 216 tag: "{.public.annotations.zip}", 217 modules: modules, 218 }, { 219 name: "all-modules-system-annotations", 220 tag: "{.system.annotations.zip}", 221 modules: modules, 222 }, { 223 name: "all-modules-module-lib-annotations", 224 tag: "{.module-lib.annotations.zip}", 225 modules: modules, 226 }, { 227 name: "all-modules-system-server-annotations", 228 tag: "{.system-server.annotations.zip}", 229 modules: system_server_modules, 230 }, 231 } { 232 props := fgProps{} 233 props.Name = proptools.StringPtr(i.name) 234 props.Srcs = createSrcs(i.modules, i.tag) 235 ctx.CreateModule(android.FileGroupFactory, &props) 236 } 237} 238 239func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) { 240 props := libraryProps{} 241 props.Name = proptools.StringPtr("all-modules-public-stubs") 242 props.Static_libs = transformArray(modules, "", ".stubs") 243 props.Sdk_version = proptools.StringPtr("module_current") 244 props.Visibility = []string{"//frameworks/base"} 245 props.Is_stubs_module = proptools.BoolPtr(true) 246 ctx.CreateModule(java.LibraryFactory, &props) 247} 248 249func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []string) { 250 props := libraryProps{} 251 props.Name = proptools.StringPtr("all-modules-public-stubs-exportable") 252 props.Static_libs = transformArray(modules, "", ".stubs.exportable") 253 props.Sdk_version = proptools.StringPtr("module_current") 254 props.Visibility = []string{"//frameworks/base"} 255 props.Is_stubs_module = proptools.BoolPtr(true) 256 ctx.CreateModule(java.LibraryFactory, &props) 257} 258 259func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) { 260 // First create the all-updatable-modules-system-stubs 261 { 262 updatable_modules := removeAll(modules, non_updatable_modules) 263 props := libraryProps{} 264 props.Name = proptools.StringPtr("all-updatable-modules-system-stubs") 265 props.Static_libs = transformArray(updatable_modules, "", ".stubs.system") 266 props.Sdk_version = proptools.StringPtr("module_current") 267 props.Visibility = []string{"//frameworks/base"} 268 props.Is_stubs_module = proptools.BoolPtr(true) 269 ctx.CreateModule(java.LibraryFactory, &props) 270 } 271 // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules 272 // into all-modules-system-stubs. 273 { 274 props := libraryProps{} 275 props.Name = proptools.StringPtr("all-modules-system-stubs") 276 props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.system") 277 props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs") 278 props.Sdk_version = proptools.StringPtr("module_current") 279 props.Visibility = []string{"//frameworks/base"} 280 props.Is_stubs_module = proptools.BoolPtr(true) 281 ctx.CreateModule(java.LibraryFactory, &props) 282 } 283} 284 285func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []string) { 286 // First create the all-updatable-modules-system-stubs 287 { 288 updatable_modules := removeAll(modules, non_updatable_modules) 289 props := libraryProps{} 290 props.Name = proptools.StringPtr("all-updatable-modules-system-stubs-exportable") 291 props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system") 292 props.Sdk_version = proptools.StringPtr("module_current") 293 props.Visibility = []string{"//frameworks/base"} 294 props.Is_stubs_module = proptools.BoolPtr(true) 295 ctx.CreateModule(java.LibraryFactory, &props) 296 } 297 // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules 298 // into all-modules-system-stubs. 299 { 300 props := libraryProps{} 301 props.Name = proptools.StringPtr("all-modules-system-stubs-exportable") 302 props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.system") 303 props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs-exportable") 304 props.Sdk_version = proptools.StringPtr("module_current") 305 props.Visibility = []string{"//frameworks/base"} 306 props.Is_stubs_module = proptools.BoolPtr(true) 307 ctx.CreateModule(java.LibraryFactory, &props) 308 } 309} 310 311func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) { 312 props := libraryProps{} 313 props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs") 314 props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.test") 315 props.Sdk_version = proptools.StringPtr("module_current") 316 props.Visibility = []string{"//frameworks/base"} 317 props.Is_stubs_module = proptools.BoolPtr(true) 318 ctx.CreateModule(java.LibraryFactory, &props) 319} 320 321func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookContext) { 322 props := libraryProps{} 323 props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs-exportable") 324 props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test") 325 props.Sdk_version = proptools.StringPtr("module_current") 326 props.Visibility = []string{"//frameworks/base"} 327 props.Is_stubs_module = proptools.BoolPtr(true) 328 ctx.CreateModule(java.LibraryFactory, &props) 329} 330 331func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) { 332 // This module is for the "framework-all" module, which should not include the core libraries. 333 modules = removeAll(modules, core_libraries_modules) 334 // Remove the modules that belong to non-updatable APEXes since those are allowed to compile 335 // against unstable APIs. 336 modules = removeAll(modules, non_updatable_modules) 337 // First create updatable-framework-module-impl, which contains all updatable modules. 338 // This module compiles against module_lib SDK. 339 { 340 props := libraryProps{} 341 props.Name = proptools.StringPtr("updatable-framework-module-impl") 342 props.Static_libs = transformArray(modules, "", ".impl") 343 props.Sdk_version = proptools.StringPtr("module_current") 344 props.Visibility = []string{"//frameworks/base"} 345 ctx.CreateModule(java.LibraryFactory, &props) 346 } 347 348 // Now create all-framework-module-impl, which contains updatable-framework-module-impl 349 // and all non-updatable modules. This module compiles against hidden APIs. 350 { 351 props := libraryProps{} 352 props.Name = proptools.StringPtr("all-framework-module-impl") 353 props.Static_libs = transformArray(non_updatable_modules, "", ".impl") 354 props.Static_libs = append(props.Static_libs, "updatable-framework-module-impl") 355 props.Sdk_version = proptools.StringPtr("core_platform") 356 props.Visibility = []string{"//frameworks/base"} 357 ctx.CreateModule(java.LibraryFactory, &props) 358 } 359} 360 361func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules []string) { 362 // The user of this module compiles against the "core" SDK and against non-updatable modules, 363 // so remove to avoid dupes. 364 modules = removeAll(modules, core_libraries_modules) 365 modules = removeAll(modules, non_updatable_modules) 366 props := libraryProps{} 367 props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api-exportable") 368 props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib") 369 props.Sdk_version = proptools.StringPtr("module_current") 370 props.Visibility = []string{"//frameworks/base"} 371 props.Is_stubs_module = proptools.BoolPtr(true) 372 ctx.CreateModule(java.LibraryFactory, &props) 373} 374 375func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) { 376 // The user of this module compiles against the "core" SDK and against non-updatable modules, 377 // so remove to avoid dupes. 378 modules = removeAll(modules, core_libraries_modules) 379 modules = removeAll(modules, non_updatable_modules) 380 props := libraryProps{} 381 props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api") 382 props.Static_libs = transformArray(modules, "", ".stubs.module_lib") 383 props.Sdk_version = proptools.StringPtr("module_current") 384 props.Visibility = []string{"//frameworks/base"} 385 props.Is_stubs_module = proptools.BoolPtr(true) 386 ctx.CreateModule(java.LibraryFactory, &props) 387} 388 389func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) { 390 // The user of this module compiles against the "core" SDK and against non-updatable bootclasspathModules, 391 // so remove to avoid dupes. 392 bootclasspathModules := removeAll(bootclasspath, core_libraries_modules) 393 bootclasspathModules = removeAll(bootclasspath, non_updatable_modules) 394 modules := append( 395 // Include all the module-lib APIs from the bootclasspath libraries. 396 transformArray(bootclasspathModules, "", ".stubs.exportable.module_lib"), 397 // Then add all the system-server APIs from the service-* libraries. 398 transformArray(system_server_classpath, "", ".stubs.exportable.system_server")..., 399 ) 400 props := libraryProps{} 401 props.Name = proptools.StringPtr("framework-updatable-stubs-system_server_api-exportable") 402 props.Static_libs = modules 403 props.Sdk_version = proptools.StringPtr("system_server_current") 404 props.Visibility = []string{"//frameworks/base"} 405 props.Is_stubs_module = proptools.BoolPtr(true) 406 ctx.CreateModule(java.LibraryFactory, &props) 407} 408 409func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []string) { 410 props := fgProps{} 411 props.Name = proptools.StringPtr("all-modules-public-stubs-source") 412 props.Srcs = createSrcs(modules, "{.public.stubs.source}") 413 props.Visibility = []string{"//frameworks/base"} 414 ctx.CreateModule(android.FileGroupFactory, &props) 415} 416 417func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string, baseTxtModulePrefix, stubsTypeSuffix string, doDist bool) { 418 var textFiles []MergedTxtDefinition 419 420 tagSuffix := []string{".api.txt}", ".removed-api.txt}"} 421 distFilename := []string{"android.txt", "android-removed.txt"} 422 for i, f := range []string{"current.txt", "removed.txt"} { 423 textFiles = append(textFiles, MergedTxtDefinition{ 424 TxtFilename: f, 425 DistFilename: distFilename[i], 426 BaseTxt: ":" + baseTxtModulePrefix + f, 427 Modules: bootclasspath, 428 ModuleTag: "{.public" + tagSuffix[i], 429 Scope: "public", 430 }) 431 textFiles = append(textFiles, MergedTxtDefinition{ 432 TxtFilename: f, 433 DistFilename: distFilename[i], 434 BaseTxt: ":" + baseTxtModulePrefix + "system-" + f, 435 Modules: bootclasspath, 436 ModuleTag: "{.system" + tagSuffix[i], 437 Scope: "system", 438 }) 439 textFiles = append(textFiles, MergedTxtDefinition{ 440 TxtFilename: f, 441 DistFilename: distFilename[i], 442 BaseTxt: ":" + baseTxtModulePrefix + "module-lib-" + f, 443 Modules: bootclasspath, 444 ModuleTag: "{.module-lib" + tagSuffix[i], 445 Scope: "module-lib", 446 }) 447 textFiles = append(textFiles, MergedTxtDefinition{ 448 TxtFilename: f, 449 DistFilename: distFilename[i], 450 BaseTxt: ":" + baseTxtModulePrefix + "system-server-" + f, 451 Modules: system_server_classpath, 452 ModuleTag: "{.system-server" + tagSuffix[i], 453 Scope: "system-server", 454 }) 455 } 456 for _, txt := range textFiles { 457 createMergedTxt(ctx, txt, stubsTypeSuffix, doDist) 458 } 459} 460 461func createApiContributionDefaults(ctx android.LoadHookContext, modules []string) { 462 defaultsSdkKinds := []android.SdkKind{ 463 android.SdkPublic, android.SdkSystem, android.SdkModule, 464 } 465 for _, sdkKind := range defaultsSdkKinds { 466 props := defaultsProps{} 467 props.Name = proptools.StringPtr( 468 sdkKind.DefaultJavaLibraryName() + "_contributions") 469 if sdkKind == android.SdkModule { 470 props.Name = proptools.StringPtr( 471 sdkKind.DefaultJavaLibraryName() + "_contributions_full") 472 } 473 props.Api_surface = proptools.StringPtr(sdkKind.String()) 474 apiSuffix := "" 475 if sdkKind != android.SdkPublic { 476 apiSuffix = "." + strings.ReplaceAll(sdkKind.String(), "-", "_") 477 } 478 props.Api_contributions = transformArray( 479 modules, "", fmt.Sprintf(".stubs.source%s.api.contribution", apiSuffix)) 480 props.Defaults_visibility = []string{"//visibility:public"} 481 props.Previous_api = proptools.StringPtr(":android.api.public.latest") 482 ctx.CreateModule(java.DefaultsFactory, &props) 483 } 484} 485 486func createFullApiLibraries(ctx android.LoadHookContext) { 487 javaLibraryNames := []string{ 488 "android_stubs_current", 489 "android_system_stubs_current", 490 "android_test_stubs_current", 491 "android_test_frameworks_core_stubs_current", 492 "android_module_lib_stubs_current", 493 "android_system_server_stubs_current", 494 } 495 496 for _, libraryName := range javaLibraryNames { 497 props := libraryProps{} 498 props.Name = proptools.StringPtr(libraryName) 499 staticLib := libraryName + ".from-source" 500 if ctx.Config().BuildFromTextStub() { 501 staticLib = libraryName + ".from-text" 502 } 503 props.Static_libs = []string{staticLib} 504 props.Defaults = []string{"android.jar_defaults"} 505 props.Visibility = []string{"//visibility:public"} 506 props.Is_stubs_module = proptools.BoolPtr(true) 507 508 ctx.CreateModule(java.LibraryFactory, &props) 509 } 510} 511 512func createFullExportableApiLibraries(ctx android.LoadHookContext) { 513 javaLibraryNames := []string{ 514 "android_stubs_current_exportable", 515 "android_system_stubs_current_exportable", 516 "android_test_stubs_current_exportable", 517 "android_module_lib_stubs_current_exportable", 518 "android_system_server_stubs_current_exportable", 519 } 520 521 for _, libraryName := range javaLibraryNames { 522 props := libraryProps{} 523 props.Name = proptools.StringPtr(libraryName) 524 staticLib := libraryName + ".from-source" 525 props.Static_libs = []string{staticLib} 526 props.Defaults = []string{"android.jar_defaults"} 527 props.Visibility = []string{"//visibility:public"} 528 props.Is_stubs_module = proptools.BoolPtr(true) 529 530 ctx.CreateModule(java.LibraryFactory, &props) 531 } 532} 533 534func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { 535 bootclasspath := a.properties.Bootclasspath 536 system_server_classpath := a.properties.System_server_classpath 537 if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") { 538 bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...) 539 sort.Strings(bootclasspath) 540 } 541 createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-", "-", false) 542 createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-exportable-", "-exportable-", true) 543 544 createMergedPublicStubs(ctx, bootclasspath) 545 createMergedSystemStubs(ctx, bootclasspath) 546 createMergedTestStubsForNonUpdatableModules(ctx) 547 createMergedFrameworkModuleLibStubs(ctx, bootclasspath) 548 createMergedFrameworkImpl(ctx, bootclasspath) 549 550 createMergedPublicExportableStubs(ctx, bootclasspath) 551 createMergedSystemExportableStubs(ctx, bootclasspath) 552 createMergedTestExportableStubsForNonUpdatableModules(ctx) 553 createMergedFrameworkModuleLibExportableStubs(ctx, bootclasspath) 554 createMergedFrameworkSystemServerExportableStubs(ctx, bootclasspath, system_server_classpath) 555 556 createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath) 557 558 createPublicStubsSourceFilegroup(ctx, bootclasspath) 559 560 createApiContributionDefaults(ctx, bootclasspath) 561 562 createFullApiLibraries(ctx) 563 564 createFullExportableApiLibraries(ctx) 565} 566 567func combinedApisModuleFactory() android.Module { 568 module := &CombinedApis{} 569 module.AddProperties(&module.properties) 570 android.InitAndroidModule(module) 571 android.InitDefaultableModule(module) 572 android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) }) 573 return module 574} 575 576// Various utility methods below. 577 578// Creates an array of ":<m><tag>" for each m in <modules>. 579func createSrcs(modules []string, tag string) []string { 580 return transformArray(modules, ":", tag) 581} 582 583// Creates an array of "<prefix><m><suffix>", for each m in <modules>. 584func transformArray(modules []string, prefix, suffix string) []string { 585 a := make([]string, 0, len(modules)) 586 for _, module := range modules { 587 a = append(a, prefix+module+suffix) 588 } 589 return a 590} 591 592func removeAll(s []string, vs []string) []string { 593 for _, v := range vs { 594 s = remove(s, v) 595 } 596 return s 597} 598 599func remove(s []string, v string) []string { 600 s2 := make([]string, 0, len(s)) 601 for _, sv := range s { 602 if sv != v { 603 s2 = append(s2, sv) 604 } 605 } 606 return s2 607} 608 609// Defaults 610type CombinedApisModuleDefaults struct { 611 android.ModuleBase 612 android.DefaultsModuleBase 613} 614 615func CombinedApisModuleDefaultsFactory() android.Module { 616 module := &CombinedApisModuleDefaults{} 617 module.AddProperties(&CombinedApisProperties{}) 618 android.InitDefaultsModule(module) 619 return module 620} 621