blob: 52e713fa13c4eb419ed2d03bef8dbdb58995d868 [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
71// 2) install stubs libs as the dist artifacts
72// 3) ensuring that apps have appropriate <uses-library> tag
73// 4) disallowing linking to the runtime shared lib
74// 5) HTML generation
75
76func init() {
77 android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
78
79 android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
80 ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
81 })
Jiyong Park82484c02018-04-23 21:41:26 +090082
83 android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
84 javaSdkLibraries := javaSdkLibraries(ctx.Config())
85 sort.Strings(*javaSdkLibraries)
86 ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
87 })
Jiyong Parkc678ad32018-04-10 13:07:10 +090088}
89
90type sdkLibraryProperties struct {
91 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
92 // or .aidl files.
93 Srcs []string `android:"arch_variant"`
94
95 // list of of java libraries that will be in the classpath
96 Libs []string `android:"arch_variant"`
97
98 // list of java libraries that will be compiled into the resulting runtime jar.
99 // These libraries are not compiled into the stubs jar.
100 Static_libs []string `android:"arch_variant"`
101
102 // list of package names that will be documented and publicized as API
103 Api_packages []string
104
105 // TODO: determines whether to create HTML doc or not
106 //Html_doc *bool
107}
108
109type sdkLibrary struct {
110 android.ModuleBase
111 android.DefaultableModuleBase
112
113 properties sdkLibraryProperties
114
115 publicApiStubsPath android.Paths
116 systemApiStubsPath android.Paths
Jiyong Parkdf130542018-04-27 16:29:21 +0900117 testApiStubsPath android.Paths
Jiyong Parkc678ad32018-04-10 13:07:10 +0900118}
119
120func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
121 // Add dependencies to the stubs library
Jiyong Parkdf130542018-04-27 16:29:21 +0900122 ctx.AddDependency(ctx.Module(), publicApiStubsTag, module.stubsName(apiScopePublic))
123 ctx.AddDependency(ctx.Module(), systemApiStubsTag, module.stubsName(apiScopeSystem))
124 ctx.AddDependency(ctx.Module(), testApiStubsTag, module.stubsName(apiScopeTest))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900125}
126
127func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
128 // Record the paths to the header jars of the stubs library.
129 // When this java_sdk_library is dependened from others via "libs" property,
130 // the recorded paths will be returned depending on the link type of the caller.
131 ctx.VisitDirectDeps(func(to android.Module) {
132 otherName := ctx.OtherModuleName(to)
133 tag := ctx.OtherModuleDependencyTag(to)
134
135 if stubs, ok := to.(Dependency); ok {
136 switch tag {
137 case publicApiStubsTag:
138 module.publicApiStubsPath = stubs.HeaderJars()
139 case systemApiStubsTag:
140 module.systemApiStubsPath = stubs.HeaderJars()
Jiyong Parkdf130542018-04-27 16:29:21 +0900141 case testApiStubsTag:
142 module.testApiStubsPath = stubs.HeaderJars()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900143 default:
144 ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
145 }
146 }
147 })
148}
149
Jiyong Park82484c02018-04-23 21:41:26 +0900150func (module *sdkLibrary) AndroidMk() android.AndroidMkData {
151 // Create a phony module that installs the impl library, for the case when this lib is
152 // in PRODUCT_PACKAGES.
153 return android.AndroidMkData{
154 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
155 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
156 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
157 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
158 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName())
159 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
160 },
161 }
162}
163
Jiyong Parkc678ad32018-04-10 13:07:10 +0900164// Module name of the stubs library
Jiyong Parkdf130542018-04-27 16:29:21 +0900165func (module *sdkLibrary) stubsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900166 stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900167 switch apiScope {
168 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900169 stubsName = stubsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900170 case apiScopeTest:
171 stubsName = stubsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900172 }
173 return stubsName
174}
175
176// Module name of the docs
Jiyong Parkdf130542018-04-27 16:29:21 +0900177func (module *sdkLibrary) docsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900178 docsName := module.BaseModuleName() + sdkDocsSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900179 switch apiScope {
180 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900181 docsName = docsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900182 case apiScopeTest:
183 docsName = docsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900184 }
185 return docsName
186}
187
188// Module name of the runtime implementation library
189func (module *sdkLibrary) implName() string {
190 return module.BaseModuleName() + sdkImplLibrarySuffix
191}
192
193// File path to the runtime implementation library
194func (module *sdkLibrary) implPath() string {
195 partition := "system"
196 if module.SocSpecific() {
197 partition = "vendor"
198 } else if module.DeviceSpecific() {
199 partition = "odm"
200 } else if module.ProductSpecific() {
201 partition = "product"
202 }
203 return "/" + partition + "/framework/" + module.implName() + ".jar"
204}
205
206// Module name of the XML file for the lib
207func (module *sdkLibrary) xmlFileName() string {
208 return module.BaseModuleName() + sdkXmlFileSuffix
209}
210
211// SDK version that the stubs library is built against. Note that this is always
212// *current. Older stubs library built with a numberd SDK version is created from
213// the prebuilt jar.
Jiyong Parkdf130542018-04-27 16:29:21 +0900214func (module *sdkLibrary) sdkVersion(apiScope apiScope) string {
215 switch apiScope {
216 case apiScopePublic:
217 return "current"
218 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900219 return "system_current"
Jiyong Parkdf130542018-04-27 16:29:21 +0900220 case apiScopeTest:
221 return "test_current"
222 default:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900223 return "current"
224 }
225}
226
227// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
228// api file for the current source
229// TODO: remove this when apicheck is done in soong
Jiyong Parkdf130542018-04-27 16:29:21 +0900230func (module *sdkLibrary) apiTagName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900231 apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
Jiyong Parkdf130542018-04-27 16:29:21 +0900232 switch apiScope {
233 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900234 apiTagName = apiTagName + "_SYSTEM"
Jiyong Parkdf130542018-04-27 16:29:21 +0900235 case apiScopeTest:
236 apiTagName = apiTagName + "_TEST"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900237 }
238 return apiTagName
239}
240
241// returns the path (relative to this module) to the API txt file. Files are located
242// ./<api_dir>/<api_level>.txt where <api_level> is either current, system-current, removed,
243// or system-removed.
Jiyong Parkdf130542018-04-27 16:29:21 +0900244func (module *sdkLibrary) apiFilePath(apiLevel string, apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900245 apiDir := "api"
246 apiFile := apiLevel
Jiyong Parkdf130542018-04-27 16:29:21 +0900247 switch apiScope {
248 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900249 apiFile = "system-" + apiFile
Jiyong Parkdf130542018-04-27 16:29:21 +0900250 case apiScopeTest:
251 apiFile = "test-" + apiFile
Jiyong Parkc678ad32018-04-10 13:07:10 +0900252 }
253 apiFile = apiFile + ".txt"
254
255 return path.Join(apiDir, apiFile)
256}
257
258// Creates a static java library that has API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900259func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900260 props := struct {
261 Name *string
262 Srcs []string
263 Sdk_version *string
264 Soc_specific *bool
265 Device_specific *bool
266 Product_specific *bool
267 Product_variables struct {
268 Unbundled_build struct {
269 Enabled *bool
270 }
Jiyong Park82484c02018-04-23 21:41:26 +0900271 Pdk struct {
272 Enabled *bool
273 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900274 }
275 }{}
276
Jiyong Parkdf130542018-04-27 16:29:21 +0900277 props.Name = proptools.StringPtr(module.stubsName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900278 // sources are generated from the droiddoc
Jiyong Parkdf130542018-04-27 16:29:21 +0900279 props.Srcs = []string{":" + module.docsName(apiScope)}
280 props.Sdk_version = proptools.StringPtr(module.sdkVersion(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900281 // Unbundled apps will use the prebult one from /prebuilts/sdk
282 props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
Jiyong Park82484c02018-04-23 21:41:26 +0900283 props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900284
285 if module.SocSpecific() {
286 props.Soc_specific = proptools.BoolPtr(true)
287 } else if module.DeviceSpecific() {
288 props.Device_specific = proptools.BoolPtr(true)
289 } else if module.ProductSpecific() {
290 props.Product_specific = proptools.BoolPtr(true)
291 }
292
293 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(false)), &props)
294}
295
296// Creates a droiddoc module that creates stubs source files from the given full source
297// files
Jiyong Parkdf130542018-04-27 16:29:21 +0900298func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900299 props := struct {
300 Name *string
301 Srcs []string
302 Custom_template *string
303 Installable *bool
304 Srcs_lib *string
305 Srcs_lib_whitelist_dirs []string
306 Srcs_lib_whitelist_pkgs []string
307 Libs []string
308 Args *string
309 Api_tag_name *string
310 Api_filename *string
311 Removed_api_filename *string
312 }{}
313
Jiyong Parkdf130542018-04-27 16:29:21 +0900314 props.Name = proptools.StringPtr(module.docsName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900315 props.Srcs = module.properties.Srcs
316 props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
317 props.Installable = proptools.BoolPtr(false)
318 props.Libs = module.properties.Libs
319
320 droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
321 " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
322 " -nodocs"
Jiyong Parkdf130542018-04-27 16:29:21 +0900323 switch apiScope {
324 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900325 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
Jiyong Parkdf130542018-04-27 16:29:21 +0900326 case apiScopeTest:
327 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900328 }
329 props.Args = proptools.StringPtr(droiddocArgs)
330
331 // List of APIs identified from the provided source files are created. They are later
332 // compared against to the not-yet-released (a.k.a current) list of APIs and to the
333 // last-released (a.k.a numbered) list of API.
334 // TODO: If any incompatible change is detected, break the build
335 currentApiFileName := "current.txt"
336 removedApiFileName := "removed.txt"
Jiyong Parkdf130542018-04-27 16:29:21 +0900337 switch apiScope {
338 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900339 currentApiFileName = "system-" + currentApiFileName
340 removedApiFileName = "system-" + removedApiFileName
Jiyong Parkdf130542018-04-27 16:29:21 +0900341 case apiScopeTest:
342 currentApiFileName = "test-" + currentApiFileName
343 removedApiFileName = "test-" + removedApiFileName
Jiyong Parkc678ad32018-04-10 13:07:10 +0900344 }
345 currentApiFileName = path.Join("api", currentApiFileName)
346 removedApiFileName = path.Join("api", removedApiFileName)
Jiyong Parkdf130542018-04-27 16:29:21 +0900347 props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900348 // Note: the exact names of these two are not important because they are always
349 // referenced by the make variable $(INTERNAL_PLATFORM_<TAG_NAME>_API_FILE)
350 props.Api_filename = proptools.StringPtr(currentApiFileName)
351 props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
352
Jiyong Park82484c02018-04-23 21:41:26 +0900353 // Include the part of the framework source. This is required for the case when
354 // API class is extending from the framework class. In that case, doclava needs
355 // to know whether the base class is hidden or not. Since that information is
356 // encoded as @hide string in the comment, we need source files for the classes,
357 // not the compiled ones. Also there are rare cases where part of SDK library is
358 // implemented in the framework (e.g. org.apache.http.legacy). In that case,
359 // we need framework source to make API stubs, though the sources are not
360 // required to build the runtime library.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900361 props.Srcs_lib = proptools.StringPtr("framework")
362 props.Srcs_lib_whitelist_dirs = []string{"core/java"}
Jiyong Park82484c02018-04-23 21:41:26 +0900363 props.Srcs_lib_whitelist_pkgs = module.properties.Api_packages
364 // Add android.annotation package to give access to the framework-defined
365 // annotations such as SystemApi, NonNull, etc.
366 props.Srcs_lib_whitelist_pkgs = append(props.Srcs_lib_whitelist_pkgs, "android.annotation")
367 // These libs are required by doclava to parse the framework sources add via
368 // Src_lib and Src_lib_whitelist_* properties just above.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900369 // If we don't add them to the classpath, errors messages are generated by doclava,
370 // though they don't break the build.
Jiyong Park82484c02018-04-23 21:41:26 +0900371 props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp", "framework")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900372
373 mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
374}
375
376// Creates the runtime library. This is not directly linkable from other modules.
377func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) {
378 props := struct {
379 Name *string
380 Srcs []string
381 Libs []string
382 Static_libs []string
383 Soc_specific *bool
384 Device_specific *bool
385 Product_specific *bool
386 Required []string
387 }{}
388
389 props.Name = proptools.StringPtr(module.implName())
390 props.Srcs = module.properties.Srcs
391 props.Libs = module.properties.Libs
392 props.Static_libs = module.properties.Static_libs
393 // XML file is installed along with the impl lib
394 props.Required = []string{module.xmlFileName()}
395
396 if module.SocSpecific() {
397 props.Soc_specific = proptools.BoolPtr(true)
398 } else if module.DeviceSpecific() {
399 props.Device_specific = proptools.BoolPtr(true)
400 } else if module.ProductSpecific() {
401 props.Product_specific = proptools.BoolPtr(true)
402 }
403
404 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory(true)), &props)
405}
406
407// Creates the xml file that publicizes the runtime library
408func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
409 template := `
410<?xml version="1.0" encoding="utf-8"?>
411<!-- Copyright (C) 2018 The Android Open Source Project
412
413 Licensed under the Apache License, Version 2.0 (the "License");
414 you may not use this file except in compliance with the License.
415 You may obtain a copy of the License at
416
417 http://www.apache.org/licenses/LICENSE-2.0
418
419 Unless required by applicable law or agreed to in writing, software
420 distributed under the License is distributed on an "AS IS" BASIS,
421 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
422 See the License for the specific language governing permissions and
423 limitations under the License.
424-->
425
426<permissions>
427 <library name="%s" file="%s"/>
428</permissions>
429`
430 // genrule to generate the xml file content from the template above
431 // TODO: preserve newlines in the generate xml file. Newlines are being squashed
432 // in the ninja file. Do we need to have an external tool for this?
433 xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath())
434 genruleProps := struct {
435 Name *string
436 Cmd *string
437 Out []string
438 }{}
439 genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
440 genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
441 genruleProps.Out = []string{module.xmlFileName()}
442 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
443
444 // creates a prebuilt_etc module to actually place the xml file under
445 // <partition>/etc/permissions
446 etcProps := struct {
447 Name *string
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900448 Src *string
Jiyong Parkc678ad32018-04-10 13:07:10 +0900449 Sub_dir *string
450 Soc_specific *bool
451 Device_specific *bool
452 Product_specific *bool
453 }{}
454 etcProps.Name = proptools.StringPtr(module.xmlFileName())
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900455 etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900456 etcProps.Sub_dir = proptools.StringPtr("permissions")
457 if module.SocSpecific() {
458 etcProps.Soc_specific = proptools.BoolPtr(true)
459 } else if module.DeviceSpecific() {
460 etcProps.Device_specific = proptools.BoolPtr(true)
461 } else if module.ProductSpecific() {
462 etcProps.Product_specific = proptools.BoolPtr(true)
463 }
464 mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
465}
466
467// to satisfy SdkLibraryDependency interface
468func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
469 // This module is just a wrapper for the stubs.
470 if linkType == javaSystem || linkType == javaPlatform {
471 return module.systemApiStubsPath
472 } else {
473 return module.publicApiStubsPath
474 }
475}
476
Jiyong Park82484c02018-04-23 21:41:26 +0900477func javaSdkLibraries(config android.Config) *[]string {
478 return config.Once("javaSdkLibraries", func() interface{} {
479 return &[]string{}
480 }).(*[]string)
481}
482
Jiyong Parkc678ad32018-04-10 13:07:10 +0900483// For a java_sdk_library module, create internal modules for stubs, docs,
484// runtime libs and xml file. If requested, the stubs and docs are created twice
485// once for public API level and once for system API level
486func sdkLibraryMutator(mctx android.TopDownMutatorContext) {
487 if module, ok := mctx.Module().(*sdkLibrary); ok {
Anton Hansson8959e142018-04-25 11:56:13 +0100488 if module.properties.Srcs == nil {
489 mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
490 }
491 if module.properties.Api_packages == nil {
492 mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
493 }
494
Jiyong Parkc678ad32018-04-10 13:07:10 +0900495 // for public API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900496 module.createStubsLibrary(mctx, apiScopePublic)
497 module.createDocs(mctx, apiScopePublic)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900498
499 // for system API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900500 module.createStubsLibrary(mctx, apiScopeSystem)
501 module.createDocs(mctx, apiScopeSystem)
502
503 // for test API stubs
504 module.createStubsLibrary(mctx, apiScopeTest)
505 module.createDocs(mctx, apiScopeTest)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900506
507 // for runtime
508 module.createXmlFile(mctx)
509 module.createImplLibrary(mctx)
Jiyong Park82484c02018-04-23 21:41:26 +0900510
511 // record java_sdk_library modules so that they are exported to make
512 javaSdkLibraries := javaSdkLibraries(mctx.Config())
513 javaSdkLibrariesLock.Lock()
514 defer javaSdkLibrariesLock.Unlock()
515 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
Jiyong Parkc678ad32018-04-10 13:07:10 +0900516 }
517}
518
519func sdkLibraryFactory() android.Module {
520 module := &sdkLibrary{}
521 module.AddProperties(&module.properties)
522 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
523 android.InitDefaultableModule(module)
524 return module
525}