blob: ee6998c397fa2809b9d6d39a69823f08f7369177 [file] [log] [blame]
Jiyong Parkc678ad32018-04-10 13:07:10 +09001// 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 "android/soong/android"
19 "android/soong/genrule"
20 "fmt"
Jiyong Park82484c02018-04-23 21:41:26 +090021 "io"
Jiyong Parkc678ad32018-04-10 13:07:10 +090022 "path"
Jiyong Park82484c02018-04-23 21:41:26 +090023 "sort"
Jiyong Parkc678ad32018-04-10 13:07:10 +090024 "strings"
Jiyong Park82484c02018-04-23 21:41:26 +090025 "sync"
Jiyong Parkc678ad32018-04-10 13:07:10 +090026
27 "github.com/google/blueprint"
28 "github.com/google/blueprint/proptools"
29)
30
31var (
32 sdkStubsLibrarySuffix = ".stubs"
33 sdkSystemApiSuffix = ".system"
Jiyong Parkdf130542018-04-27 16:29:21 +090034 sdkTestApiSuffix = ".test"
Jiyong Parkc678ad32018-04-10 13:07:10 +090035 sdkDocsSuffix = ".docs"
36 sdkImplLibrarySuffix = ".impl"
37 sdkXmlFileSuffix = ".xml"
38)
39
40type stubsLibraryDependencyTag struct {
41 blueprint.BaseDependencyTag
42 name string
43}
44
45var (
46 publicApiStubsTag = dependencyTag{name: "public"}
47 systemApiStubsTag = dependencyTag{name: "system"}
Jiyong Parkdf130542018-04-27 16:29:21 +090048 testApiStubsTag = dependencyTag{name: "test"}
49)
50
51type apiScope int
52
53const (
54 apiScopePublic apiScope = iota
55 apiScopeSystem
56 apiScopeTest
Jiyong Parkc678ad32018-04-10 13:07:10 +090057)
58
Jiyong Park82484c02018-04-23 21:41:26 +090059var (
60 javaSdkLibrariesLock sync.Mutex
61)
62
Jiyong Parkc678ad32018-04-10 13:07:10 +090063// java_sdk_library is to make a Java library that implements optional platform APIs to apps.
64// It is actually a wrapper of several modules: 1) stubs library that clients are linked against
65// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
66// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the
67// classpath at runtime if requested via <uses-library>.
68//
69// TODO: these are big features that are currently missing
70// 1) check for API consistency
Jiyong Park90078382018-05-02 19:30:15 +090071// 2) ensuring that apps have appropriate <uses-library> tag
72// 3) disallowing linking to the runtime shared lib
73// 4) HTML generation
Jiyong Parkc678ad32018-04-10 13:07:10 +090074
75func init() {
76 android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
77
78 android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
79 ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
80 })
Jiyong Park82484c02018-04-23 21:41:26 +090081
82 android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
83 javaSdkLibraries := javaSdkLibraries(ctx.Config())
84 sort.Strings(*javaSdkLibraries)
85 ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
86 })
Jiyong Parkc678ad32018-04-10 13:07:10 +090087}
88
89type sdkLibraryProperties struct {
90 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
91 // or .aidl files.
92 Srcs []string `android:"arch_variant"`
93
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +090094 // list of optional source files that are part of API but not part of runtime library.
95 Api_srcs []string `android:"arch_variant"`
96
Jiyong Parkc678ad32018-04-10 13:07:10 +090097 // list of of java libraries that will be in the classpath
98 Libs []string `android:"arch_variant"`
99
100 // list of java libraries that will be compiled into the resulting runtime jar.
101 // These libraries are not compiled into the stubs jar.
102 Static_libs []string `android:"arch_variant"`
103
104 // list of package names that will be documented and publicized as API
105 Api_packages []string
106
Jiyong Park5a2c9d72018-05-01 22:25:41 +0900107 // list of package names that must be hidden from the API
108 Hidden_api_packages []string
109
Jiyong Parkc678ad32018-04-10 13:07:10 +0900110 // TODO: determines whether to create HTML doc or not
111 //Html_doc *bool
112}
113
114type sdkLibrary struct {
115 android.ModuleBase
116 android.DefaultableModuleBase
117
Jiyong Park441a47d2018-05-01 23:33:08 +0900118 properties sdkLibraryProperties
119 deviceProperties CompilerDeviceProperties
Jiyong Parkc678ad32018-04-10 13:07:10 +0900120
121 publicApiStubsPath android.Paths
122 systemApiStubsPath android.Paths
Jiyong Parkdf130542018-04-27 16:29:21 +0900123 testApiStubsPath android.Paths
Jiyong Parkc678ad32018-04-10 13:07:10 +0900124}
125
126func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
127 // Add dependencies to the stubs library
Jiyong Parkdf130542018-04-27 16:29:21 +0900128 ctx.AddDependency(ctx.Module(), publicApiStubsTag, module.stubsName(apiScopePublic))
129 ctx.AddDependency(ctx.Module(), systemApiStubsTag, module.stubsName(apiScopeSystem))
130 ctx.AddDependency(ctx.Module(), testApiStubsTag, module.stubsName(apiScopeTest))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900131}
132
133func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
134 // Record the paths to the header jars of the stubs library.
135 // When this java_sdk_library is dependened from others via "libs" property,
136 // the recorded paths will be returned depending on the link type of the caller.
137 ctx.VisitDirectDeps(func(to android.Module) {
138 otherName := ctx.OtherModuleName(to)
139 tag := ctx.OtherModuleDependencyTag(to)
140
141 if stubs, ok := to.(Dependency); ok {
142 switch tag {
143 case publicApiStubsTag:
144 module.publicApiStubsPath = stubs.HeaderJars()
145 case systemApiStubsTag:
146 module.systemApiStubsPath = stubs.HeaderJars()
Jiyong Parkdf130542018-04-27 16:29:21 +0900147 case testApiStubsTag:
148 module.testApiStubsPath = stubs.HeaderJars()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900149 default:
150 ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
151 }
152 }
153 })
154}
155
Jiyong Park82484c02018-04-23 21:41:26 +0900156func (module *sdkLibrary) AndroidMk() android.AndroidMkData {
Jiyong Park82484c02018-04-23 21:41:26 +0900157 return android.AndroidMkData{
158 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
Jiyong Park90078382018-05-02 19:30:15 +0900159 // Create a phony module that installs the impl library, for the case when this lib is
160 // in PRODUCT_PACKAGES.
Jiyong Park82484c02018-04-23 21:41:26 +0900161 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
162 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
163 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
164 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName())
165 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
Jiyong Park90078382018-05-02 19:30:15 +0900166 // Create dist rules to install the stubs libs to the dist dir
Jiyong Parkb674a522018-05-06 07:53:02 +0900167 if len(module.publicApiStubsPath) == 1 {
168 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
169 module.publicApiStubsPath.Strings()[0]+
170 ":"+path.Join("apistubs", "public", module.BaseModuleName()+".jar")+")")
171 }
172 if len(module.systemApiStubsPath) == 1 {
173 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
174 module.systemApiStubsPath.Strings()[0]+
175 ":"+path.Join("apistubs", "system", module.BaseModuleName()+".jar")+")")
176 }
177 if len(module.testApiStubsPath) == 1 {
178 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
179 module.testApiStubsPath.Strings()[0]+
180 ":"+path.Join("apistubs", "test", module.BaseModuleName()+".jar")+")")
181 }
Jiyong Park82484c02018-04-23 21:41:26 +0900182 },
183 }
184}
185
Jiyong Parkc678ad32018-04-10 13:07:10 +0900186// Module name of the stubs library
Jiyong Parkdf130542018-04-27 16:29:21 +0900187func (module *sdkLibrary) stubsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900188 stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900189 switch apiScope {
190 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900191 stubsName = stubsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900192 case apiScopeTest:
193 stubsName = stubsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900194 }
195 return stubsName
196}
197
198// Module name of the docs
Jiyong Parkdf130542018-04-27 16:29:21 +0900199func (module *sdkLibrary) docsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900200 docsName := module.BaseModuleName() + sdkDocsSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900201 switch apiScope {
202 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900203 docsName = docsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900204 case apiScopeTest:
205 docsName = docsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900206 }
207 return docsName
208}
209
210// Module name of the runtime implementation library
211func (module *sdkLibrary) implName() string {
212 return module.BaseModuleName() + sdkImplLibrarySuffix
213}
214
215// File path to the runtime implementation library
216func (module *sdkLibrary) implPath() string {
217 partition := "system"
218 if module.SocSpecific() {
219 partition = "vendor"
220 } else if module.DeviceSpecific() {
221 partition = "odm"
222 } else if module.ProductSpecific() {
223 partition = "product"
224 }
225 return "/" + partition + "/framework/" + module.implName() + ".jar"
226}
227
228// Module name of the XML file for the lib
229func (module *sdkLibrary) xmlFileName() string {
230 return module.BaseModuleName() + sdkXmlFileSuffix
231}
232
233// SDK version that the stubs library is built against. Note that this is always
234// *current. Older stubs library built with a numberd SDK version is created from
235// the prebuilt jar.
Jiyong Parkdf130542018-04-27 16:29:21 +0900236func (module *sdkLibrary) sdkVersion(apiScope apiScope) string {
237 switch apiScope {
238 case apiScopePublic:
239 return "current"
240 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900241 return "system_current"
Jiyong Parkdf130542018-04-27 16:29:21 +0900242 case apiScopeTest:
243 return "test_current"
244 default:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900245 return "current"
246 }
247}
248
249// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
250// api file for the current source
251// TODO: remove this when apicheck is done in soong
Jiyong Parkdf130542018-04-27 16:29:21 +0900252func (module *sdkLibrary) apiTagName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900253 apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
Jiyong Parkdf130542018-04-27 16:29:21 +0900254 switch apiScope {
255 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900256 apiTagName = apiTagName + "_SYSTEM"
Jiyong Parkdf130542018-04-27 16:29:21 +0900257 case apiScopeTest:
258 apiTagName = apiTagName + "_TEST"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900259 }
260 return apiTagName
261}
262
263// returns the path (relative to this module) to the API txt file. Files are located
264// ./<api_dir>/<api_level>.txt where <api_level> is either current, system-current, removed,
265// or system-removed.
Jiyong Parkdf130542018-04-27 16:29:21 +0900266func (module *sdkLibrary) apiFilePath(apiLevel string, apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900267 apiDir := "api"
268 apiFile := apiLevel
Jiyong Parkdf130542018-04-27 16:29:21 +0900269 switch apiScope {
270 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900271 apiFile = "system-" + apiFile
Jiyong Parkdf130542018-04-27 16:29:21 +0900272 case apiScopeTest:
273 apiFile = "test-" + apiFile
Jiyong Parkc678ad32018-04-10 13:07:10 +0900274 }
275 apiFile = apiFile + ".txt"
276
277 return path.Join(apiDir, apiFile)
278}
279
280// Creates a static java library that has API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900281func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900282 props := struct {
283 Name *string
284 Srcs []string
285 Sdk_version *string
286 Soc_specific *bool
287 Device_specific *bool
288 Product_specific *bool
289 Product_variables struct {
290 Unbundled_build struct {
291 Enabled *bool
292 }
Jiyong Park82484c02018-04-23 21:41:26 +0900293 Pdk struct {
294 Enabled *bool
295 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900296 }
297 }{}
298
Jiyong Parkdf130542018-04-27 16:29:21 +0900299 props.Name = proptools.StringPtr(module.stubsName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900300 // sources are generated from the droiddoc
Jiyong Parkdf130542018-04-27 16:29:21 +0900301 props.Srcs = []string{":" + module.docsName(apiScope)}
302 props.Sdk_version = proptools.StringPtr(module.sdkVersion(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900303 // Unbundled apps will use the prebult one from /prebuilts/sdk
304 props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
Jiyong Park82484c02018-04-23 21:41:26 +0900305 props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900306
307 if module.SocSpecific() {
308 props.Soc_specific = proptools.BoolPtr(true)
309 } else if module.DeviceSpecific() {
310 props.Device_specific = proptools.BoolPtr(true)
311 } else if module.ProductSpecific() {
312 props.Product_specific = proptools.BoolPtr(true)
313 }
314
315 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(false)), &props)
316}
317
318// Creates a droiddoc module that creates stubs source files from the given full source
319// files
Jiyong Parkdf130542018-04-27 16:29:21 +0900320func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900321 props := struct {
322 Name *string
323 Srcs []string
324 Custom_template *string
325 Installable *bool
326 Srcs_lib *string
327 Srcs_lib_whitelist_dirs []string
328 Srcs_lib_whitelist_pkgs []string
329 Libs []string
330 Args *string
331 Api_tag_name *string
332 Api_filename *string
333 Removed_api_filename *string
334 }{}
335
Jiyong Parkdf130542018-04-27 16:29:21 +0900336 props.Name = proptools.StringPtr(module.docsName(apiScope))
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +0900337 props.Srcs = append(props.Srcs, module.properties.Srcs...)
338 props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900339 props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
340 props.Installable = proptools.BoolPtr(false)
341 props.Libs = module.properties.Libs
342
343 droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
344 " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
Jiyong Park5a2c9d72018-05-01 22:25:41 +0900345 " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, "-hidePackage ") +
Jiyong Parkc678ad32018-04-10 13:07:10 +0900346 " -nodocs"
Jiyong Parkdf130542018-04-27 16:29:21 +0900347 switch apiScope {
348 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900349 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
Jiyong Parkdf130542018-04-27 16:29:21 +0900350 case apiScopeTest:
351 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900352 }
353 props.Args = proptools.StringPtr(droiddocArgs)
354
355 // List of APIs identified from the provided source files are created. They are later
356 // compared against to the not-yet-released (a.k.a current) list of APIs and to the
357 // last-released (a.k.a numbered) list of API.
358 // TODO: If any incompatible change is detected, break the build
359 currentApiFileName := "current.txt"
360 removedApiFileName := "removed.txt"
Jiyong Parkdf130542018-04-27 16:29:21 +0900361 switch apiScope {
362 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900363 currentApiFileName = "system-" + currentApiFileName
364 removedApiFileName = "system-" + removedApiFileName
Jiyong Parkdf130542018-04-27 16:29:21 +0900365 case apiScopeTest:
366 currentApiFileName = "test-" + currentApiFileName
367 removedApiFileName = "test-" + removedApiFileName
Jiyong Parkc678ad32018-04-10 13:07:10 +0900368 }
369 currentApiFileName = path.Join("api", currentApiFileName)
370 removedApiFileName = path.Join("api", removedApiFileName)
Jiyong Parkdf130542018-04-27 16:29:21 +0900371 props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900372 // Note: the exact names of these two are not important because they are always
373 // referenced by the make variable $(INTERNAL_PLATFORM_<TAG_NAME>_API_FILE)
374 props.Api_filename = proptools.StringPtr(currentApiFileName)
375 props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
376
Jiyong Park82484c02018-04-23 21:41:26 +0900377 // Include the part of the framework source. This is required for the case when
378 // API class is extending from the framework class. In that case, doclava needs
379 // to know whether the base class is hidden or not. Since that information is
380 // encoded as @hide string in the comment, we need source files for the classes,
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +0900381 // not the compiled ones.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900382 props.Srcs_lib = proptools.StringPtr("framework")
383 props.Srcs_lib_whitelist_dirs = []string{"core/java"}
Jiyong Park82484c02018-04-23 21:41:26 +0900384 // Add android.annotation package to give access to the framework-defined
385 // annotations such as SystemApi, NonNull, etc.
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +0900386 props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
Jiyong Park82484c02018-04-23 21:41:26 +0900387 // These libs are required by doclava to parse the framework sources add via
388 // Src_lib and Src_lib_whitelist_* properties just above.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900389 // If we don't add them to the classpath, errors messages are generated by doclava,
390 // though they don't break the build.
Jiyong Park82484c02018-04-23 21:41:26 +0900391 props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp", "framework")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900392
393 mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
394}
395
396// Creates the runtime library. This is not directly linkable from other modules.
397func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) {
398 props := struct {
399 Name *string
400 Srcs []string
401 Libs []string
402 Static_libs []string
403 Soc_specific *bool
404 Device_specific *bool
405 Product_specific *bool
406 Required []string
407 }{}
408
409 props.Name = proptools.StringPtr(module.implName())
410 props.Srcs = module.properties.Srcs
411 props.Libs = module.properties.Libs
412 props.Static_libs = module.properties.Static_libs
413 // XML file is installed along with the impl lib
414 props.Required = []string{module.xmlFileName()}
415
416 if module.SocSpecific() {
417 props.Soc_specific = proptools.BoolPtr(true)
418 } else if module.DeviceSpecific() {
419 props.Device_specific = proptools.BoolPtr(true)
420 } else if module.ProductSpecific() {
421 props.Product_specific = proptools.BoolPtr(true)
422 }
423
Jiyong Park441a47d2018-05-01 23:33:08 +0900424 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(true)), &props, &module.deviceProperties)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900425}
426
427// Creates the xml file that publicizes the runtime library
428func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
429 template := `
430<?xml version="1.0" encoding="utf-8"?>
431<!-- Copyright (C) 2018 The Android Open Source Project
432
433 Licensed under the Apache License, Version 2.0 (the "License");
434 you may not use this file except in compliance with the License.
435 You may obtain a copy of the License at
436
437 http://www.apache.org/licenses/LICENSE-2.0
438
439 Unless required by applicable law or agreed to in writing, software
440 distributed under the License is distributed on an "AS IS" BASIS,
441 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
442 See the License for the specific language governing permissions and
443 limitations under the License.
444-->
445
446<permissions>
447 <library name="%s" file="%s"/>
448</permissions>
449`
450 // genrule to generate the xml file content from the template above
451 // TODO: preserve newlines in the generate xml file. Newlines are being squashed
452 // in the ninja file. Do we need to have an external tool for this?
453 xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath())
454 genruleProps := struct {
455 Name *string
456 Cmd *string
457 Out []string
458 }{}
459 genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
460 genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
461 genruleProps.Out = []string{module.xmlFileName()}
462 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
463
464 // creates a prebuilt_etc module to actually place the xml file under
465 // <partition>/etc/permissions
466 etcProps := struct {
467 Name *string
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900468 Src *string
Jiyong Parkc678ad32018-04-10 13:07:10 +0900469 Sub_dir *string
470 Soc_specific *bool
471 Device_specific *bool
472 Product_specific *bool
473 }{}
474 etcProps.Name = proptools.StringPtr(module.xmlFileName())
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900475 etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900476 etcProps.Sub_dir = proptools.StringPtr("permissions")
477 if module.SocSpecific() {
478 etcProps.Soc_specific = proptools.BoolPtr(true)
479 } else if module.DeviceSpecific() {
480 etcProps.Device_specific = proptools.BoolPtr(true)
481 } else if module.ProductSpecific() {
482 etcProps.Product_specific = proptools.BoolPtr(true)
483 }
484 mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
485}
486
487// to satisfy SdkLibraryDependency interface
488func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
489 // This module is just a wrapper for the stubs.
490 if linkType == javaSystem || linkType == javaPlatform {
491 return module.systemApiStubsPath
492 } else {
493 return module.publicApiStubsPath
494 }
495}
496
Jiyong Park82484c02018-04-23 21:41:26 +0900497func javaSdkLibraries(config android.Config) *[]string {
498 return config.Once("javaSdkLibraries", func() interface{} {
499 return &[]string{}
500 }).(*[]string)
501}
502
Jiyong Parkc678ad32018-04-10 13:07:10 +0900503// For a java_sdk_library module, create internal modules for stubs, docs,
504// runtime libs and xml file. If requested, the stubs and docs are created twice
505// once for public API level and once for system API level
506func sdkLibraryMutator(mctx android.TopDownMutatorContext) {
507 if module, ok := mctx.Module().(*sdkLibrary); ok {
Anton Hansson8959e142018-04-25 11:56:13 +0100508 if module.properties.Srcs == nil {
509 mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
510 }
511 if module.properties.Api_packages == nil {
512 mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
513 }
514
Jiyong Parkc678ad32018-04-10 13:07:10 +0900515 // for public API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900516 module.createStubsLibrary(mctx, apiScopePublic)
517 module.createDocs(mctx, apiScopePublic)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900518
519 // for system API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900520 module.createStubsLibrary(mctx, apiScopeSystem)
521 module.createDocs(mctx, apiScopeSystem)
522
523 // for test API stubs
524 module.createStubsLibrary(mctx, apiScopeTest)
525 module.createDocs(mctx, apiScopeTest)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900526
527 // for runtime
528 module.createXmlFile(mctx)
529 module.createImplLibrary(mctx)
Jiyong Park82484c02018-04-23 21:41:26 +0900530
531 // record java_sdk_library modules so that they are exported to make
532 javaSdkLibraries := javaSdkLibraries(mctx.Config())
533 javaSdkLibrariesLock.Lock()
534 defer javaSdkLibrariesLock.Unlock()
535 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
Jiyong Parkc678ad32018-04-10 13:07:10 +0900536 }
537}
538
539func sdkLibraryFactory() android.Module {
540 module := &sdkLibrary{}
541 module.AddProperties(&module.properties)
Jiyong Park441a47d2018-05-01 23:33:08 +0900542 module.AddProperties(&module.deviceProperties)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900543 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
544 android.InitDefaultableModule(module)
545 return module
546}