1// Copyright (C) 2018 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 aidl 16 17import ( 18 "android/soong/android" 19 "android/soong/cc" 20 "android/soong/java" 21 "android/soong/phony" 22 "android/soong/rust" 23 24 "fmt" 25 "path/filepath" 26 "regexp" 27 "sort" 28 "strconv" 29 "strings" 30 "sync" 31 32 "github.com/google/blueprint/proptools" 33) 34 35const ( 36 aidlInterfaceSuffix = "_interface" 37 aidlMetadataSingletonName = "aidl_metadata_json" 38 aidlApiDir = "aidl_api" 39 aidlApiSuffix = "-api" 40 langCpp = "cpp" 41 langJava = "java" 42 langNdk = "ndk" 43 langNdkPlatform = "ndk_platform" 44 langRust = "rust" 45 46 currentVersion = "current" 47) 48 49var ( 50 pctx = android.NewPackageContext("android/aidl") 51) 52 53func init() { 54 pctx.Import("android/soong/android") 55 pctx.HostBinToolVariable("aidlCmd", "aidl") 56 pctx.SourcePathVariable("aidlToJniCmd", "system/tools/aidl/build/aidl_to_jni.py") 57 pctx.SourcePathVariable("aidlRustGlueCmd", "system/tools/aidl/build/aidl_rust_glue.py") 58 android.RegisterModuleType("aidl_interface", aidlInterfaceFactory) 59 android.PreArchMutators(registerPreDepsMutators) 60 android.PreArchBp2BuildMutators(registerPreDepsMutators) 61 android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 62 ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel() 63 ctx.BottomUp("recordVersions", recordVersions).Parallel() 64 ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel() 65 }) 66} 67 68func registerPreDepsMutators(ctx android.RegisterMutatorsContext) { 69 ctx.BottomUp("checkImports", checkImports).Parallel() 70 ctx.TopDown("createAidlInterface", createAidlInterfaceMutator).Parallel() 71} 72 73func createAidlInterfaceMutator(mctx android.TopDownMutatorContext) { 74 if g, ok := mctx.Module().(*aidlImplementationGenerator); ok { 75 g.GenerateImplementation(mctx) 76 } 77} 78 79func checkUnstableModuleMutator(mctx android.BottomUpMutatorContext) { 80 // If it is an aidl interface, we don't need to check its dependencies. 81 if isAidlModule(mctx.ModuleName(), mctx.Config()) { 82 return 83 } 84 mctx.VisitDirectDepsIf(func(m android.Module) bool { 85 return android.InList(m.Name(), *unstableModules(mctx.Config())) 86 }, func(m android.Module) { 87 if mctx.ModuleName() == m.Name() { 88 return 89 } 90 // TODO(b/154066686): Replace it with a common method instead of listing up module types. 91 // Test libraries are exempted. 92 if android.InList(mctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) { 93 return 94 } 95 96 mctx.ModuleErrorf(m.Name() + " is disallowed in release version because it is unstable, and its \"owner\" property is missing.") 97 }) 98} 99 100func isAidlModule(moduleName string, config android.Config) bool { 101 for _, i := range *aidlInterfaces(config) { 102 if android.InList(moduleName, i.internalModuleNames) { 103 return true 104 } 105 } 106 return false 107} 108 109func recordVersions(mctx android.BottomUpMutatorContext) { 110 switch mctx.Module().(type) { 111 case *java.Library: 112 case *cc.Module: 113 case *rust.Module: 114 case *aidlGenRule: 115 default: 116 return 117 } 118 119 isAidlModule := isAidlModule(mctx.ModuleName(), mctx.Config()) 120 121 // First, gather all the AIDL interfaces modules that are directly or indirectly 122 // depended on by this module 123 myAidlDeps := make(map[DepInfo]bool) 124 mctx.VisitDirectDeps(func(dep android.Module) { 125 switch dep.(type) { 126 case *java.Library: 127 case *cc.Module: 128 case *rust.Module: 129 case *aidlGenRule: 130 // Dependencies to the source module is tracked only when it's from a client 131 // module, i.e. not from an AIDL-generated stub library 132 if isAidlModule { 133 return 134 } 135 default: 136 return 137 } 138 depName := mctx.OtherModuleName(dep) 139 isSource := strings.HasSuffix(depName, "-source") 140 depName = strings.TrimSuffix(depName, "-source") 141 // If this module depends on one of the aidl interface module, record it 142 for _, i := range *aidlInterfaces(mctx.Config()) { 143 if android.InList(depName, i.internalModuleNames) { 144 ifaceName := i.ModuleBase.Name() 145 verLang := depName[len(ifaceName):] 146 myAidlDeps[DepInfo{ifaceName, verLang, isSource}] = true 147 break 148 } 149 } 150 // If dep is in aidlDeps, that means dep has direct or indirect dependencies to AIDL interfaces 151 // That becomes this module's aidlDeps as well 152 aidlDepsMutex.RLock() 153 if depsOfDep, ok := aidlDeps(mctx.Config())[dep]; ok { 154 for _, d := range depsOfDep { 155 myAidlDeps[d] = true 156 } 157 } 158 aidlDepsMutex.RUnlock() 159 }) 160 161 if len(myAidlDeps) == 0 { 162 // This should be usual case. 163 return 164 } 165 166 // Then, record the aidl deps of this module to the global map so that it can be used by 167 // next runs of this mutator for the modules that depend on this module. 168 var list []DepInfo 169 for d := range myAidlDeps { 170 list = append(list, d) 171 } 172 aidlDepsMutex.Lock() 173 aidlDeps(mctx.Config())[mctx.Module()] = list 174 aidlDepsMutex.Unlock() 175} 176 177func checkDuplicatedVersions(mctx android.BottomUpMutatorContext) { 178 switch mctx.Module().(type) { 179 case *java.Library: 180 case *cc.Module: 181 case *rust.Module: 182 case *aidlGenRule: 183 default: 184 return 185 } 186 187 aidlDepsMutex.RLock() 188 myAidlDeps := aidlDeps(mctx.Config())[mctx.Module()] 189 aidlDepsMutex.RUnlock() 190 if myAidlDeps == nil || len(myAidlDeps) == 0 { 191 return // This should be the usual case 192 } 193 194 // Lastly, report an error if there is any duplicated versions of the same interface * lang 195 for _, lang := range []string{langJava, langCpp, langNdk, langNdkPlatform} { 196 // interfaceName -> verLang -> list of module names 197 versionsOf := make(map[string]map[string][]string) 198 for _, dep := range myAidlDeps { 199 if !strings.HasSuffix(dep.verLang, lang) { 200 continue 201 } 202 versions := versionsOf[dep.ifaceName] 203 if versions == nil { 204 versions = make(map[string][]string) 205 versionsOf[dep.ifaceName] = versions 206 } 207 versions[dep.verLang] = append(versions[dep.verLang], dep.moduleName()) 208 } 209 210 for _, versions := range versionsOf { 211 if len(versions) >= 2 { 212 var violators []string 213 for _, modules := range versions { 214 violators = append(violators, modules...) 215 } 216 violators = android.SortedUniqueStrings(violators) 217 mctx.ModuleErrorf("depends on multiple versions of the same aidl_interface: %s", strings.Join(violators, ", ")) 218 mctx.WalkDeps(func(child android.Module, parent android.Module) bool { 219 if android.InList(child.Name(), violators) { 220 mctx.ModuleErrorf("Dependency path: %s", mctx.GetPathString(true)) 221 return false 222 } 223 return true 224 }) 225 } 226 } 227 } 228} 229 230func getPaths(ctx android.ModuleContext, rawSrcs []string, root string) (srcs android.Paths, imports []string) { 231 // TODO(b/189288369): move this to android.PathsForModuleSrcSubDir(ctx, srcs, subdir) 232 for _, src := range rawSrcs { 233 if m, _ := android.SrcIsModuleWithTag(src); m != "" { 234 srcs = append(srcs, android.PathsForModuleSrc(ctx, []string{src})...) 235 } else { 236 srcs = append(srcs, android.PathsWithModuleSrcSubDir(ctx, android.PathsForModuleSrc(ctx, []string{src}), root)...) 237 } 238 } 239 240 if len(srcs) == 0 { 241 ctx.PropertyErrorf("srcs", "No sources provided.") 242 } 243 244 // gather base directories from input .aidl files 245 for _, src := range srcs { 246 if src.Ext() != ".aidl" { 247 // Silently ignore non-aidl files as some filegroups have both java and aidl files together 248 continue 249 } 250 baseDir := strings.TrimSuffix(src.String(), src.Rel()) 251 baseDir = strings.TrimSuffix(baseDir, "/") 252 if baseDir != "" && !android.InList(baseDir, imports) { 253 imports = append(imports, baseDir) 254 } 255 } 256 257 return srcs, imports 258} 259 260func isRelativePath(path string) bool { 261 if path == "" { 262 return true 263 } 264 return filepath.Clean(path) == path && path != ".." && 265 !strings.HasPrefix(path, "../") && !strings.HasPrefix(path, "/") 266} 267 268type CommonBackendProperties struct { 269 // Whether to generate code in the corresponding backend. 270 // Default: true 271 Enabled *bool 272 Apex_available []string 273 274 // The minimum version of the sdk that the compiled artifacts will run against 275 // For native modules, the property needs to be set when a module is a part of mainline modules(APEX). 276 // Forwarded to generated java/native module. 277 Min_sdk_version *string 278 279 // Determines whether the generated source files are available or not. When set to true, 280 // the source files can be added to `srcs` property via `:<ifacename>-<backend>-source`, 281 // e.g., ":myaidl-java-source" 282 Srcs_available *bool 283} 284 285type CommonNativeBackendProperties struct { 286 CommonBackendProperties 287 // Whether to generate additional code for gathering information 288 // about the transactions. 289 // Default: false 290 Gen_log *bool 291 292 // VNDK properties for correspdoning backend. 293 cc.VndkProperties 294} 295 296type DumpApiProperties struct { 297 // Dumps without license header (assuming it is the first comment in .aidl file). Default: false 298 No_license *bool 299} 300 301type aidlInterfaceProperties struct { 302 // Vndk properties for C++/NDK libraries only (preferred to use backend-specific settings) 303 cc.VndkProperties 304 305 // How to interpret VNDK options. We only want one library in the VNDK (not multiple 306 // versions, since this would be a waste of space/unclear, and ultimately we want all 307 // code in a given release to be updated to use a specific version). By default, this 308 // puts either the latest stable version of the library or, if there is no stable 309 // version, the unstable version of the library in the VNDK. When using this field, 310 // explicitly set it to one of the values in the 'versions' field to put that version 311 // in the VNDK or set it to the next version (1 higher than this) to mean the version 312 // that will be frozen in the next update. 313 Vndk_use_version *string 314 315 // Whether the library can be installed on the vendor image. 316 Vendor_available *bool 317 318 // Whether the library can be installed on the odm image. 319 Odm_available *bool 320 321 // Whether the library can be installed on the product image. 322 Product_available *bool 323 324 // Whether the library can be loaded multiple times into the same process 325 Double_loadable *bool 326 327 // Whether the library can be used on host 328 Host_supported *bool 329 330 // Whether tracing should be added to the interface. 331 Gen_trace *bool 332 333 // Top level directories for includes. 334 // TODO(b/128940869): remove it if aidl_interface can depend on framework.aidl 335 Include_dirs []string 336 // Relative path for includes. By default assumes AIDL path is relative to current directory. 337 Local_include_dir string 338 339 // List of .aidl files which compose this interface. 340 Srcs []string `android:"path"` 341 342 // List of aidl_interface modules that this uses. If one of your AIDL interfaces uses an 343 // interface or parcelable from another aidl_interface, you should put its name here. 344 // It could be an aidl_interface solely or with version(such as -V1) 345 Imports []string 346 347 // List of aidl_interface modules that this uses. It trims version suffix in 'Imports' field. 348 ImportsWithoutVersion []string `blueprint:"mutated"` 349 350 // Used by gen dependency to fill out aidl include path 351 Full_import_paths []string `blueprint:"mutated"` 352 353 // Stability promise. Currently only supports "vintf". 354 // If this is unset, this corresponds to an interface with stability within 355 // this compilation context (so an interface loaded here can only be used 356 // with things compiled together, e.g. on the system.img). 357 // If this is set to "vintf", this corresponds to a stability promise: the 358 // interface must be kept stable as long as it is used. 359 Stability *string 360 361 // Previous API versions that are now frozen. The version that is last in 362 // the list is considered as the most recent version. 363 Versions []string 364 365 Backend struct { 366 // Backend of the compiler generating code for Java clients. 367 // When enabled, this creates a target called "<name>-java". 368 Java struct { 369 CommonBackendProperties 370 // Set to the version of the sdk to compile against 371 // Default: system_current 372 Sdk_version *string 373 // Whether to compile against platform APIs instead of 374 // an SDK. 375 Platform_apis *bool 376 } 377 // Backend of the compiler generating code for C++ clients using 378 // libbinder (unstable C++ interface) 379 // When enabled, this creates a target called "<name>-cpp". 380 Cpp struct { 381 CommonNativeBackendProperties 382 } 383 // Backend of the compiler generating code for C++ clients using 384 // libbinder_ndk (stable C interface to system's libbinder) 385 // When enabled, this creates a target called "<name>-ndk" 386 // (for apps) and "<name>-ndk_platform" (for platform usage). 387 Ndk struct { 388 CommonNativeBackendProperties 389 390 // Currently, all ndk-supported interfaces generate two variants: 391 // - ndk - for apps to use, against an NDK 392 // - ndk_platform - for the platform to use 393 // 394 // This adds an option to disable the 'ndk' variant in cases where APIs 395 // only available in the platform version work. 396 Apps_enabled *bool 397 } 398 // Backend of the compiler generating code for Rust clients. 399 // When enabled, this creates a target called "<name>-rust". 400 Rust struct { 401 CommonBackendProperties 402 } 403 } 404 405 // Marks that this interface does not need to be stable. When set to true, the build system 406 // doesn't create the API dump and require it to be updated. Default is false. 407 Unstable *bool 408 409 // Optional flags to be passed to the AIDL compiler. e.g. "-Weverything" 410 Flags []string 411 412 // --dumpapi options 413 Dumpapi DumpApiProperties 414} 415 416type aidlInterface struct { 417 android.ModuleBase 418 419 properties aidlInterfaceProperties 420 421 computedTypes []string 422 423 // list of module names that are created for this interface 424 internalModuleNames []string 425} 426 427func (i *aidlInterface) shouldGenerateJavaBackend() bool { 428 // explicitly true if not specified to give early warning to devs 429 return i.properties.Backend.Java.Enabled == nil || *i.properties.Backend.Java.Enabled 430} 431 432func (i *aidlInterface) shouldGenerateCppBackend() bool { 433 // explicitly true if not specified to give early warning to devs 434 return i.properties.Backend.Cpp.Enabled == nil || *i.properties.Backend.Cpp.Enabled 435} 436 437func (i *aidlInterface) shouldGenerateNdkBackend() bool { 438 // explicitly true if not specified to give early warning to devs 439 return i.properties.Backend.Ndk.Enabled == nil || *i.properties.Backend.Ndk.Enabled 440} 441 442func (i *aidlInterface) shouldGenerateAppNdkBackend() bool { 443 if !i.shouldGenerateNdkBackend() { 444 return false 445 } 446 // explicitly true if not specified to give early warning to devs 447 return i.properties.Backend.Ndk.Apps_enabled == nil || *i.properties.Backend.Ndk.Apps_enabled 448} 449 450func (i *aidlInterface) shouldGenerateRustBackend() bool { 451 return i.properties.Backend.Rust.Enabled != nil && *i.properties.Backend.Rust.Enabled 452} 453 454func (i *aidlInterface) gatherInterface(mctx android.LoadHookContext) { 455 aidlInterfaces := aidlInterfaces(mctx.Config()) 456 aidlInterfaceMutex.Lock() 457 defer aidlInterfaceMutex.Unlock() 458 *aidlInterfaces = append(*aidlInterfaces, i) 459} 460 461func addUnstableModule(mctx android.LoadHookContext, moduleName string) { 462 unstableModules := unstableModules(mctx.Config()) 463 unstableModuleMutex.Lock() 464 defer unstableModuleMutex.Unlock() 465 *unstableModules = append(*unstableModules, moduleName) 466} 467 468func checkImports(mctx android.BottomUpMutatorContext) { 469 if i, ok := mctx.Module().(*aidlInterface); ok { 470 for _, anImportWithVersion := range i.properties.Imports { 471 anImport, version := parseModuleWithVersion(anImportWithVersion) 472 other := lookupInterface(anImport, mctx.Config()) 473 474 if other == nil { 475 if mctx.Config().AllowMissingDependencies() { 476 continue 477 } 478 mctx.PropertyErrorf("imports", "Import does not exist: "+anImport) 479 } 480 if version != "" { 481 candidateVersions := concat(other.properties.Versions, []string{other.nextVersion()}) 482 if !android.InList(version, candidateVersions) { 483 mctx.PropertyErrorf("imports", "%q depends on %q version %q(%q), which doesn't exist. The version must be one of %q", i.ModuleBase.Name(), anImport, version, anImportWithVersion, candidateVersions) 484 } 485 } 486 if i.shouldGenerateJavaBackend() && !other.shouldGenerateJavaBackend() { 487 mctx.PropertyErrorf("backend.java.enabled", 488 "Java backend not enabled in the imported AIDL interface %q", anImport) 489 } 490 491 if i.shouldGenerateCppBackend() && !other.shouldGenerateCppBackend() { 492 mctx.PropertyErrorf("backend.cpp.enabled", 493 "C++ backend not enabled in the imported AIDL interface %q", anImport) 494 } 495 496 if i.shouldGenerateNdkBackend() && !other.shouldGenerateNdkBackend() { 497 mctx.PropertyErrorf("backend.ndk.enabled", 498 "NDK backend not enabled in the imported AIDL interface %q", anImport) 499 } 500 501 if i.shouldGenerateRustBackend() && !other.shouldGenerateRustBackend() { 502 mctx.PropertyErrorf("backend.rust.enabled", 503 "Rust backend not enabled in the imported AIDL interface %q", anImport) 504 } 505 } 506 } 507} 508 509func (i *aidlInterface) checkGenTrace(mctx android.LoadHookContext) { 510 if !proptools.Bool(i.properties.Gen_trace) { 511 return 512 } 513 if i.shouldGenerateJavaBackend() && !proptools.Bool(i.properties.Backend.Java.Platform_apis) { 514 mctx.PropertyErrorf("gen_trace", "must be false when Java backend is enabled and platform_apis is false") 515 } 516} 517 518func (i *aidlInterface) checkStability(mctx android.LoadHookContext) { 519 if i.properties.Stability == nil { 520 return 521 } 522 523 if proptools.Bool(i.properties.Unstable) { 524 mctx.PropertyErrorf("stability", "must be empty when \"unstable\" is true") 525 } 526 527 // TODO(b/136027762): should we allow more types of stability (e.g. for APEX) or 528 // should we switch this flag to be something like "vintf { enabled: true }" 529 isVintf := "vintf" == proptools.String(i.properties.Stability) 530 if !isVintf { 531 mctx.PropertyErrorf("stability", "must be empty or \"vintf\"") 532 } 533} 534func (i *aidlInterface) checkVersions(mctx android.LoadHookContext) { 535 versions := make(map[string]bool) 536 intVersions := make([]int, 0, len(i.properties.Versions)) 537 for _, ver := range i.properties.Versions { 538 if _, dup := versions[ver]; dup { 539 mctx.PropertyErrorf("versions", "duplicate found", ver) 540 continue 541 } 542 versions[ver] = true 543 n, err := strconv.Atoi(ver) 544 if err != nil { 545 mctx.PropertyErrorf("versions", "%q is not an integer", ver) 546 continue 547 } 548 if n <= 0 { 549 mctx.PropertyErrorf("versions", "should be > 0, but is %v", ver) 550 continue 551 } 552 intVersions = append(intVersions, n) 553 554 } 555 if !mctx.Failed() && !sort.IntsAreSorted(intVersions) { 556 mctx.PropertyErrorf("versions", "should be sorted, but is %v", i.properties.Versions) 557 } 558} 559func (i *aidlInterface) checkVndkUseVersion(mctx android.LoadHookContext) { 560 if i.properties.Vndk_use_version == nil { 561 return 562 } 563 if !i.hasVersion() { 564 mctx.PropertyErrorf("vndk_use_version", "This does not make sense when no 'versions' are specified.") 565 566 } 567 if *i.properties.Vndk_use_version == i.nextVersion() { 568 return 569 } 570 for _, ver := range i.properties.Versions { 571 if *i.properties.Vndk_use_version == ver { 572 return 573 } 574 } 575 mctx.PropertyErrorf("vndk_use_version", "Specified version %q does not exist", *i.properties.Vndk_use_version) 576} 577 578func (i *aidlInterface) nextVersion() string { 579 if proptools.Bool(i.properties.Unstable) { 580 return "" 581 } 582 return nextVersion(i.properties.Versions) 583} 584 585func nextVersion(versions []string) string { 586 if len(versions) == 0 { 587 return "1" 588 } 589 ver := versions[len(versions)-1] 590 i, err := strconv.Atoi(ver) 591 if err != nil { 592 panic(err) 593 } 594 return strconv.Itoa(i + 1) 595} 596 597func (i *aidlInterface) latestVersion() string { 598 if !i.hasVersion() { 599 return "0" 600 } 601 return i.properties.Versions[len(i.properties.Versions)-1] 602} 603 604func (i *aidlInterface) hasVersion() bool { 605 return len(i.properties.Versions) > 0 606} 607 608func hasVersionSuffix(moduleName string) bool { 609 hasVersionSuffix, _ := regexp.MatchString("-V\\d+$", moduleName) 610 return hasVersionSuffix 611} 612 613func parseModuleWithVersion(moduleName string) (string, string) { 614 if hasVersionSuffix(moduleName) { 615 versionIdx := strings.LastIndex(moduleName, "-V") 616 if versionIdx == -1 { 617 panic("-V must exist in this context") 618 } 619 return moduleName[:versionIdx], moduleName[versionIdx+len("-V"):] 620 } 621 return moduleName, "" 622} 623 624func trimVersionSuffixInList(moduleNames []string) []string { 625 return wrapFunc("", moduleNames, "", func(moduleName string) string { 626 moduleNameWithoutVersion, _ := parseModuleWithVersion(moduleName) 627 return moduleNameWithoutVersion 628 }) 629} 630 631func aidlInterfaceHook(mctx android.LoadHookContext, i *aidlInterface) { 632 if hasVersionSuffix(i.ModuleBase.Name()) { 633 mctx.PropertyErrorf("name", "aidl_interface should not have '-V<number> suffix") 634 } 635 i.properties.ImportsWithoutVersion = trimVersionSuffixInList(i.properties.Imports) 636 if !isRelativePath(i.properties.Local_include_dir) { 637 mctx.PropertyErrorf("local_include_dir", "must be relative path: "+i.properties.Local_include_dir) 638 } 639 var importPaths []string 640 importPaths = append(importPaths, filepath.Join(mctx.ModuleDir(), i.properties.Local_include_dir)) 641 importPaths = append(importPaths, i.properties.Include_dirs...) 642 643 i.properties.Full_import_paths = importPaths 644 645 i.gatherInterface(mctx) 646 i.checkStability(mctx) 647 i.checkVersions(mctx) 648 i.checkVndkUseVersion(mctx) 649 i.checkGenTrace(mctx) 650 651 if mctx.Failed() { 652 return 653 } 654 655 var libs []string 656 sdkIsFinal := !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview() 657 658 unstable := proptools.Bool(i.properties.Unstable) 659 660 if unstable { 661 if i.hasVersion() { 662 mctx.PropertyErrorf("versions", "cannot have versions for an unstable interface") 663 return 664 } 665 if i.properties.Stability != nil { 666 mctx.ModuleErrorf("unstable:true and stability:%q cannot happen at the same time", i.properties.Stability) 667 return 668 } 669 } 670 671 // Two different types of 'unstable' here 672 // - 'unstable: true' meaning the module is never stable 673 // - current unfrozen ToT version 674 // 675 // OEM branches may remove 'i.Owner()' here to apply the check to all interfaces, in 676 // addition to core platform interfaces. Otherwise, we rely on vts_treble_vintf_vendor_test. 677 requireFrozenVersion := !unstable && sdkIsFinal && i.Owner() == "" 678 679 // surface error early, main check is via checkUnstableModuleMutator 680 if requireFrozenVersion && !i.hasVersion() { 681 mctx.PropertyErrorf("versions", "must be set (need to be frozen) when \"unstable\" is false, PLATFORM_VERSION_CODENAME is REL, and \"owner\" property is missing.") 682 } 683 684 versions := i.properties.Versions 685 nextVersion := i.nextVersion() 686 shouldGenerateLangBackendMap := map[string]bool{ 687 langCpp: i.shouldGenerateCppBackend(), 688 langNdk: i.shouldGenerateAppNdkBackend(), 689 langNdkPlatform: i.shouldGenerateNdkBackend(), 690 langJava: i.shouldGenerateJavaBackend(), 691 langRust: i.shouldGenerateRustBackend()} 692 for lang, shouldGenerate := range shouldGenerateLangBackendMap { 693 if !shouldGenerate { 694 continue 695 } 696 libs = append(libs, addLibrary(mctx, i, nextVersion, lang)) 697 if requireFrozenVersion { 698 addUnstableModule(mctx, libs[len(libs)-1]) 699 } 700 for _, version := range versions { 701 libs = append(libs, addLibrary(mctx, i, version, lang)) 702 } 703 } 704 705 if unstable { 706 apiDirRoot := filepath.Join(aidlApiDir, i.ModuleBase.Name()) 707 aidlDumps, _ := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), apiDirRoot, "**/*.aidl"), nil) 708 if len(aidlDumps) != 0 { 709 mctx.PropertyErrorf("unstable", "The interface is configured as unstable, "+ 710 "but API dumps exist under %q. Unstable interface cannot have dumps.", apiDirRoot) 711 } 712 } else { 713 addApiModule(mctx, i) 714 } 715 716 if proptools.Bool(i.properties.VndkProperties.Vndk.Enabled) { 717 if "vintf" != proptools.String(i.properties.Stability) { 718 mctx.PropertyErrorf("stability", "must be \"vintf\" if the module is for VNDK.") 719 } 720 } 721 722 // Reserve this module name for future use 723 mctx.CreateModule(phony.PhonyFactory, &phonyProperties{ 724 Name: proptools.StringPtr(i.ModuleBase.Name()), 725 }) 726 727 i.internalModuleNames = libs 728} 729 730func (i *aidlInterface) commonBackendProperties(lang string) CommonBackendProperties { 731 switch lang { 732 case langCpp: 733 return i.properties.Backend.Cpp.CommonBackendProperties 734 case langJava: 735 return i.properties.Backend.Java.CommonBackendProperties 736 case langNdk, langNdkPlatform: 737 return i.properties.Backend.Ndk.CommonBackendProperties 738 case langRust: 739 return i.properties.Backend.Rust.CommonBackendProperties 740 default: 741 panic(fmt.Errorf("unsupported language backend %q\n", lang)) 742 } 743} 744 745// srcsVisibility gives the value for the `visibility` property of the source gen module for the 746// language backend `lang`. By default, the source gen module is not visible to the clients of 747// aidl_interface (because it's an impl detail), but when `backend.<backend>.srcs_available` is set 748// to true, the source gen module follows the visibility of the aidl_interface module. 749func srcsVisibility(mctx android.LoadHookContext, lang string) []string { 750 if a, ok := mctx.Module().(*aidlInterface); !ok { 751 panic(fmt.Errorf("%q is not aidl_interface", mctx.Module().String())) 752 } else { 753 if proptools.Bool(a.commonBackendProperties(lang).Srcs_available) { 754 // Returning nil so that the visibility of the source module defaults to the 755 // the package-level default visibility. This way, the source module gets 756 // the same visibility as the library modules. 757 return nil 758 } 759 } 760 return []string{ 761 "//" + mctx.ModuleDir(), 762 // system/tools/aidl/build is always added because aidl_metadata_json in the 763 // directory has dependencies to all aidl_interface modules. 764 "//system/tools/aidl/build", 765 } 766} 767 768func (i *aidlInterface) Name() string { 769 return i.ModuleBase.Name() + aidlInterfaceSuffix 770} 771func (i *aidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) { 772 aidlRoot := android.PathForModuleSrc(ctx, i.properties.Local_include_dir) 773 for _, src := range android.PathsForModuleSrc(ctx, i.properties.Srcs) { 774 baseDir := getBaseDir(ctx, src, aidlRoot) 775 relPath, _ := filepath.Rel(baseDir, src.String()) 776 computedType := strings.TrimSuffix(strings.ReplaceAll(relPath, "/", "."), ".aidl") 777 i.computedTypes = append(i.computedTypes, computedType) 778 } 779} 780func (i *aidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) { 781 ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName) 782} 783 784var ( 785 aidlInterfacesKey = android.NewOnceKey("aidlInterfaces") 786 unstableModulesKey = android.NewOnceKey("unstableModules") 787 aidlDepsKey = android.NewOnceKey("aidlDeps") 788 aidlInterfaceMutex sync.Mutex 789 unstableModuleMutex sync.Mutex 790 aidlDepsMutex sync.RWMutex 791) 792 793func aidlInterfaces(config android.Config) *[]*aidlInterface { 794 return config.Once(aidlInterfacesKey, func() interface{} { 795 return &[]*aidlInterface{} 796 }).(*[]*aidlInterface) 797} 798 799func unstableModules(config android.Config) *[]string { 800 return config.Once(unstableModulesKey, func() interface{} { 801 return &[]string{} 802 }).(*[]string) 803} 804 805type DepInfo struct { 806 ifaceName string 807 verLang string 808 isSource bool 809} 810 811func (d DepInfo) moduleName() string { 812 name := d.ifaceName + d.verLang 813 if d.isSource { 814 name += "-source" 815 } 816 return name 817} 818 819func aidlDeps(config android.Config) map[android.Module][]DepInfo { 820 return config.Once(aidlDepsKey, func() interface{} { 821 return make(map[android.Module][]DepInfo) 822 }).(map[android.Module][]DepInfo) 823} 824 825func aidlInterfaceFactory() android.Module { 826 i := &aidlInterface{} 827 i.AddProperties(&i.properties) 828 android.InitAndroidModule(i) 829 android.AddLoadHook(i, func(ctx android.LoadHookContext) { aidlInterfaceHook(ctx, i) }) 830 return i 831} 832 833func lookupInterface(name string, config android.Config) *aidlInterface { 834 for _, i := range *aidlInterfaces(config) { 835 if i.ModuleBase.Name() == name { 836 return i 837 } 838 } 839 return nil 840} 841