blob: a1004380214d9cc80ee301a226864e05d715e6c1 [file] [log] [blame]
Jeongik Chada36d5a2021-01-20 00:43:34 +09001// 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 aidl
16
17import (
18 "android/soong/android"
19 "android/soong/cc"
20 "android/soong/java"
21 "android/soong/rust"
22
23 "path/filepath"
Jeongik Chada36d5a2021-01-20 00:43:34 +090024 "strings"
25
26 "github.com/google/blueprint/proptools"
27)
28
Jeongik Cha52e98022021-01-20 18:37:20 +090029func addLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
30 if lang == langJava {
31 return addJavaLibrary(mctx, i, version)
32 } else if lang == langRust {
33 return addRustLibrary(mctx, i, version)
34 }
35 return addCppLibrary(mctx, i, version, lang)
36}
37
38func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
39 cppSourceGen := i.versionedName(version) + "-" + lang + "-source"
40 cppModuleGen := i.versionedName(version) + "-" + lang
41
Jeongik Chada36d5a2021-01-20 00:43:34 +090042 srcs, aidlRoot := i.srcsForVersion(mctx, version)
43 if len(srcs) == 0 {
44 // This can happen when the version is about to be frozen; the version
45 // directory is created but API dump hasn't been copied there.
46 // Don't create a library for the yet-to-be-frozen version.
47 return ""
48 }
49
50 var overrideVndkProperties cc.VndkProperties
51
Jeongik Cha52e98022021-01-20 18:37:20 +090052 if !i.isModuleForVndk(version) {
Jeongik Chada36d5a2021-01-20 00:43:34 +090053 // We only want the VNDK to include the latest interface. For interfaces in
54 // development, they will be frozen, so we put their latest version in the
55 // VNDK. For interfaces which are already frozen, we put their latest version
56 // in the VNDK, and when that version is frozen, the version in the VNDK can
57 // be updated. Otherwise, we remove this library from the VNDK, to avoid adding
58 // multiple versions of the same library to the VNDK.
59 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
60 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
61 }
62
63 var commonProperties *CommonNativeBackendProperties
64 if lang == langCpp {
65 commonProperties = &i.properties.Backend.Cpp.CommonNativeBackendProperties
66 } else if lang == langNdk || lang == langNdkPlatform {
67 commonProperties = &i.properties.Backend.Ndk.CommonNativeBackendProperties
68 }
69
70 genLog := proptools.Bool(commonProperties.Gen_log)
71 genTrace := proptools.Bool(i.properties.Gen_trace)
72
73 mctx.CreateModule(aidlGenFactory, &nameProperties{
74 Name: proptools.StringPtr(cppSourceGen),
75 }, &aidlGenProperties{
76 Srcs: srcs,
77 AidlRoot: aidlRoot,
78 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
79 Stability: i.properties.Stability,
80 Lang: lang,
81 BaseName: i.ModuleBase.Name(),
82 GenLog: genLog,
Jeongik Cha52e98022021-01-20 18:37:20 +090083 Version: i.versionForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +090084 GenTrace: genTrace,
85 Unstable: i.properties.Unstable,
86 Visibility: srcsVisibility(mctx, lang),
Jooyung Han03b19c32021-02-09 10:08:19 +090087 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +090088 })
Jeongik Chada36d5a2021-01-20 00:43:34 +090089
Jeongik Cha52e98022021-01-20 18:37:20 +090090 importExportDependencies := []string{}
Jeongik Chada36d5a2021-01-20 00:43:34 +090091 var sharedLibDependency []string
92 var headerLibs []string
93 var sdkVersion *string
94 var minSdkVersion *string
95 var stl *string
96 var cpp_std *string
97 var hostSupported *bool
98 var addCflags []string
99
100 if lang == langCpp {
101 importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
102 if genTrace {
103 sharedLibDependency = append(sharedLibDependency, "libcutils")
104 }
105 hostSupported = i.properties.Host_supported
106 minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
107 } else if lang == langNdk {
108 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
109 if genTrace {
110 sharedLibDependency = append(sharedLibDependency, "libandroid")
111 }
112 sdkVersion = proptools.StringPtr("current")
113 stl = proptools.StringPtr("c++_shared")
114 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
115 } else if lang == langNdkPlatform {
116 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
117 if genTrace {
118 headerLibs = append(headerLibs, "libandroid_aidltrace")
119 sharedLibDependency = append(sharedLibDependency, "libcutils")
120 }
121 hostSupported = i.properties.Host_supported
122 addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
123 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
124 } else {
125 panic("Unrecognized language: " + lang)
126 }
127
128 vendorAvailable := i.properties.Vendor_available
Justin Yun08cb78a2021-01-25 17:24:24 +0900129 odmAvailable := i.properties.Odm_available
Jeongik Chada36d5a2021-01-20 00:43:34 +0900130 productAvailable := i.properties.Product_available
131 if lang == langCpp {
132 // Vendor and product modules cannot use the libbinder (cpp) backend of AIDL in a
133 // way that is stable. So, in order to prevent accidental usage of these library by
134 // vendor and product forcibly disabling this version of the library.
135 //
136 // It may be the case in the future that we will want to enable this (if some generic
137 // helper should be used by both libbinder vendor things using /dev/vndbinder as well
138 // as those things using /dev/binder + libbinder_ndk to talk to stable interfaces).
139 if "vintf" == proptools.String(i.properties.Stability) {
140 overrideVndkProperties.Vndk.Private = proptools.BoolPtr(true)
141 }
142 // As libbinder is not available for the product processes, we must not create
143 // product variant for the aidl_interface
144 productAvailable = nil
145 }
146
147 if lang == langNdk {
148 // TODO(b/121157555): when the NDK variant is its own variant, these wouldn't interact,
149 // but we can't create a vendor or product version of an NDK variant
150 //
151 // nil (unspecified) is used instead of false so that this can't conflict with
152 // 'vendor: true', for instance.
153 vendorAvailable = nil
Justin Yun08cb78a2021-01-25 17:24:24 +0900154 odmAvailable = nil
Jeongik Chada36d5a2021-01-20 00:43:34 +0900155 productAvailable = nil
156 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
157 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
158 }
159
Jeongik Cha52e98022021-01-20 18:37:20 +0900160 mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
161 Name: proptools.StringPtr(cppModuleGen + "-generator"),
162 }, &aidlImplementationGeneratorProperties{
163 Lang: lang,
164 AidlInterfaceName: i.ModuleBase.Name(),
165 Version: version,
166 ModuleProperties: []interface{}{
167 &ccProperties{
168 Name: proptools.StringPtr(cppModuleGen),
169 Vendor_available: vendorAvailable,
Justin Yun08cb78a2021-01-25 17:24:24 +0900170 Odm_available: odmAvailable,
Jeongik Cha52e98022021-01-20 18:37:20 +0900171 Product_available: productAvailable,
172 Host_supported: hostSupported,
173 Defaults: []string{"aidl-cpp-module-defaults"},
174 Double_loadable: i.properties.Double_loadable,
175 Generated_sources: []string{cppSourceGen},
176 Generated_headers: []string{cppSourceGen},
177 Export_generated_headers: []string{cppSourceGen},
178 Shared_libs: append(importExportDependencies, sharedLibDependency...),
179 Header_libs: headerLibs,
180 Export_shared_lib_headers: importExportDependencies,
181 Sdk_version: sdkVersion,
182 Stl: stl,
183 Cpp_std: cpp_std,
184 Cflags: append(addCflags, "-Wextra", "-Wall", "-Werror", "-Wextra-semi"),
185 Apex_available: commonProperties.Apex_available,
186 Min_sdk_version: minSdkVersion,
187 UseApexNameMacro: true,
188 Target: ccTargetProperties{
189 // Currently necessary for host builds
190 // TODO(b/31559095): bionic on host should define this
191 // TODO(b/146436251): default isn't applied because the module is created
192 // in PreArchMutators, when import behavior becomes explicit, the logic can
193 // be moved back to LoadHook
194 Host: hostProperties{Cflags: []string{
195 "-D__INTRODUCED_IN(n)=",
196 "-D__assert(a,b,c)=",
197 // We want all the APIs to be available on the host.
198 "-D__ANDROID_API__=10000"}},
199 Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
200 Tidy: proptools.BoolPtr(true),
201 // Do the tidy check only for the generated headers
202 Tidy_flags: []string{"--header-filter=" + android.PathForOutput(mctx).String() + ".*"},
203 Tidy_checks_as_errors: []string{"*"},
204 }, &i.properties.VndkProperties,
205 &commonProperties.VndkProperties,
206 &overrideVndkProperties,
207 },
208 })
Jeongik Chada36d5a2021-01-20 00:43:34 +0900209
210 return cppModuleGen
211}
212
Jeongik Cha52e98022021-01-20 18:37:20 +0900213func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
214 javaSourceGen := i.versionedName(version) + "-java-source"
215 javaModuleGen := i.versionedName(version) + "-java"
Jeongik Chada36d5a2021-01-20 00:43:34 +0900216 srcs, aidlRoot := i.srcsForVersion(mctx, version)
217 if len(srcs) == 0 {
218 // This can happen when the version is about to be frozen; the version
219 // directory is created but API dump hasn't been copied there.
220 // Don't create a library for the yet-to-be-frozen version.
221 return ""
222 }
223
224 sdkVersion := i.properties.Backend.Java.Sdk_version
225 if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
226 // platform apis requires no default
227 sdkVersion = proptools.StringPtr("system_current")
228 }
229
230 mctx.CreateModule(aidlGenFactory, &nameProperties{
231 Name: proptools.StringPtr(javaSourceGen),
232 }, &aidlGenProperties{
233 Srcs: srcs,
234 AidlRoot: aidlRoot,
235 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
236 Stability: i.properties.Stability,
237 Lang: langJava,
238 BaseName: i.ModuleBase.Name(),
Jeongik Cha52e98022021-01-20 18:37:20 +0900239 Version: i.versionForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900240 GenTrace: proptools.Bool(i.properties.Gen_trace),
241 Unstable: i.properties.Unstable,
242 Visibility: srcsVisibility(mctx, langJava),
Jooyung Han03b19c32021-02-09 10:08:19 +0900243 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900244 })
245
Jeongik Cha52e98022021-01-20 18:37:20 +0900246 mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
247 Name: proptools.StringPtr(javaModuleGen + "-generator"),
248 }, &aidlImplementationGeneratorProperties{
249 Lang: langJava,
250 AidlInterfaceName: i.ModuleBase.Name(),
251 Version: version,
252 ModuleProperties: []interface{}{&javaProperties{
253 Name: proptools.StringPtr(javaModuleGen),
254 Installable: proptools.BoolPtr(true),
255 Defaults: []string{"aidl-java-module-defaults"},
256 Sdk_version: sdkVersion,
257 Platform_apis: i.properties.Backend.Java.Platform_apis,
258 Srcs: []string{":" + javaSourceGen},
259 Apex_available: i.properties.Backend.Java.Apex_available,
260 Min_sdk_version: i.properties.Backend.Java.Min_sdk_version,
261 }},
Jeongik Chada36d5a2021-01-20 00:43:34 +0900262 })
263
264 return javaModuleGen
265}
266
Jeongik Cha52e98022021-01-20 18:37:20 +0900267func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
268 rustSourceGen := i.versionedName(version) + "-rust-source"
269 rustModuleGen := i.versionedName(version) + "-rust"
Jeongik Chada36d5a2021-01-20 00:43:34 +0900270 srcs, aidlRoot := i.srcsForVersion(mctx, version)
271 if len(srcs) == 0 {
272 // This can happen when the version is about to be frozen; the version
273 // directory is created but API dump hasn't been copied there.
274 // Don't create a library for the yet-to-be-frozen version.
275 return ""
276 }
277
278 mctx.CreateModule(aidlGenFactory, &nameProperties{
279 Name: proptools.StringPtr(rustSourceGen),
280 }, &aidlGenProperties{
281 Srcs: srcs,
282 AidlRoot: aidlRoot,
283 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
284 Stability: i.properties.Stability,
285 Lang: langRust,
286 BaseName: i.ModuleBase.Name(),
Jeongik Cha52e98022021-01-20 18:37:20 +0900287 Version: i.versionForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900288 Unstable: i.properties.Unstable,
289 Visibility: srcsVisibility(mctx, langRust),
Jooyung Han03b19c32021-02-09 10:08:19 +0900290 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900291 })
292
Jeongik Cha52e98022021-01-20 18:37:20 +0900293 versionedRustName := fixRustName(i.versionedName(version))
294 rustCrateName := fixRustName(i.ModuleBase.Name())
Jeongik Chada36d5a2021-01-20 00:43:34 +0900295
296 mctx.CreateModule(aidlRustLibraryFactory, &rustProperties{
297 Name: proptools.StringPtr(rustModuleGen),
Jeongik Cha52e98022021-01-20 18:37:20 +0900298 Crate_name: rustCrateName,
Jeongik Chada36d5a2021-01-20 00:43:34 +0900299 Stem: proptools.StringPtr("lib" + versionedRustName),
300 Defaults: []string{"aidl-rust-module-defaults"},
301 Host_supported: i.properties.Host_supported,
Jiyong Park33690252021-02-16 13:21:40 +0900302 Apex_available: i.properties.Backend.Rust.Apex_available,
Jeongik Cha52e98022021-01-20 18:37:20 +0900303 Target: rustTargetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
Jeongik Chada36d5a2021-01-20 00:43:34 +0900304 }, &rust.SourceProviderProperties{
305 Source_stem: proptools.StringPtr(versionedRustName),
306 }, &aidlRustSourceProviderProperties{
Jeongik Cha52e98022021-01-20 18:37:20 +0900307 SourceGen: rustSourceGen,
308 Imports: i.properties.Imports,
309 Version: version,
310 AidlInterfaceName: i.ModuleBase.Name(),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900311 })
312
313 return rustModuleGen
314}
315
316// This function returns module name with version. Assume that there is foo of which latest version is 2
317// Version -> Module name
318// "1"->foo-V1
319// "2"->foo-V2
Jeongik Cha52e98022021-01-20 18:37:20 +0900320// "3"->foo-V3
321// And assume that there is 'bar' which is an 'unstable' interface.
322// ""->bar
Jeongik Chada36d5a2021-01-20 00:43:34 +0900323func (i *aidlInterface) versionedName(version string) string {
324 name := i.ModuleBase.Name()
Jeongik Cha52e98022021-01-20 18:37:20 +0900325 // TODO(b/150578172) remove exception when every module specify its version.
Jeongik Chada36d5a2021-01-20 00:43:34 +0900326 if version == "" {
327 return name
Jeongik Cha52e98022021-01-20 18:37:20 +0900328 } else if version == unstableVersion {
Jeongik Chada36d5a2021-01-20 00:43:34 +0900329 return name + "-" + unstableVersion
330 }
331 return name + "-V" + version
332}
333
Jeongik Chada36d5a2021-01-20 00:43:34 +0900334func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
Jeongik Cha52e98022021-01-20 18:37:20 +0900335 // TODO(b/150578172) remove exception when every module specify its version.
336 version = i.normalizeVersion(version)
337 if version == i.nextVersion() {
Jeongik Chada36d5a2021-01-20 00:43:34 +0900338 return i.properties.Srcs, i.properties.Local_include_dir
339 } else {
340 aidlRoot = filepath.Join(aidlApiDir, i.ModuleBase.Name(), version)
341 full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), aidlRoot, "**/*.aidl"), nil)
342 if err != nil {
343 panic(err)
344 }
345 for _, path := range full_paths {
346 // Here, we need path local to the module
347 srcs = append(srcs, strings.TrimPrefix(path, mctx.ModuleDir()+"/"))
348 }
349 return srcs, aidlRoot
350 }
351}
Jeongik Cha52e98022021-01-20 18:37:20 +0900352
353func (i *aidlInterface) versionForAidlGenRule(version string) string {
354 if !i.hasVersion() {
355 return ""
356 }
357 // TODO(b/150578172) remove exception when every module specify its version.
358 if version == "" {
359 return i.latestVersion()
360 }
361 if version == unstableVersion {
362 return i.nextVersion()
363 }
364 return version
365}
366
Jooyung Han03b19c32021-02-09 10:08:19 +0900367func (i *aidlInterface) flagsForAidlGenRule(version string) (flags []string) {
368 flags = append(flags, i.properties.Flags...)
369 // For ToT, turn on "-Weverything" (enable all warnings)
370 if version == i.nextVersion() {
371 flags = append(flags, "-Weverything")
372 }
373 return
374}
375
Jeongik Cha52e98022021-01-20 18:37:20 +0900376func (i *aidlInterface) isModuleForVndk(version string) bool {
377 // TODO(b/150578172) remove exception when every module specify its version.
378 version = i.normalizeVersion(version)
379
380 if i.properties.Vndk_use_version != nil {
381 if !i.hasVersion() {
382 panic("does not make sense, vndk_use_version specififed")
383 }
384 // Will be exactly one of the version numbers
385 return version == *i.properties.Vndk_use_version
386 }
387
388 // For an interface with no versions, this is the ToT interface.
389 if !i.hasVersion() {
390 return version == i.nextVersion()
391 }
392
393 return version == i.latestVersion()
394}
395
396// importing aidl_interface's version | imported aidl_interface | imported aidl_interface's version
397// --------------------------------------------------------------------------------------------------
398// whatever | unstable | unstable version
399// ToT version(including unstable) | whatever | ToT version(unstable if unstable)
400// otherwise | whatever | the latest stable version
401// TODO(b/146436251) Make import field specify the explicit version which it wants to import.
402func (i *aidlInterface) getImportWithVersion(version string, anImport string, config android.Config) string {
403 // TODO(b/150578172) remove exception when every module specify its version.
404 version = i.normalizeVersion(version)
405
406 other := lookupInterface(anImport, config)
407 if proptools.Bool(other.properties.Unstable) {
408 return anImport
409 }
410 if version == i.nextVersion() || !other.hasVersion() {
411 return other.versionedName(other.nextVersion())
412 }
413 return other.versionedName(other.latestVersion())
414}
415
416// TODO(b/150578172) remove exception when every module specify its version.
417func (i *aidlInterface) normalizeVersion(version string) string {
418 if version == "" {
419 if i.hasVersion() {
420 return i.latestVersion()
421 } else if !proptools.Bool(i.properties.Unstable) {
422 return i.nextVersion()
423 }
424 } else if version == unstableVersion {
425 return i.nextVersion()
426 }
427 return version
428}
429
430func aidlImplementationGeneratorFactory() android.Module {
431 g := &aidlImplementationGenerator{}
432 g.AddProperties(&g.properties)
433 android.InitAndroidModule(g)
434 return g
435}
436
437type aidlImplementationGenerator struct {
438 android.ModuleBase
439 properties aidlImplementationGeneratorProperties
440}
441
442type aidlImplementationGeneratorProperties struct {
443 Lang string
444 AidlInterfaceName string
445 Version string
446 ModuleProperties []interface{}
447}
448
449func (g *aidlImplementationGenerator) DepsMutator(ctx android.BottomUpMutatorContext) {
450}
451
452func (g *aidlImplementationGenerator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
453}
454
455func (g *aidlImplementationGenerator) GenerateImplementation(ctx android.TopDownMutatorContext) {
456 i := lookupInterface(g.properties.AidlInterfaceName, ctx.Config())
457 version := g.properties.Version
458 lang := g.properties.Lang
459 if g.properties.Lang == langJava {
460 imports := make([]string, len(i.properties.Imports))
461 for idx, anImport := range i.properties.Imports {
462 imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + langJava
463 }
464 if p, ok := g.properties.ModuleProperties[0].(*javaProperties); ok {
465 p.Static_libs = imports
466 }
467 ctx.CreateModule(java.LibraryFactory, g.properties.ModuleProperties...)
468 } else {
469 imports := make([]string, len(i.properties.Imports))
470 for idx, anImport := range i.properties.Imports {
471 imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + lang
472 }
473 if p, ok := g.properties.ModuleProperties[0].(*ccProperties); ok {
474 p.Shared_libs = append(p.Shared_libs, imports...)
475 p.Export_shared_lib_headers = append(p.Export_shared_lib_headers, imports...)
476 }
477 ctx.CreateModule(cc.LibraryFactory, g.properties.ModuleProperties...)
478 }
479}