summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.bp2
-rw-r--r--java/boot_image.go82
-rw-r--r--java/hiddenapi.go28
-rw-r--r--java/hiddenapi_modular.go176
-rw-r--r--java/hiddenapi_singleton.go117
-rw-r--r--java/hiddenapi_singleton_test.go34
-rw-r--r--java/java_test.go161
-rw-r--r--java/lint.go55
-rw-r--r--java/lint_test.go204
-rw-r--r--java/platform_bootclasspath.go26
-rw-r--r--java/sdk.go6
-rw-r--r--java/sdk_library.go5
-rw-r--r--java/testing.go6
13 files changed, 620 insertions, 282 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/boot_image.go b/java/boot_image.go
index 78215f05a..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 {
@@ -187,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
}
@@ -202,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
@@ -295,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/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 e5dba33e8..8cc6f8f23 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -21,6 +21,158 @@ import (
// 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.
@@ -64,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
@@ -74,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
@@ -87,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) {
@@ -97,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) {
@@ -107,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) {
@@ -117,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) {
@@ -127,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) {
@@ -137,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) {
@@ -147,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) {
@@ -157,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) {
@@ -206,7 +358,7 @@ var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{
// 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_test.go b/java/java_test.go
index e7ea4ef54..1b8aec286 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1203,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 {
@@ -1647,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)
- }
- }
- 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)
+ 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)
+ }
+ 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 ba758ddfb..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 {
@@ -353,10 +365,24 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags
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/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 223be5cf7..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
@@ -1275,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 {
@@ -1299,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) {
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,
)
}