fb2721f2a6
The metalava is supported instead of doclava. However, not all sdk
libraries are available now. So metalava_enabled property is added for
it.
when using metalava, DroidstubsFactory module will be created instead of
DroiddocFactory.
Test: make -j
Test: make apicheck
Bug: 117127012
Merged-In: I7fd10230bfe30a4ef4dceb1a4459145b674668cd
Change-Id: I7fd10230bfe30a4ef4dceb1a4459145b674668cd
(cherry picked from commit 0817d01ab1
)
726 lines
25 KiB
Go
726 lines
25 KiB
Go
// Copyright 2018 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package java
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"android/soong/genrule"
|
|
"fmt"
|
|
"io"
|
|
"path"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/google/blueprint"
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
var (
|
|
sdkStubsLibrarySuffix = ".stubs"
|
|
sdkSystemApiSuffix = ".system"
|
|
sdkTestApiSuffix = ".test"
|
|
sdkDocsSuffix = ".docs"
|
|
sdkImplLibrarySuffix = ".impl"
|
|
sdkXmlFileSuffix = ".xml"
|
|
)
|
|
|
|
type stubsLibraryDependencyTag struct {
|
|
blueprint.BaseDependencyTag
|
|
name string
|
|
}
|
|
|
|
var (
|
|
publicApiStubsTag = dependencyTag{name: "public"}
|
|
systemApiStubsTag = dependencyTag{name: "system"}
|
|
testApiStubsTag = dependencyTag{name: "test"}
|
|
implLibTag = dependencyTag{name: "platform"}
|
|
publicApiFileTag = dependencyTag{name: "publicApi"}
|
|
systemApiFileTag = dependencyTag{name: "systemApi"}
|
|
testApiFileTag = dependencyTag{name: "testApi"}
|
|
)
|
|
|
|
type apiScope int
|
|
|
|
const (
|
|
apiScopePublic apiScope = iota
|
|
apiScopeSystem
|
|
apiScopeTest
|
|
)
|
|
|
|
var (
|
|
javaSdkLibrariesLock sync.Mutex
|
|
)
|
|
|
|
// java_sdk_library is to make a Java library that implements optional platform APIs to apps.
|
|
// It is actually a wrapper of several modules: 1) stubs library that clients are linked against
|
|
// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
|
|
// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the
|
|
// classpath at runtime if requested via <uses-library>.
|
|
//
|
|
// TODO: these are big features that are currently missing
|
|
// 1) disallowing linking to the runtime shared lib
|
|
// 2) HTML generation
|
|
|
|
func init() {
|
|
android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
|
|
|
|
android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
|
|
ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
|
|
})
|
|
|
|
android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
|
|
javaSdkLibraries := javaSdkLibraries(ctx.Config())
|
|
sort.Strings(*javaSdkLibraries)
|
|
ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
|
|
})
|
|
}
|
|
|
|
type sdkLibraryProperties struct {
|
|
// list of source files used to compile the Java module. May be .java, .logtags, .proto,
|
|
// or .aidl files.
|
|
Srcs []string `android:"arch_variant"`
|
|
|
|
// list of optional source files that are part of API but not part of runtime library.
|
|
Api_srcs []string `android:"arch_variant"`
|
|
|
|
// list of of java libraries that will be in the classpath
|
|
Libs []string `android:"arch_variant"`
|
|
|
|
// list of java libraries that will be compiled into the resulting runtime jar.
|
|
// These libraries are not compiled into the stubs jar.
|
|
Static_libs []string `android:"arch_variant"`
|
|
|
|
// List of Java libraries that will be in the classpath when building stubs
|
|
Stub_only_libs []string `android:"arch_variant"`
|
|
|
|
// list of package names that will be documented and publicized as API
|
|
Api_packages []string
|
|
|
|
// list of package names that must be hidden from the API
|
|
Hidden_api_packages []string
|
|
|
|
Errorprone struct {
|
|
// List of javac flags that should only be used when running errorprone.
|
|
Javacflags []string
|
|
}
|
|
|
|
// Additional droiddoc options
|
|
Droiddoc_options []string
|
|
|
|
// If set to true, compile dex regardless of installable. Defaults to false.
|
|
// This applies to the stubs lib.
|
|
Compile_dex *bool
|
|
|
|
// the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
|
|
// Defaults to "android.annotation".
|
|
Srcs_lib_whitelist_pkgs []string
|
|
|
|
// if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
|
|
// currently still used for documentation generation, and will be replaced by Dokka soon.
|
|
// Defaults to true.
|
|
Metalava_enabled *bool
|
|
|
|
// TODO: determines whether to create HTML doc or not
|
|
//Html_doc *bool
|
|
}
|
|
|
|
type sdkLibrary struct {
|
|
android.ModuleBase
|
|
android.DefaultableModuleBase
|
|
|
|
properties sdkLibraryProperties
|
|
deviceProperties CompilerDeviceProperties
|
|
|
|
publicApiStubsPath android.Paths
|
|
systemApiStubsPath android.Paths
|
|
testApiStubsPath android.Paths
|
|
implLibPath android.Paths
|
|
|
|
publicApiStubsImplPath android.Paths
|
|
systemApiStubsImplPath android.Paths
|
|
testApiStubsImplPath android.Paths
|
|
implLibImplPath android.Paths
|
|
|
|
publicApiFilePath android.Path
|
|
systemApiFilePath android.Path
|
|
testApiFilePath android.Path
|
|
}
|
|
|
|
func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|
// Add dependencies to the stubs library
|
|
ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
|
|
ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
|
|
ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
|
|
ctx.AddVariationDependencies(nil, implLibTag, module.implName())
|
|
|
|
ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
|
|
ctx.AddVariationDependencies(nil, systemApiFileTag, module.docsName(apiScopeSystem))
|
|
ctx.AddVariationDependencies(nil, testApiFileTag, module.docsName(apiScopeTest))
|
|
}
|
|
|
|
func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
// Record the paths to the header jars of the library (stubs and impl).
|
|
// When this java_sdk_library is dependened from others via "libs" property,
|
|
// the recorded paths will be returned depending on the link type of the caller.
|
|
ctx.VisitDirectDeps(func(to android.Module) {
|
|
otherName := ctx.OtherModuleName(to)
|
|
tag := ctx.OtherModuleDependencyTag(to)
|
|
|
|
if lib, ok := to.(Dependency); ok {
|
|
switch tag {
|
|
case publicApiStubsTag:
|
|
module.publicApiStubsPath = lib.HeaderJars()
|
|
module.publicApiStubsImplPath = lib.ImplementationJars()
|
|
case systemApiStubsTag:
|
|
module.systemApiStubsPath = lib.HeaderJars()
|
|
module.systemApiStubsImplPath = lib.ImplementationJars()
|
|
case testApiStubsTag:
|
|
module.testApiStubsPath = lib.HeaderJars()
|
|
module.testApiStubsImplPath = lib.ImplementationJars()
|
|
case implLibTag:
|
|
module.implLibPath = lib.HeaderJars()
|
|
module.implLibImplPath = lib.ImplementationJars()
|
|
default:
|
|
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
|
|
}
|
|
}
|
|
if doc, ok := to.(ApiFilePath); ok {
|
|
switch tag {
|
|
case publicApiFileTag:
|
|
module.publicApiFilePath = doc.ApiFilePath()
|
|
case systemApiFileTag:
|
|
module.systemApiFilePath = doc.ApiFilePath()
|
|
case testApiFileTag:
|
|
module.testApiFilePath = doc.ApiFilePath()
|
|
default:
|
|
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func (module *sdkLibrary) AndroidMk() android.AndroidMkData {
|
|
return android.AndroidMkData{
|
|
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
|
|
// Create a phony module that installs the impl library, for the case when this lib is
|
|
// in PRODUCT_PACKAGES.
|
|
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
|
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
|
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
|
|
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName())
|
|
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
|
|
owner := module.ModuleBase.Owner()
|
|
if owner == "" {
|
|
owner = "android"
|
|
}
|
|
// Create dist rules to install the stubs libs to the dist dir
|
|
if len(module.publicApiStubsPath) == 1 {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.publicApiStubsPath.Strings()[0]+
|
|
":"+path.Join("apistubs", owner, "public",
|
|
module.BaseModuleName()+".jar")+")")
|
|
}
|
|
if len(module.systemApiStubsPath) == 1 {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.systemApiStubsPath.Strings()[0]+
|
|
":"+path.Join("apistubs", owner, "system",
|
|
module.BaseModuleName()+".jar")+")")
|
|
}
|
|
if len(module.testApiStubsPath) == 1 {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.testApiStubsPath.Strings()[0]+
|
|
":"+path.Join("apistubs", owner, "test",
|
|
module.BaseModuleName()+".jar")+")")
|
|
}
|
|
if module.publicApiFilePath != nil {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.publicApiFilePath.String()+
|
|
":"+path.Join("apistubs", owner, "public", "api",
|
|
module.BaseModuleName()+".txt")+")")
|
|
}
|
|
if module.systemApiFilePath != nil {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.systemApiFilePath.String()+
|
|
":"+path.Join("apistubs", owner, "system", "api",
|
|
module.BaseModuleName()+".txt")+")")
|
|
}
|
|
if module.testApiFilePath != nil {
|
|
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
|
|
module.testApiFilePath.String()+
|
|
":"+path.Join("apistubs", owner, "test", "api",
|
|
module.BaseModuleName()+".txt")+")")
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
// Module name of the stubs library
|
|
func (module *sdkLibrary) stubsName(apiScope apiScope) string {
|
|
stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
|
|
switch apiScope {
|
|
case apiScopeSystem:
|
|
stubsName = stubsName + sdkSystemApiSuffix
|
|
case apiScopeTest:
|
|
stubsName = stubsName + sdkTestApiSuffix
|
|
}
|
|
return stubsName
|
|
}
|
|
|
|
// Module name of the docs
|
|
func (module *sdkLibrary) docsName(apiScope apiScope) string {
|
|
docsName := module.BaseModuleName() + sdkDocsSuffix
|
|
switch apiScope {
|
|
case apiScopeSystem:
|
|
docsName = docsName + sdkSystemApiSuffix
|
|
case apiScopeTest:
|
|
docsName = docsName + sdkTestApiSuffix
|
|
}
|
|
return docsName
|
|
}
|
|
|
|
// Module name of the runtime implementation library
|
|
func (module *sdkLibrary) implName() string {
|
|
return module.BaseModuleName() + sdkImplLibrarySuffix
|
|
}
|
|
|
|
// File path to the runtime implementation library
|
|
func (module *sdkLibrary) implPath() string {
|
|
partition := "system"
|
|
if module.SocSpecific() {
|
|
partition = "vendor"
|
|
} else if module.DeviceSpecific() {
|
|
partition = "odm"
|
|
} else if module.ProductSpecific() {
|
|
partition = "product"
|
|
}
|
|
return "/" + partition + "/framework/" + module.implName() + ".jar"
|
|
}
|
|
|
|
// Module name of the XML file for the lib
|
|
func (module *sdkLibrary) xmlFileName() string {
|
|
return module.BaseModuleName() + sdkXmlFileSuffix
|
|
}
|
|
|
|
// SDK version that the stubs library is built against. Note that this is always
|
|
// *current. Older stubs library built with a numberd SDK version is created from
|
|
// the prebuilt jar.
|
|
func (module *sdkLibrary) sdkVersion(apiScope apiScope) string {
|
|
switch apiScope {
|
|
case apiScopePublic:
|
|
return "current"
|
|
case apiScopeSystem:
|
|
return "system_current"
|
|
case apiScopeTest:
|
|
return "test_current"
|
|
default:
|
|
return "current"
|
|
}
|
|
}
|
|
|
|
// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
|
|
// api file for the current source
|
|
// TODO: remove this when apicheck is done in soong
|
|
func (module *sdkLibrary) apiTagName(apiScope apiScope) string {
|
|
apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
|
|
switch apiScope {
|
|
case apiScopeSystem:
|
|
apiTagName = apiTagName + "_SYSTEM"
|
|
case apiScopeTest:
|
|
apiTagName = apiTagName + "_TEST"
|
|
}
|
|
return apiTagName
|
|
}
|
|
|
|
func (module *sdkLibrary) latestApiFilegroupName(apiScope apiScope) string {
|
|
name := ":" + module.BaseModuleName() + ".api."
|
|
switch apiScope {
|
|
case apiScopePublic:
|
|
name = name + "public"
|
|
case apiScopeSystem:
|
|
name = name + "system"
|
|
case apiScopeTest:
|
|
name = name + "test"
|
|
}
|
|
name = name + ".latest"
|
|
return name
|
|
}
|
|
|
|
func (module *sdkLibrary) latestRemovedApiFilegroupName(apiScope apiScope) string {
|
|
name := ":" + module.BaseModuleName() + "-removed.api."
|
|
switch apiScope {
|
|
case apiScopePublic:
|
|
name = name + "public"
|
|
case apiScopeSystem:
|
|
name = name + "system"
|
|
case apiScopeTest:
|
|
name = name + "test"
|
|
}
|
|
name = name + ".latest"
|
|
return name
|
|
}
|
|
|
|
// Creates a static java library that has API stubs
|
|
func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, apiScope apiScope) {
|
|
props := struct {
|
|
Name *string
|
|
Srcs []string
|
|
Sdk_version *string
|
|
Libs []string
|
|
Soc_specific *bool
|
|
Device_specific *bool
|
|
Product_specific *bool
|
|
Compile_dex *bool
|
|
Product_variables struct {
|
|
Unbundled_build struct {
|
|
Enabled *bool
|
|
}
|
|
Pdk struct {
|
|
Enabled *bool
|
|
}
|
|
}
|
|
}{}
|
|
|
|
props.Name = proptools.StringPtr(module.stubsName(apiScope))
|
|
// sources are generated from the droiddoc
|
|
props.Srcs = []string{":" + module.docsName(apiScope)}
|
|
props.Sdk_version = proptools.StringPtr(module.sdkVersion(apiScope))
|
|
props.Libs = module.properties.Stub_only_libs
|
|
// Unbundled apps will use the prebult one from /prebuilts/sdk
|
|
props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
|
|
props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
|
|
if module.properties.Compile_dex != nil {
|
|
props.Compile_dex = module.properties.Compile_dex
|
|
}
|
|
|
|
if module.SocSpecific() {
|
|
props.Soc_specific = proptools.BoolPtr(true)
|
|
} else if module.DeviceSpecific() {
|
|
props.Device_specific = proptools.BoolPtr(true)
|
|
} else if module.ProductSpecific() {
|
|
props.Product_specific = proptools.BoolPtr(true)
|
|
}
|
|
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props)
|
|
}
|
|
|
|
// Creates a droiddoc module that creates stubs source files from the given full source
|
|
// files
|
|
func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, apiScope apiScope) {
|
|
props := struct {
|
|
Name *string
|
|
Srcs []string
|
|
Installable *bool
|
|
Srcs_lib *string
|
|
Srcs_lib_whitelist_dirs []string
|
|
Srcs_lib_whitelist_pkgs []string
|
|
Libs []string
|
|
Args *string
|
|
Api_tag_name *string
|
|
Api_filename *string
|
|
Removed_api_filename *string
|
|
Check_api struct {
|
|
Current ApiToCheck
|
|
Last_released ApiToCheck
|
|
}
|
|
Aidl struct {
|
|
Include_dirs []string
|
|
Local_include_dirs []string
|
|
}
|
|
}{}
|
|
droiddocProps := struct {
|
|
Custom_template *string
|
|
}{}
|
|
|
|
props.Name = proptools.StringPtr(module.docsName(apiScope))
|
|
props.Srcs = append(props.Srcs, module.properties.Srcs...)
|
|
props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
|
|
props.Installable = proptools.BoolPtr(false)
|
|
// A droiddoc module has only one Libs property and doesn't distinguish between
|
|
// shared libs and static libs. So we need to add both of these libs to Libs property.
|
|
props.Libs = module.properties.Libs
|
|
props.Libs = append(props.Libs, module.properties.Static_libs...)
|
|
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
|
|
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
|
|
|
|
if module.properties.Metalava_enabled == nil {
|
|
module.properties.Metalava_enabled = proptools.BoolPtr(true)
|
|
}
|
|
|
|
droiddocArgs := ""
|
|
if Bool(module.properties.Metalava_enabled) == true {
|
|
droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
|
|
" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
|
|
" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
|
|
" --hide MissingPermission --hide BroadcastBehavior " +
|
|
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
|
|
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
|
|
} else {
|
|
droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
|
|
droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
|
|
" " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
|
|
" " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
|
|
" -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
|
|
}
|
|
|
|
switch apiScope {
|
|
case apiScopeSystem:
|
|
droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
|
|
case apiScopeTest:
|
|
droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
|
|
}
|
|
props.Args = proptools.StringPtr(droiddocArgs)
|
|
|
|
// List of APIs identified from the provided source files are created. They are later
|
|
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
|
|
// last-released (a.k.a numbered) list of API.
|
|
currentApiFileName := "current.txt"
|
|
removedApiFileName := "removed.txt"
|
|
switch apiScope {
|
|
case apiScopeSystem:
|
|
currentApiFileName = "system-" + currentApiFileName
|
|
removedApiFileName = "system-" + removedApiFileName
|
|
case apiScopeTest:
|
|
currentApiFileName = "test-" + currentApiFileName
|
|
removedApiFileName = "test-" + removedApiFileName
|
|
}
|
|
currentApiFileName = path.Join("api", currentApiFileName)
|
|
removedApiFileName = path.Join("api", removedApiFileName)
|
|
// TODO(jiyong): remove these three props
|
|
props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
|
|
props.Api_filename = proptools.StringPtr(currentApiFileName)
|
|
props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
|
|
|
|
// check against the not-yet-release API
|
|
props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
|
|
props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
|
|
|
|
// check against the latest released API
|
|
props.Check_api.Last_released.Api_file = proptools.StringPtr(
|
|
module.latestApiFilegroupName(apiScope))
|
|
props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
|
|
module.latestRemovedApiFilegroupName(apiScope))
|
|
if Bool(module.properties.Metalava_enabled) == false {
|
|
// any change is reported as error
|
|
props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
|
|
"-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
|
|
"-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
|
|
"-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
|
|
|
|
// backward incompatible changes are reported as error
|
|
props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
|
|
"-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
|
|
"-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
|
|
"-error 15 -error 16 -error 17 -error 18")
|
|
|
|
// Include the part of the framework source. This is required for the case when
|
|
// API class is extending from the framework class. In that case, doclava needs
|
|
// to know whether the base class is hidden or not. Since that information is
|
|
// encoded as @hide string in the comment, we need source files for the classes,
|
|
// not the compiled ones.
|
|
props.Srcs_lib = proptools.StringPtr("framework")
|
|
props.Srcs_lib_whitelist_dirs = []string{"core/java"}
|
|
|
|
// Add android.annotation package to give access to the framework-defined
|
|
// annotations such as SystemApi, NonNull, etc.
|
|
if module.properties.Srcs_lib_whitelist_pkgs != nil {
|
|
props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
|
|
} else {
|
|
props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
|
|
}
|
|
}
|
|
// These libs are required by doclava to parse the framework sources add via
|
|
// Src_lib and Src_lib_whitelist_* properties just above.
|
|
// If we don't add them to the classpath, errors messages are generated by doclava,
|
|
// though they don't break the build.
|
|
props.Libs = append(props.Libs, "framework")
|
|
|
|
if Bool(module.properties.Metalava_enabled) == true {
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
|
|
} else {
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
|
|
}
|
|
}
|
|
|
|
// Creates the runtime library. This is not directly linkable from other modules.
|
|
func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) {
|
|
props := struct {
|
|
Name *string
|
|
Srcs []string
|
|
Libs []string
|
|
Static_libs []string
|
|
Soc_specific *bool
|
|
Device_specific *bool
|
|
Product_specific *bool
|
|
Installable *bool
|
|
Required []string
|
|
Errorprone struct {
|
|
Javacflags []string
|
|
}
|
|
}{}
|
|
|
|
props.Name = proptools.StringPtr(module.implName())
|
|
props.Srcs = module.properties.Srcs
|
|
props.Libs = module.properties.Libs
|
|
props.Static_libs = module.properties.Static_libs
|
|
props.Installable = proptools.BoolPtr(true)
|
|
// XML file is installed along with the impl lib
|
|
props.Required = []string{module.xmlFileName()}
|
|
props.Errorprone.Javacflags = module.properties.Errorprone.Javacflags
|
|
|
|
if module.SocSpecific() {
|
|
props.Soc_specific = proptools.BoolPtr(true)
|
|
} else if module.DeviceSpecific() {
|
|
props.Device_specific = proptools.BoolPtr(true)
|
|
} else if module.ProductSpecific() {
|
|
props.Product_specific = proptools.BoolPtr(true)
|
|
}
|
|
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props, &module.deviceProperties)
|
|
}
|
|
|
|
// Creates the xml file that publicizes the runtime library
|
|
func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
|
|
template := `
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- Copyright (C) 2018 The Android Open Source Project
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
-->
|
|
|
|
<permissions>
|
|
<library name="%s" file="%s"/>
|
|
</permissions>
|
|
`
|
|
// genrule to generate the xml file content from the template above
|
|
// TODO: preserve newlines in the generate xml file. Newlines are being squashed
|
|
// in the ninja file. Do we need to have an external tool for this?
|
|
xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath())
|
|
genruleProps := struct {
|
|
Name *string
|
|
Cmd *string
|
|
Out []string
|
|
}{}
|
|
genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
|
|
genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
|
|
genruleProps.Out = []string{module.xmlFileName()}
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
|
|
|
|
// creates a prebuilt_etc module to actually place the xml file under
|
|
// <partition>/etc/permissions
|
|
etcProps := struct {
|
|
Name *string
|
|
Src *string
|
|
Sub_dir *string
|
|
Soc_specific *bool
|
|
Device_specific *bool
|
|
Product_specific *bool
|
|
}{}
|
|
etcProps.Name = proptools.StringPtr(module.xmlFileName())
|
|
etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
|
|
etcProps.Sub_dir = proptools.StringPtr("permissions")
|
|
if module.SocSpecific() {
|
|
etcProps.Soc_specific = proptools.BoolPtr(true)
|
|
} else if module.DeviceSpecific() {
|
|
etcProps.Device_specific = proptools.BoolPtr(true)
|
|
} else if module.ProductSpecific() {
|
|
etcProps.Product_specific = proptools.BoolPtr(true)
|
|
}
|
|
mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
|
|
}
|
|
|
|
// to satisfy SdkLibraryDependency interface
|
|
func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
|
|
// This module is just a wrapper for the stubs.
|
|
if linkType == javaSystem {
|
|
return module.systemApiStubsPath
|
|
} else if linkType == javaPlatform {
|
|
return module.implLibPath
|
|
} else {
|
|
return module.publicApiStubsPath
|
|
}
|
|
}
|
|
|
|
// to satisfy SdkLibraryDependency interface
|
|
func (module *sdkLibrary) ImplementationJars(linkType linkType) android.Paths {
|
|
// This module is just a wrapper for the stubs.
|
|
if linkType == javaSystem {
|
|
return module.systemApiStubsImplPath
|
|
} else if linkType == javaPlatform {
|
|
return module.implLibImplPath
|
|
} else {
|
|
return module.publicApiStubsImplPath
|
|
}
|
|
}
|
|
|
|
func javaSdkLibraries(config android.Config) *[]string {
|
|
return config.Once("javaSdkLibraries", func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
// For a java_sdk_library module, create internal modules for stubs, docs,
|
|
// runtime libs and xml file. If requested, the stubs and docs are created twice
|
|
// once for public API level and once for system API level
|
|
func sdkLibraryMutator(mctx android.TopDownMutatorContext) {
|
|
if module, ok := mctx.Module().(*sdkLibrary); ok {
|
|
if module.properties.Srcs == nil {
|
|
mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
|
|
}
|
|
if module.properties.Api_packages == nil {
|
|
mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
|
|
}
|
|
|
|
// for public API stubs
|
|
module.createStubsLibrary(mctx, apiScopePublic)
|
|
module.createDocs(mctx, apiScopePublic)
|
|
|
|
// for system API stubs
|
|
module.createStubsLibrary(mctx, apiScopeSystem)
|
|
module.createDocs(mctx, apiScopeSystem)
|
|
|
|
// for test API stubs
|
|
module.createStubsLibrary(mctx, apiScopeTest)
|
|
module.createDocs(mctx, apiScopeTest)
|
|
|
|
// for runtime
|
|
module.createXmlFile(mctx)
|
|
module.createImplLibrary(mctx)
|
|
|
|
// record java_sdk_library modules so that they are exported to make
|
|
javaSdkLibraries := javaSdkLibraries(mctx.Config())
|
|
javaSdkLibrariesLock.Lock()
|
|
defer javaSdkLibrariesLock.Unlock()
|
|
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
|
|
}
|
|
}
|
|
|
|
func sdkLibraryFactory() android.Module {
|
|
module := &sdkLibrary{}
|
|
module.AddProperties(&module.properties)
|
|
module.AddProperties(&module.deviceProperties)
|
|
InitJavaModule(module, android.DeviceSupported)
|
|
return module
|
|
}
|