summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.bp2
-rw-r--r--java/androidmk.go3
-rw-r--r--java/boot_image.go96
-rw-r--r--java/dexpreopt.go40
-rw-r--r--java/hiddenapi.go28
-rw-r--r--java/hiddenapi_modular.go185
-rw-r--r--java/hiddenapi_singleton.go117
-rw-r--r--java/hiddenapi_singleton_test.go34
-rw-r--r--java/java.go34
-rw-r--r--java/java_test.go192
-rw-r--r--java/lint.go55
-rw-r--r--java/lint_test.go204
-rw-r--r--java/platform_bootclasspath.go43
-rw-r--r--java/platform_bootclasspath_test.go92
-rw-r--r--java/sdk.go6
-rw-r--r--java/sdk_library.go59
-rw-r--r--java/testing.go6
17 files changed, 888 insertions, 308 deletions
diff --git a/java/Android.bp b/java/Android.bp
index 2a4b596ab..8e3e10d9d 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -79,9 +79,11 @@ bootstrap_go_package {
"droiddoc_test.go",
"droidstubs_test.go",
"hiddenapi_singleton_test.go",
+ "jacoco_test.go",
"java_test.go",
"jdeps_test.go",
"kotlin_test.go",
+ "lint_test.go",
"platform_bootclasspath_test.go",
"platform_compat_config_test.go",
"plugin_test.go",
diff --git a/java/androidmk.go b/java/androidmk.go
index 4e594a2fa..015454464 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -398,6 +398,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if len(app.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled)
}
+ if app.dexpreopter.configPath != nil {
+ entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", app.dexpreopter.configPath)
+ }
for _, extra := range app.extraOutputFiles {
install := app.onDeviceDir + "/" + extra.Base()
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
diff --git a/java/boot_image.go b/java/boot_image.go
index 0c4797609..d0862a961 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -16,6 +16,7 @@ package java
import (
"fmt"
+ "path/filepath"
"strings"
"android/soong/android"
@@ -53,7 +54,7 @@ func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory)
}
-type bootImageContentDependencyTag struct {
+type bootclasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
@@ -62,16 +63,22 @@ type bootImageContentDependencyTag struct {
// This is a temporary workaround to make it easier to migrate to boot image modules with proper
// dependencies.
// TODO(b/177892522): Remove this and add needed visibility.
-func (b bootImageContentDependencyTag) ExcludeFromVisibilityEnforcement() {
+func (b bootclasspathFragmentContentDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+// The bootclasspath_fragment contents must never depend on prebuilts.
+func (b bootclasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool {
+ return false
}
// The tag used for the dependency between the boot image module and its contents.
-var bootImageContentDepTag = bootImageContentDependencyTag{}
+var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
-var _ android.ExcludeFromVisibilityEnforcementTag = bootImageContentDepTag
+var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
+var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
-func IsbootImageContentDepTag(tag blueprint.DependencyTag) bool {
- return tag == bootImageContentDepTag
+func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
+ return tag == bootclasspathFragmentContentDepTag
}
type bootImageProperties struct {
@@ -84,6 +91,8 @@ type bootImageProperties struct {
//
// The order of this list matters as it is the order that is used in the bootclasspath.
Contents []string
+
+ Hidden_api HiddenAPIFlagFileProperties
}
type BootImageModule struct {
@@ -185,7 +194,7 @@ func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]an
func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
- if tag == bootImageContentDepTag {
+ if IsBootclasspathFragmentContentDepTag(tag) {
// Boot image contents are automatically added to apex.
return true
}
@@ -200,8 +209,28 @@ func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
return nil
}
+// ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a
+// corresponding source module are renamed. This means that adding a dependency using a name without
+// a prebuilt_ prefix will always resolve to a source module and when using a name with that prefix
+// it will always resolve to a prebuilt module.
+func (b *BootImageModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+ module := ctx.Module()
+ _, isSourceModule := module.(*BootImageModule)
+
+ for _, name := range b.properties.Contents {
+ // A bootclasspath_fragment must depend only on other source modules, while the
+ // prebuilt_bootclasspath_fragment must only depend on other prebuilt modules.
+ //
+ // TODO(b/177892522) - avoid special handling of jacocoagent.
+ if !isSourceModule && name != "jacocoagent" {
+ name = android.PrebuiltNameFromSource(name)
+ }
+ ctx.AddDependency(module, bootclasspathFragmentContentDepTag, name)
+ }
+
+}
+
func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
if SkipDexpreoptBootJars(ctx) {
return
@@ -213,6 +242,9 @@ func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Perform hidden API processing.
+ b.generateHiddenAPIBuildActions(ctx)
+
// Nothing to do if skipping the dexpreopt of boot image jars.
if SkipDexpreoptBootJars(ctx) {
return
@@ -253,6 +285,15 @@ func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootIm
return imageConfig
}
+// generateHiddenAPIBuildActions generates all the hidden API related build rules.
+func (b *BootImageModule) generateHiddenAPIBuildActions(ctx android.ModuleContext) {
+ // Resolve the properties to paths.
+ flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
+
+ // Store the information for use by platform_bootclasspath.
+ ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+}
+
type bootImageMemberType struct {
android.SdkMemberTypeBase
}
@@ -281,19 +322,58 @@ func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberP
type bootImageSdkMemberProperties struct {
android.SdkMemberPropertiesBase
+ // The image name
Image_name *string
+
+ // Contents of the bootclasspath fragment
+ Contents []string
+
+ // Flag files by *hiddenAPIFlagFileCategory
+ Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths
}
func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
module := variant.(*BootImageModule)
b.Image_name = module.properties.Image_name
+ if b.Image_name == nil {
+ // Only one of image_name or contents can be specified. However, if image_name is set then the
+ // contents property is updated to match the configuration used to create the corresponding
+ // boot image. Therefore, contents property is only copied if the image name is not specified.
+ b.Contents = module.properties.Contents
+ }
+
+ // Get the flag file information from the module.
+ mctx := ctx.SdkModuleContext()
+ flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
+ b.Flag_files_by_category = flagFileInfo.categoryToPaths
}
func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
if b.Image_name != nil {
propertySet.AddProperty("image_name", *b.Image_name)
}
+
+ if len(b.Contents) > 0 {
+ propertySet.AddPropertyWithTag("contents", b.Contents, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
+ }
+
+ builder := ctx.SnapshotBuilder()
+ if b.Flag_files_by_category != nil {
+ hiddenAPISet := propertySet.AddPropertySet("hidden_api")
+ for _, category := range hiddenAPIFlagFileCategories {
+ paths := b.Flag_files_by_category[category]
+ if len(paths) > 0 {
+ dests := []string{}
+ for _, p := range paths {
+ dest := filepath.Join("hiddenapi", p.Base())
+ builder.CopyToSnapshot(p, dest)
+ dests = append(dests, dest)
+ }
+ hiddenAPISet.AddProperty(category.propertyName, dests)
+ }
+ }
+ }
}
var _ android.SdkMemberType = (*bootImageMemberType)(nil)
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 3571590db..d00d74b8c 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -41,9 +41,12 @@ type dexpreopter struct {
builtInstalled string
- // A path to a dexpreopt.config file generated by Soong for libraries that may be used as a
- // <uses-library> by Make modules. The path is passed to Make via LOCAL_SOONG_DEXPREOPT_CONFIG
- // variable. If the path is nil, no config is generated (which is the case for apps and tests).
+ // The config is used for two purposes:
+ // - Passing dexpreopt information about libraries from Soong to Make. This is needed when
+ // a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py).
+ // Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself.
+ // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
+ // dexpreopt another partition).
configPath android.WritablePath
}
@@ -138,27 +141,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
}
}
- if !d.isApp && !d.isTest {
- // Slim dexpreopt config is serialized to dexpreopt.config files and used by
- // dex_preopt_config_merger.py to get information about <uses-library> dependencies.
- // Note that it might be needed even if dexpreopt is disabled for this module.
- slimDexpreoptConfig := &dexpreopt.ModuleConfig{
- Name: ctx.ModuleName(),
- DexLocation: dexLocation,
- EnforceUsesLibraries: d.enforceUsesLibs,
- ProvidesUsesLibrary: providesUsesLib,
- ClassLoaderContexts: d.classLoaderContexts,
- // The rest of the fields are not needed.
- }
- d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
- dexpreopt.WriteSlimModuleConfigForMake(ctx, slimDexpreoptConfig, d.configPath)
- }
-
- if d.dexpreoptDisabled(ctx) {
+ // If it is neither app nor test, make config files regardless of its dexpreopt setting.
+ // The config files are required for apps defined in make which depend on the lib.
+ // TODO(b/158843648): The config for apps should be generated as well regardless of setting.
+ if (d.isApp || d.isTest) && d.dexpreoptDisabled(ctx) {
return
}
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
isSystemServerJar := inList(ctx.ModuleName(), global.SystemServerJars)
@@ -251,6 +240,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
PresignedPrebuilt: d.isPresignedPrebuilt,
}
+ d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
+ dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
+
+ if d.dexpreoptDisabled(ctx) {
+ return
+ }
+
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
+
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 3ecb9772a..e57508546 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -156,16 +156,24 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationNa
// A source module that has been replaced by a prebuilt can never be the primary module.
if module.IsReplacedByPrebuilt() {
- ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
- if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
- primary = false
- } else {
- ctx.ModuleErrorf(
- "hiddenapi has determined that the source module %q should be ignored as it has been"+
- " replaced by the prebuilt module %q but unfortunately it does not provide a"+
- " suitable boot dex jar", ctx.ModuleName(), ctx.OtherModuleName(prebuilt))
- }
- })
+ if ctx.HasProvider(android.ApexInfoProvider) {
+ // The source module is in an APEX but the prebuilt module on which it depends is not in an
+ // APEX and so is not the one that will actually be used for hidden API processing. That
+ // means it is not possible to check to see if it is a suitable replacement so just assume
+ // that it is.
+ primary = false
+ } else {
+ ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
+ if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
+ primary = false
+ } else {
+ ctx.ModuleErrorf(
+ "hiddenapi has determined that the source module %q should be ignored as it has been"+
+ " replaced by the prebuilt module %q but unfortunately it does not provide a"+
+ " suitable boot dex jar", ctx.ModuleName(), ctx.OtherModuleName(prebuilt))
+ }
+ })
+ }
}
}
h.primary = primary
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 7cf082b6a..8cc6f8f23 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -16,10 +16,163 @@ package java
import (
"android/soong/android"
+ "github.com/google/blueprint"
)
// Contains support for processing hiddenAPI in a modular fashion.
+type hiddenAPIStubsDependencyTag struct {
+ blueprint.BaseDependencyTag
+ sdkKind android.SdkKind
+}
+
+func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
+}
+
+func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
+ return false
+}
+
+// Avoid having to make stubs content explicitly visible to dependent modules.
+//
+// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
+// with proper dependencies.
+// TODO(b/177892522): Remove this and add needed visibility.
+func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
+var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
+var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
+
+// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
+// API processing.
+var hiddenAPIRelevantSdkKinds = []android.SdkKind{
+ android.SdkPublic,
+ android.SdkSystem,
+ android.SdkTest,
+ android.SdkCorePlatform,
+}
+
+// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
+// needed to produce the hidden API monolithic stub flags file.
+func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
+ var publicStubModules []string
+ var systemStubModules []string
+ var testStubModules []string
+ var corePlatformStubModules []string
+
+ if config.AlwaysUsePrebuiltSdks() {
+ // Build configuration mandates using prebuilt stub modules
+ publicStubModules = append(publicStubModules, "sdk_public_current_android")
+ systemStubModules = append(systemStubModules, "sdk_system_current_android")
+ testStubModules = append(testStubModules, "sdk_test_current_android")
+ } else {
+ // Use stub modules built from source
+ publicStubModules = append(publicStubModules, "android_stubs_current")
+ systemStubModules = append(systemStubModules, "android_system_stubs_current")
+ testStubModules = append(testStubModules, "android_test_stubs_current")
+ }
+ // We do not have prebuilts of the core platform api yet
+ corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+
+ // Allow products to define their own stubs for custom product jars that apps can use.
+ publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
+ systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
+ testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
+ if config.IsEnvTrue("EMMA_INSTRUMENT") {
+ publicStubModules = append(publicStubModules, "jacoco-stubs")
+ }
+
+ m := map[android.SdkKind][]string{}
+ m[android.SdkPublic] = publicStubModules
+ m[android.SdkSystem] = systemStubModules
+ m[android.SdkTest] = testStubModules
+ m[android.SdkCorePlatform] = corePlatformStubModules
+ return m
+}
+
+// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
+// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
+// identify the source of the dependency.
+func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
+ module := ctx.Module()
+ for _, sdkKind := range hiddenAPIRelevantSdkKinds {
+ modules := sdkKindToStubLibModules[sdkKind]
+ ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
+ }
+}
+
+// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
+// in hiddenAPIAddStubLibDependencies.
+func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths {
+ m := map[android.SdkKind]android.Paths{}
+ ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
+ kind := hiddenAPIStubsTag.sdkKind
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module)
+ if dexJar != nil {
+ m[kind] = append(m[kind], dexJar)
+ }
+ }
+ })
+ return m
+}
+
+// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
+// available, or reports an error.
+func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module) android.Path {
+ if j, ok := module.(UsesLibraryDependency); ok {
+ dexJar := j.DexJarBuildPath()
+ if dexJar != nil {
+ return dexJar
+ }
+ ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
+ } else {
+ ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
+ }
+ return nil
+}
+
+var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
+ android.SdkPublic: "public-stub-classpath",
+ android.SdkSystem: "system-stub-classpath",
+ android.SdkTest: "test-stub-classpath",
+ android.SdkCorePlatform: "core-platform-stub-classpath",
+}
+
+// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
+//
+// The rule is initialized but not built so that the caller can modify it and select an appropriate
+// name.
+func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
+ // Singleton rule which applies hiddenapi on all boot class path dex files.
+ rule := android.NewRuleBuilder(pctx, ctx)
+
+ tempPath := tempPathForRestat(ctx, outputPath)
+
+ command := rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
+ Text("list").
+ FlagForEachInput("--boot-dex=", bootDexJars)
+
+ // Iterate over the sdk kinds in a fixed order.
+ for _, sdkKind := range hiddenAPIRelevantSdkKinds {
+ paths := sdkKindToPathList[sdkKind]
+ if len(paths) > 0 {
+ option := sdkKindToHiddenapiListOption[sdkKind]
+ command.FlagWithInputList("--"+option+"=", paths, ":")
+ }
+ }
+
+ // Add the output path.
+ command.FlagWithOutput("--out-api-flags=", tempPath)
+
+ commitChangeForRestat(rule, tempPath, outputPath)
+ return rule
+}
+
// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
// information obtained from annotations within the source code in order to create the complete set
// of flags that should be applied to the dex implementation jars on the bootclasspath.
@@ -63,7 +216,7 @@ type HiddenAPIFlagFileProperties struct {
func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}}
for _, category := range hiddenAPIFlagFileCategories {
- paths := android.PathsForModuleSrc(ctx, category.propertyAccessor(p))
+ paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
info.categoryToPaths[category] = paths
}
return info
@@ -73,9 +226,9 @@ type hiddenAPIFlagFileCategory struct {
// propertyName is the name of the property for this category.
propertyName string
- // propertyAccessor retrieves the value of the property for this category from the set of
+ // propertyValueReader retrieves the value of the property for this category from the set of
// properties.
- propertyAccessor func(properties *HiddenAPIFlagFileProperties) []string
+ propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
// commandMutator adds the appropriate command line options for this category to the supplied
// command
@@ -86,7 +239,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Unsupported
{
propertyName: "unsupported",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -96,7 +249,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Removed
{
propertyName: "removed",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Removed
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -106,7 +259,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
{
propertyName: "max_target_r_low_priority",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_r_low_priority
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -116,7 +269,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Max_target_q
{
propertyName: "max_target_q",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_q
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -126,7 +279,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Max_target_p
{
propertyName: "max_target_p",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_p
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -136,7 +289,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
{
propertyName: "max_target_o_low_priority",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_o_low_priority
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -146,7 +299,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Blocked
{
propertyName: "blocked",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Blocked
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -156,7 +309,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// See HiddenAPIFlagFileProperties.Unsupported_packages
{
propertyName: "unsupported_packages",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported_packages
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -172,6 +325,14 @@ type hiddenAPIFlagFileInfo struct {
categoryToPaths map[*hiddenAPIFlagFileCategory]android.Paths
}
+func (i *hiddenAPIFlagFileInfo) append(other hiddenAPIFlagFileInfo) {
+ for _, category := range hiddenAPIFlagFileCategories {
+ i.categoryToPaths[category] = append(i.categoryToPaths[category], other.categoryToPaths[category]...)
+ }
+}
+
+var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})
+
// ruleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from the
// flags from all the modules, the stub flags, augmented with some additional configuration files.
//
@@ -197,7 +358,7 @@ type hiddenAPIFlagFileInfo struct {
// augmentationInfo is a struct containing paths to files that augment the information provided by
// the moduleSpecificFlagsPaths.
func ruleToGenerateHiddenApiFlags(ctx android.BuilderContext, outputPath android.WritablePath, baseFlagsPath android.Path, moduleSpecificFlagsPaths android.Paths, augmentationInfo hiddenAPIFlagFileInfo) {
- tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
+ tempPath := tempPathForRestat(ctx, outputPath)
rule := android.NewRuleBuilder(pctx, ctx)
command := rule.Command().
BuiltTool("generate_hiddenapi_lists").
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ed0b72250..3cc88e606 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -15,6 +15,8 @@
package java
import (
+ "strings"
+
"android/soong/android"
)
@@ -125,8 +127,6 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext)
return
}
- stubFlagsRule(ctx)
-
// If there is a prebuilt hiddenapi dir, generate rules to use the
// files within. Generally, we build the hiddenapi files from source
// during the build, ensuring consistency. It's possible, in a split
@@ -158,109 +158,6 @@ func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", h.flags.String())
}
-// stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image
-// modules.
-func stubFlagsRule(ctx android.SingletonContext) {
- var publicStubModules []string
- var systemStubModules []string
- var testStubModules []string
- var corePlatformStubModules []string
-
- if ctx.Config().AlwaysUsePrebuiltSdks() {
- // Build configuration mandates using prebuilt stub modules
- publicStubModules = append(publicStubModules, "sdk_public_current_android")
- systemStubModules = append(systemStubModules, "sdk_system_current_android")
- testStubModules = append(testStubModules, "sdk_test_current_android")
- } else {
- // Use stub modules built from source
- publicStubModules = append(publicStubModules, "android_stubs_current")
- systemStubModules = append(systemStubModules, "android_system_stubs_current")
- testStubModules = append(testStubModules, "android_test_stubs_current")
- }
- // We do not have prebuilts of the core platform api yet
- corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
-
- // Allow products to define their own stubs for custom product jars that apps can use.
- publicStubModules = append(publicStubModules, ctx.Config().ProductHiddenAPIStubs()...)
- systemStubModules = append(systemStubModules, ctx.Config().ProductHiddenAPIStubsSystem()...)
- testStubModules = append(testStubModules, ctx.Config().ProductHiddenAPIStubsTest()...)
- if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") {
- publicStubModules = append(publicStubModules, "jacoco-stubs")
- }
-
- publicStubPaths := make(android.Paths, len(publicStubModules))
- systemStubPaths := make(android.Paths, len(systemStubModules))
- testStubPaths := make(android.Paths, len(testStubModules))
- corePlatformStubPaths := make(android.Paths, len(corePlatformStubModules))
-
- moduleListToPathList := map[*[]string]android.Paths{
- &publicStubModules: publicStubPaths,
- &systemStubModules: systemStubPaths,
- &testStubModules: testStubPaths,
- &corePlatformStubModules: corePlatformStubPaths,
- }
-
- var bootDexJars android.Paths
-
- ctx.VisitAllModules(func(module android.Module) {
- // Collect dex jar paths for the modules listed above.
- if j, ok := module.(UsesLibraryDependency); ok {
- name := ctx.ModuleName(module)
- for moduleList, pathList := range moduleListToPathList {
- if i := android.IndexList(name, *moduleList); i != -1 {
- pathList[i] = j.DexJarBuildPath()
- }
- }
- }
-
- // Collect dex jar paths for modules that had hiddenapi encode called on them.
- if h, ok := module.(hiddenAPIIntf); ok {
- if jar := h.bootDexJar(); jar != nil {
- bootDexJars = append(bootDexJars, jar)
- }
- }
- })
-
- var missingDeps []string
- // Ensure all modules were converted to paths
- for moduleList, pathList := range moduleListToPathList {
- for i := range pathList {
- if pathList[i] == nil {
- moduleName := (*moduleList)[i]
- pathList[i] = android.PathForOutput(ctx, "missing/module", moduleName)
- if ctx.Config().AllowMissingDependencies() {
- missingDeps = append(missingDeps, moduleName)
- } else {
- ctx.Errorf("failed to find dex jar path for module %q",
- moduleName)
- }
- }
- }
- }
-
- // Singleton rule which applies hiddenapi on all boot class path dex files.
- rule := android.NewRuleBuilder(pctx, ctx)
-
- outputPath := hiddenAPISingletonPaths(ctx).stubFlags
- tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
-
- rule.MissingDeps(missingDeps)
-
- rule.Command().
- Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
- Text("list").
- FlagForEachInput("--boot-dex=", bootDexJars).
- FlagWithInputList("--public-stub-classpath=", publicStubPaths, ":").
- FlagWithInputList("--system-stub-classpath=", systemStubPaths, ":").
- FlagWithInputList("--test-stub-classpath=", testStubPaths, ":").
- FlagWithInputList("--core-platform-stub-classpath=", corePlatformStubPaths, ":").
- FlagWithOutput("--out-api-flags=", tempPath)
-
- commitChangeForRestat(rule, tempPath, outputPath)
-
- rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags")
-}
-
// Checks to see whether the supplied module variant is in the list of boot jars.
//
// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed
@@ -348,6 +245,16 @@ func emptyFlagsRule(ctx android.SingletonContext) android.Path {
return outputPath
}
+// tempPathForRestat creates a path of the same type as the supplied type but with a name of
+// <path>.tmp.
+//
+// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
+// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.tmp
+func tempPathForRestat(ctx android.PathContext, path android.WritablePath) android.WritablePath {
+ extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
+ return path.ReplaceExtension(ctx, extWithoutLeadingDot+".tmp")
+}
+
// commitChangeForRestat adds a command to a rule that updates outputPath from tempPath if they are different. It
// also marks the rule as restat and marks the tempPath as a temporary file that should not be considered an output of
// the rule.
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 5ea9a5bca..3ab22772a 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -23,12 +23,20 @@ import (
"github.com/google/blueprint/proptools"
)
+// TODO(b/177892522): Move these tests into a more appropriate place.
+
func fixtureSetPrebuiltHiddenApiDirProductVariable(prebuiltHiddenApiDir *string) android.FixturePreparer {
return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
})
}
+var prepareForTestWithDefaultPlatformBootclasspath = android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ }
+`)
+
var hiddenApiFixtureFactory = android.GroupFixturePreparers(
prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents)
@@ -36,6 +44,7 @@ func TestHiddenAPISingleton(t *testing.T) {
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
+ prepareForTestWithDefaultPlatformBootclasspath,
).RunTestWithBp(t, `
java_library {
name: "foo",
@@ -44,8 +53,8 @@ func TestHiddenAPISingleton(t *testing.T) {
}
`)
- hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
@@ -59,6 +68,7 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T)
android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
+ prepareForTestWithDefaultPlatformBootclasspath,
).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)).
RunTestWithBp(t, `
java_library {
@@ -79,6 +89,7 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
+ prepareForTestWithDefaultPlatformBootclasspath,
).RunTestWithBp(t, `
java_import {
name: "foo",
@@ -87,8 +98,8 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
}
`)
- hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
@@ -97,6 +108,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
+ prepareForTestWithDefaultPlatformBootclasspath,
).RunTestWithBp(t, `
java_library {
name: "foo",
@@ -112,8 +124,8 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
}
`)
- hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
@@ -125,6 +137,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
+ prepareForTestWithDefaultPlatformBootclasspath,
).RunTestWithBp(t, `
java_library {
name: "foo",
@@ -140,8 +153,8 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
}
`)
- hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
@@ -184,13 +197,14 @@ func TestHiddenAPISingletonSdks(t *testing.T) {
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
tc.preparer,
+ prepareForTestWithDefaultPlatformBootclasspath,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
}),
).RunTest(t)
- hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)
diff --git a/java/java.go b/java/java.go
index ee4f2eb0b..adb0c5644 100644
--- a/java/java.go
+++ b/java/java.go
@@ -27,6 +27,7 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/dexpreopt"
"android/soong/java/config"
"android/soong/tradefed"
@@ -708,6 +709,9 @@ type testProperties struct {
// Test options.
Test_options TestOptions
+
+ // Names of modules containing JNI libraries that should be installed alongside the test.
+ Jni_libs []string
}
type hostTestProperties struct {
@@ -769,6 +773,13 @@ func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
+ if len(j.testProperties.Jni_libs) > 0 {
+ for _, target := range ctx.MultiTargets() {
+ sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
+ ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
+ }
+ }
+
j.deps(ctx)
}
@@ -793,6 +804,29 @@ func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
})
+ ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
+ sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ if sharedLibInfo.SharedLibrary != nil {
+ // Copy to an intermediate output directory to append "lib[64]" to the path,
+ // so that it's compatible with the default rpath values.
+ var relPath string
+ if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
+ } else {
+ relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
+ }
+ relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: sharedLibInfo.SharedLibrary,
+ Output: relocatedLib,
+ })
+ j.data = append(j.data, relocatedLib)
+ } else {
+ ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ }
+ })
+
j.Library.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index 052345871..1b8aec286 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -20,6 +20,7 @@ import (
"path/filepath"
"reflect"
"regexp"
+ "runtime"
"strconv"
"strings"
"testing"
@@ -462,6 +463,38 @@ func TestBinary(t *testing.T) {
}
}
+func TestTest(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_test_host {
+ name: "foo",
+ srcs: ["a.java"],
+ jni_libs: ["libjni"],
+ }
+
+ cc_library_shared {
+ name: "libjni",
+ host_supported: true,
+ device_supported: false,
+ stl: "none",
+ }
+ `)
+
+ buildOS := android.BuildOs.String()
+
+ foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+
+ expected := "lib64/libjni.so"
+ if runtime.GOOS == "darwin" {
+ expected = "lib64/libjni.dylib"
+ }
+
+ fooTestData := foo.data
+ if len(fooTestData) != 1 || fooTestData[0].Rel() != expected {
+ t.Errorf(`expected foo test data relative path [%q], got %q`,
+ expected, fooTestData.Strings())
+ }
+}
+
func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
bp := `
java_library {
@@ -1170,107 +1203,6 @@ func TestIncludeSrcs(t *testing.T) {
}
}
-func TestJavaLint(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- java_library {
- name: "foo",
- srcs: [
- "a.java",
- "b.java",
- "c.java",
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- }
- `, map[string][]byte{
- "lint-baseline.xml": nil,
- })
-
- foo := ctx.ModuleForTests("foo", "android_common")
-
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
- t.Error("did not pass --baseline flag")
- }
-}
-
-func TestJavaLintWithoutBaseline(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- java_library {
- name: "foo",
- srcs: [
- "a.java",
- "b.java",
- "c.java",
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- }
- `, map[string][]byte{})
-
- foo := ctx.ModuleForTests("foo", "android_common")
-
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if strings.Contains(*sboxProto.Commands[0].Command, "--baseline") {
- t.Error("passed --baseline flag for non existent file")
- }
-}
-
-func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) {
- android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.PrepareForTestDisallowNonExistentPaths,
- ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{`source path "mybaseline.xml" does not exist`})).
- RunTestWithBp(t, `
- java_library {
- name: "foo",
- srcs: [
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- lint: {
- baseline_filename: "mybaseline.xml",
- },
- }
- `)
-}
-
-func TestJavaLintUsesCorrectBpConfig(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- java_library {
- name: "foo",
- srcs: [
- "a.java",
- "b.java",
- "c.java",
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- lint: {
- error_checks: ["SomeCheck"],
- baseline_filename: "mybaseline.xml",
- },
- }
- `, map[string][]byte{
- "mybaseline.xml": nil,
- })
-
- foo := ctx.ModuleForTests("foo", "android_common")
-
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
- t.Error("did not use the correct file for baseline")
- }
-
- if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check NewApi") {
- t.Error("should check NewApi errors")
- }
-
- if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check SomeCheck") {
- t.Error("should combine NewApi errors with SomeCheck errors")
- }
-}
-
func TestGeneratedSources(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
java_library {
@@ -1614,31 +1546,51 @@ func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
java_sdk_library {
name: "sdklib",
srcs: ["a.java"],
- impl_only_libs: ["foo"],
- stub_only_libs: ["bar"],
+ libs: ["lib"],
+ static_libs: ["static-lib"],
+ impl_only_libs: ["impl-only-lib"],
+ stub_only_libs: ["stub-only-lib"],
+ stub_only_static_libs: ["stub-only-static-lib"],
}
- java_library {
- name: "foo",
- srcs: ["a.java"],
- sdk_version: "current",
- }
- java_library {
- name: "bar",
+ java_defaults {
+ name: "defaults",
srcs: ["a.java"],
sdk_version: "current",
}
+ java_library { name: "lib", defaults: ["defaults"] }
+ java_library { name: "static-lib", defaults: ["defaults"] }
+ java_library { name: "impl-only-lib", defaults: ["defaults"] }
+ java_library { name: "stub-only-lib", defaults: ["defaults"] }
+ java_library { name: "stub-only-static-lib", defaults: ["defaults"] }
`)
-
- for _, implName := range []string{"sdklib", "sdklib.impl"} {
- implJavacCp := result.ModuleForTests(implName, "android_common").Rule("javac").Args["classpath"]
- if !strings.Contains(implJavacCp, "/foo.jar") || strings.Contains(implJavacCp, "/bar.jar") {
- t.Errorf("%v javac classpath %v does not contain foo and not bar", implName, implJavacCp)
- }
+ var expectations = []struct {
+ lib string
+ on_impl_classpath bool
+ on_stub_classpath bool
+ in_impl_combined bool
+ in_stub_combined bool
+ }{
+ {lib: "lib", on_impl_classpath: true},
+ {lib: "static-lib", in_impl_combined: true},
+ {lib: "impl-only-lib", on_impl_classpath: true},
+ {lib: "stub-only-lib", on_stub_classpath: true},
+ {lib: "stub-only-static-lib", in_stub_combined: true},
+ }
+ verify := func(sdklib, dep string, cp, combined bool) {
+ sdklibCp := result.ModuleForTests(sdklib, "android_common").Rule("javac").Args["classpath"]
+ expected := cp || combined // Every combined jar is also on the classpath.
+ android.AssertStringContainsEquals(t, "bad classpath for "+sdklib, sdklibCp, "/"+dep+".jar", expected)
+
+ combineJarInputs := result.ModuleForTests(sdklib, "android_common").Rule("combineJar").Inputs.Strings()
+ depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine-combined", dep+".jar")
+ android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
}
- stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
- stubsJavacCp := result.ModuleForTests(stubName, "android_common").Rule("javac").Args["classpath"]
- if strings.Contains(stubsJavacCp, "/foo.jar") || !strings.Contains(stubsJavacCp, "/bar.jar") {
- t.Errorf("stubs javac classpath %v does not contain bar and not foo", stubsJavacCp)
+ for _, expectation := range expectations {
+ verify("sdklib", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
+ verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
+
+ stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
+ verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
}
}
diff --git a/java/lint.go b/java/lint.go
index aa308e669..862c9b4d9 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -26,6 +26,10 @@ import (
"android/soong/remoteexec"
)
+// lint checks automatically enforced for modules that have different min_sdk_version than
+// sdk_version
+var updatabilityChecks = []string{"NewApi"}
+
type LintProperties struct {
// Controls for running Android Lint on the module.
Lint struct {
@@ -53,6 +57,9 @@ type LintProperties struct {
// Name of the file that lint uses as the baseline. Defaults to "lint-baseline.xml".
Baseline_filename *string
+
+ // If true, baselining updatability lint checks (e.g. NewApi) is prohibited. Defaults to false.
+ Strict_updatability_linting *bool
}
}
@@ -200,7 +207,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
cmd := rule.Command().
- BuiltTool("lint-project-xml").
+ BuiltTool("lint_project_xml").
FlagWithOutput("--project_out ", projectXMLPath).
FlagWithOutput("--config_out ", configXMLPath).
FlagWithArg("--name ", ctx.ModuleName())
@@ -253,6 +260,13 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
+ if BoolDefault(l.properties.Lint.Strict_updatability_linting, false) {
+ if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() {
+ cmd.FlagWithInput("--baseline ", baselinePath.Path())
+ cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
+ }
+ }
+
return lintPaths{
projectXML: projectXMLPath,
configXML: configXMLPath,
@@ -279,13 +293,36 @@ func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleB
return manifestPath
}
+func (l *linter) getBaselineFilepath(ctx android.ModuleContext) android.OptionalPath {
+ var lintBaseline android.OptionalPath
+ if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" {
+ if String(l.properties.Lint.Baseline_filename) != "" {
+ // if manually specified, we require the file to exist
+ lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename))
+ } else {
+ lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename)
+ }
+ }
+ return lintBaseline
+}
+
func (l *linter) lint(ctx android.ModuleContext) {
if !l.enabled() {
return
}
if l.minSdkVersion != l.compileSdkVersion {
- l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, "NewApi")
+ l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
+ _, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks)
+ if len(filtered) != 0 {
+ ctx.PropertyErrorf("lint.warning_checks",
+ "Can't treat %v checks as warnings if min_sdk_version is different from sdk_version.", filtered)
+ }
+ _, filtered = android.FilterList(l.properties.Lint.Disabled_checks, updatabilityChecks)
+ if len(filtered) != 0 {
+ ctx.PropertyErrorf("lint.disabled_checks",
+ "Can't disable %v checks if min_sdk_version is different from sdk_version.", filtered)
+ }
}
extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
@@ -381,17 +418,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
cmd.FlagWithArg("--check ", checkOnly)
}
- if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" {
- var lintBaseline android.OptionalPath
- if String(l.properties.Lint.Baseline_filename) != "" {
- // if manually specified, we require the file to exist
- lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename))
- } else {
- lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename)
- }
- if lintBaseline.Valid() {
- cmd.FlagWithInput("--baseline ", lintBaseline.Path())
- }
+ lintBaseline := l.getBaselineFilepath(ctx)
+ if lintBaseline.Valid() {
+ cmd.FlagWithInput("--baseline ", lintBaseline.Path())
}
cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
diff --git a/java/lint_test.go b/java/lint_test.go
new file mode 100644
index 000000000..a253df979
--- /dev/null
+++ b/java/lint_test.go
@@ -0,0 +1,204 @@
+// Copyright 2021 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 (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestJavaLint(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ "b.java",
+ "c.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "system_current",
+ }
+ `, map[string][]byte{
+ "lint-baseline.xml": nil,
+ })
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
+ t.Error("did not pass --baseline flag")
+ }
+}
+
+func TestJavaLintWithoutBaseline(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ "b.java",
+ "c.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "system_current",
+ }
+ `, map[string][]byte{})
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command, "--baseline") {
+ t.Error("passed --baseline flag for non existent file")
+ }
+}
+
+func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) {
+ android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestDisallowNonExistentPaths,
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{`source path "mybaseline.xml" does not exist`})).
+ RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: [
+ ],
+ min_sdk_version: "29",
+ sdk_version: "system_current",
+ lint: {
+ baseline_filename: "mybaseline.xml",
+ },
+ }
+ `)
+}
+
+func TestJavaLintUsesCorrectBpConfig(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ "b.java",
+ "c.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "system_current",
+ lint: {
+ error_checks: ["SomeCheck"],
+ baseline_filename: "mybaseline.xml",
+ },
+ }
+ `, map[string][]byte{
+ "mybaseline.xml": nil,
+ })
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
+ t.Error("did not use the correct file for baseline")
+ }
+
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check NewApi") {
+ t.Error("should check NewApi errors")
+ }
+
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check SomeCheck") {
+ t.Error("should combine NewApi errors with SomeCheck errors")
+ }
+}
+
+func TestJavaLintBypassUpdatableChecks(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ error string
+ }{
+ {
+ name: "warning_checks",
+ bp: `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ warning_checks: ["NewApi"],
+ },
+ }
+ `,
+ error: "lint.warning_checks: Can't treat \\[NewApi\\] checks as warnings if min_sdk_version is different from sdk_version.",
+ },
+ {
+ name: "disable_checks",
+ bp: `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ disabled_checks: ["NewApi"],
+ },
+ }
+ `,
+ error: "lint.disabled_checks: Can't disable \\[NewApi\\] checks if min_sdk_version is different from sdk_version.",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.error)
+ android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, testCase.bp)
+ })
+ }
+}
+
+func TestJavaLintStrictUpdatabilityLinting(t *testing.T) {
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ strict_updatability_linting: true,
+ },
+ }
+ `
+ fs := android.MockFS{
+ "lint-baseline.xml": nil,
+ }
+
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()).
+ RunTestWithBp(t, bp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ t.Error("did not restrict baselining NewApi")
+ }
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index cb8ad683b..568f5e406 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -140,6 +140,8 @@ func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, er
}
func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ b.hiddenAPIDepsMutator(ctx)
+
if SkipDexpreoptBootJars(ctx) {
return
}
@@ -149,6 +151,16 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon
dexpreopt.RegisterToolDeps(ctx)
}
+func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+
+ // Add dependencies onto the stub lib modules.
+ sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+ hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules)
+}
+
func platformBootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
m := ctx.Module()
if p, ok := m.(*platformBootclasspathModule); ok {
@@ -258,7 +270,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo
}
})
- b.generateHiddenAPIBuildActions(ctx, b.configuredModules)
+ b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
// Nothing to do if skipping the dexpreopt of boot image jars.
if SkipDexpreoptBootJars(ctx) {
@@ -286,7 +298,7 @@ func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleCont
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module) {
+func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
// Save the paths to the monolithic files for retrieval via OutputFiles().
b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags
@@ -338,16 +350,39 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
moduleSpecificFlagsPaths = append(moduleSpecificFlagsPaths, module.flagsCSV())
}
- augmentationInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
+ flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
+ for _, fragment := range fragments {
+ if ctx.OtherModuleHasProvider(fragment, hiddenAPIFlagFileInfoProvider) {
+ info := ctx.OtherModuleProvider(fragment, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
+ flagFileInfo.append(info)
+ }
+ }
+
+ // Store the information for testing.
+ ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
outputPath := hiddenAPISingletonPaths(ctx).flags
baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags
- ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, augmentationInfo)
+ ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, flagFileInfo)
+ b.generateHiddenAPIStubFlagsRules(ctx, hiddenAPISupportingModules)
b.generateHiddenAPIIndexRules(ctx, hiddenAPISupportingModules)
b.generatedHiddenAPIMetadataRules(ctx, hiddenAPISupportingModules)
}
+func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
+ bootDexJars := android.Paths{}
+ for _, module := range modules {
+ bootDexJars = append(bootDexJars, module.bootDexJar())
+ }
+
+ sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx)
+
+ outputPath := hiddenAPISingletonPaths(ctx).stubFlags
+ rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToStubPaths)
+ rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
+}
+
func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
indexes := android.Paths{}
for _, module := range modules {
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index e51b0493a..955e387a9 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -15,6 +15,8 @@
package java
import (
+ "fmt"
+ "strings"
"testing"
"android/soong/android"
@@ -132,6 +134,96 @@ func TestPlatformBootclasspath(t *testing.T) {
})
}
+func TestPlatformBootclasspath_Fragments(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ android.FixtureWithRootAndroidBp(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {module:"bar-fragment"},
+ ],
+ hidden_api: {
+ unsupported: [
+ "unsupported.txt",
+ ],
+ removed: [
+ "removed.txt",
+ ],
+ max_target_r_low_priority: [
+ "max-target-r-low-priority.txt",
+ ],
+ max_target_q: [
+ "max-target-q.txt",
+ ],
+ max_target_p: [
+ "max-target-p.txt",
+ ],
+ max_target_o_low_priority: [
+ "max-target-o-low-priority.txt",
+ ],
+ blocked: [
+ "blocked.txt",
+ ],
+ unsupported_packages: [
+ "unsupported-packages.txt",
+ ],
+ },
+ }
+
+ bootclasspath_fragment {
+ name: "bar-fragment",
+ contents: ["bar"],
+ hidden_api: {
+ unsupported: [
+ "bar-unsupported.txt",
+ ],
+ removed: [
+ "bar-removed.txt",
+ ],
+ max_target_r_low_priority: [
+ "bar-max-target-r-low-priority.txt",
+ ],
+ max_target_q: [
+ "bar-max-target-q.txt",
+ ],
+ max_target_p: [
+ "bar-max-target-p.txt",
+ ],
+ max_target_o_low_priority: [
+ "bar-max-target-o-low-priority.txt",
+ ],
+ blocked: [
+ "bar-blocked.txt",
+ ],
+ unsupported_packages: [
+ "bar-unsupported-packages.txt",
+ ],
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ }
+ `),
+ ).RunTest(t)
+
+ pbcp := result.Module("platform-bootclasspath", "android_common")
+ info := result.ModuleProvider(pbcp, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
+
+ for _, category := range hiddenAPIFlagFileCategories {
+ name := category.propertyName
+ message := fmt.Sprintf("category %s", name)
+ filename := strings.ReplaceAll(name, "_", "-")
+ expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
+ android.AssertPathsRelativeToTopEquals(t, message, expected, info.categoryToPaths[category])
+ }
+}
+
func TestPlatformBootclasspathVariant(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
diff --git a/java/sdk.go b/java/sdk.go
index d6e20a78f..1c097d5b7 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -247,7 +247,7 @@ func createSdkFrameworkAidl(ctx android.SingletonContext) {
}
combinedAidl := sdkFrameworkAidlPath(ctx)
- tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+ tempPath := tempPathForRestat(ctx, combinedAidl)
rule := createFrameworkAidl(stubsModules, tempPath, ctx)
@@ -261,7 +261,7 @@ func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
stubsModules := []string{"android_module_lib_stubs_current"}
combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
- tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+ tempPath := tempPathForRestat(ctx, combinedAidl)
rule := createFrameworkAidl(stubsModules, tempPath, ctx)
@@ -270,7 +270,7 @@ func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
rule.Build("framework_non_updatable_aidl", "generate framework_non_updatable.aidl")
}
-func createFrameworkAidl(stubsModules []string, path android.OutputPath, ctx android.SingletonContext) *android.RuleBuilder {
+func createFrameworkAidl(stubsModules []string, path android.WritablePath, ctx android.SingletonContext) *android.RuleBuilder {
stubsJars := make([]android.Paths, len(stubsModules))
ctx.VisitAllModules(func(module android.Module) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e5ee39705..05ce97aea 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -399,6 +399,9 @@ type sdkLibraryProperties struct {
// List of Java libraries that will be in the classpath when building stubs
Stub_only_libs []string `android:"arch_variant"`
+ // List of Java libraries that will included in stub libraries
+ Stub_only_static_libs []string `android:"arch_variant"`
+
// list of package names that will be documented and publicized as API.
// This allows the API to be restricted to a subset of the source files provided.
// If this is unspecified then all the source files will be treated as being part
@@ -534,6 +537,11 @@ type scopePaths struct {
// This is not the implementation jar, it still only contains stubs.
stubsImplPath android.Paths
+ // The dex jar for the stubs.
+ //
+ // This is not the implementation jar, it still only contains stubs.
+ stubsDexJarPath android.Path
+
// The API specification file, e.g. system_current.txt.
currentApiFilePath android.OptionalPath
@@ -549,6 +557,9 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.Modul
lib := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath()
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
@@ -825,8 +836,22 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.
return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
}
+ paths := c.selectScopePaths(ctx, sdkVersion.Kind)
+ if paths == nil {
+ return nil
+ }
+
+ return paths.stubsHeaderPath
+}
+
+// selectScopePaths returns the *scopePaths appropriate for the specific kind.
+//
+// If the module does not support the specific kind then it will return the *scopePaths for the
+// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then
+// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not.
+func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths {
var apiScope *apiScope
- switch sdkVersion.Kind {
+ switch kind {
case android.SdkSystem:
apiScope = apiScopeSystem
case android.SdkModule:
@@ -851,7 +876,17 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.
return nil
}
- return paths.stubsHeaderPath
+ return paths
+}
+
+// to satisfy SdkLibraryDependency interface
+func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path {
+ paths := c.selectScopePaths(ctx, kind)
+ if paths == nil {
+ return nil
+ }
+
+ return paths.stubsDexJarPath
}
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
@@ -944,6 +979,10 @@ type SdkLibraryDependency interface {
// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
// they are identical to the corresponding header jars.
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
+
+ // SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
+ // tool which processes dex files.
+ SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
}
type SdkLibrary struct {
@@ -1239,6 +1278,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
System_modules *string
Patch_module *string
Libs []string
+ Static_libs []string
Compile_dex *bool
Java_version *string
Openjdk9 struct {
@@ -1263,6 +1303,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
props.Patch_module = module.properties.Patch_module
props.Installable = proptools.BoolPtr(false)
props.Libs = module.sdkLibraryProperties.Stub_only_libs
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
// The stub-annotations library contains special versions of the annotations
// with CLASS retention policy, so that they're kept.
if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
@@ -1781,6 +1822,9 @@ type sdkLibraryImportProperties struct {
// List of shared java libs, common to all scopes, that this module has
// dependencies to
Libs []string
+
+ // If set to true, compile dex files for the stubs. Defaults to false.
+ Compile_dex *bool
}
type SdkLibraryImport struct {
@@ -1916,6 +1960,7 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl
Libs []string
Jars []string
Prefer *bool
+ Compile_dex *bool
}{}
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
props.Sdk_version = scopeProperties.Sdk_version
@@ -1927,6 +1972,9 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl
// The imports are preferred if the java_sdk_library_import is preferred.
props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+ // The imports need to be compiled to dex if the java_sdk_library_import requests it.
+ props.Compile_dex = module.properties.Compile_dex
+
mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -2348,6 +2396,9 @@ type sdkLibrarySdkMemberProperties struct {
// otherwise.
Shared_library *bool
+ // True if the stub imports should produce dex jars.
+ Compile_dex *bool
+
// The paths to the doctag files to add to the prebuilt.
Doctag_paths android.Paths
}
@@ -2389,6 +2440,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe
s.Libs = sdk.properties.Libs
s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
+ s.Compile_dex = sdk.dexProperties.Compile_dex
s.Doctag_paths = sdk.doctagPaths
}
@@ -2399,6 +2451,9 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo
if s.Shared_library != nil {
propertySet.AddProperty("shared_library", *s.Shared_library)
}
+ if s.Compile_dex != nil {
+ propertySet.AddProperty("compile_dex", *s.Compile_dex)
+ }
for _, apiScope := range allApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
diff --git a/java/testing.go b/java/testing.go
index aee0710c4..08a71b880 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -200,6 +200,9 @@ func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer {
}),
dexpreopt.FixtureSetBootJars(bootJars...),
dexpreopt.FixtureSetArtBootJars(artBootJars...),
+
+ // Add a fake dex2oatd module.
+ dexpreopt.PrepareForTestWithFakeDex2oatd,
)
}
@@ -212,6 +215,9 @@ func FixtureConfigureUpdatableBootJars(bootJars ...string) android.FixturePrepar
variables.UpdatableBootJars = android.CreateTestConfiguredJarList(bootJars)
}),
dexpreopt.FixtureSetUpdatableBootJars(bootJars...),
+
+ // Add a fake dex2oatd module.
+ dexpreopt.PrepareForTestWithFakeDex2oatd,
)
}