diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/aar.go | 3 | ||||
-rwxr-xr-x | java/app.go | 3 | ||||
-rw-r--r-- | java/base.go | 2 | ||||
-rwxr-xr-x | java/invalid_implementation_jar.sh | 61 | ||||
-rw-r--r-- | java/java.go | 319 | ||||
-rw-r--r-- | java/java_test.go | 105 | ||||
-rw-r--r-- | java/legacy_core_platform_api_usage.go | 146 | ||||
-rw-r--r-- | java/plugin.go | 3 |
8 files changed, 452 insertions, 190 deletions
diff --git a/java/aar.go b/java/aar.go index 6261f2974..0fdde0362 100644 --- a/java/aar.go +++ b/java/aar.go @@ -1046,7 +1046,8 @@ func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { - commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2buildInfo.DepLabels deps := depLabels.Deps if !commonAttrs.Srcs.IsEmpty() { diff --git a/java/app.go b/java/app.go index 2a51e10df..e36808fe0 100755 --- a/java/app.go +++ b/java/app.go @@ -1492,7 +1492,8 @@ type bazelAndroidAppAttributes struct { // ConvertWithBp2build is used to convert android_app to Bazel. func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { - commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := a.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps deps.Append(depLabels.StaticDeps) diff --git a/java/base.go b/java/base.go index 602e8d882..5d2498169 100644 --- a/java/base.go +++ b/java/base.go @@ -868,7 +868,7 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs)) sdkVersion := (j.SdkVersion(ctx)).Kind - defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform)) + defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform) || (sdkVersion == android.SdkModule)) if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) { flags = append(flags, "-t") } diff --git a/java/invalid_implementation_jar.sh b/java/invalid_implementation_jar.sh new file mode 100755 index 000000000..3820058d0 --- /dev/null +++ b/java/invalid_implementation_jar.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright 2022 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. + +# Script to detect and report an attempt to access an invalid implementation +# jar. + +MOD=$1 + +cat <<EOF + + $MOD is a java_library that generates a jar file which must not be accessed + from outside the mainline module that provides it. If you are seeing this + message it means that you are incorrectly attempting to use the jar file + from a java_import prebuilt of $MOD. + + This is most likely due to an incorrect dependency on $MOD in an Android.mk + or Android.bp file. Please remove that dependency and replace with + something more appropriate, e.g. a dependency on an API provided by the + module. + + If you do not know where the extraneous dependency was added then you can + run the following command to find a list of all the paths from the target + which you are trying to build to the target which produced this error. + + prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-\${TARGET_PRODUCT}.ninja -t path <target> <invalid-jar> + + Where <target> is the build target you specified on the command line which + produces this error and <invalid-jar> is the rule that failed with this + message. If you are specifying multiple build targets then you will need to + run the above command for every target until you find the cause. + + The command will output one (of the possibly many) dependency paths from + <target> to <invalid-jar>, one file/phony target per line. e.g. it may + output something like this: + + .... + out/soong/.intermediates/acme/broken/android_common/combined/broken.jar + out/soong/.intermediates/prebuilts/module_sdk/art/current/sdk/prebuilt_core-libart/android_common/combined/core-libart.jar + out/soong/.intermediates/prebuilts/module_sdk/art/current/sdk/art-module-sdk_core-libart-error/gen/this-file-will-never-be-created.jar + + The last line is the failing target, the second to last line is a dependency + from the core-libart java_import onto the failing target, the third to last + line is the source of the dependency so you should look in acme/Android.bp + file for the "broken" module. + +EOF + +exit 1 diff --git a/java/java.go b/java/java.go index b6fc6b831..ad46e9880 100644 --- a/java/java.go +++ b/java/java.go @@ -25,6 +25,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" + "android/soong/remoteexec" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -59,6 +60,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory) ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory) ctx.RegisterModuleType("dex_import", DexImportFactory) + ctx.RegisterModuleType("java_api_library", ApiLibraryFactory) + ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory) // This mutator registers dependencies on dex2oat for modules that should be // dexpreopted. This is done late when the final variants have been @@ -86,11 +89,11 @@ func RegisterJavaSdkMemberTypes() { var ( // Supports adding java header libraries to module_exports and sdk. javaHeaderLibsSdkMemberType = &librarySdkMemberType{ - android.SdkMemberTypeBase{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ PropertyName: "java_header_libs", SupportsSdk: true, }, - func(_ android.SdkMemberContext, j *Library) android.Path { + jarToExportGetter: func(_ android.SdkMemberContext, j *Library) android.Path { headerJars := j.HeaderJars() if len(headerJars) != 1 { panic(fmt.Errorf("there must be only one header jar from %q", j.Name())) @@ -98,8 +101,8 @@ var ( return headerJars[0] }, - sdkSnapshotFilePathForJar, - copyEverythingToSnapshot, + snapshotPathGetter: sdkSnapshotFilePathForJar, + onlyCopyJarToSnapshot: copyEverythingToSnapshot, } // Export implementation classes jar as part of the sdk. @@ -113,12 +116,12 @@ var ( // Supports adding java implementation libraries to module_exports but not sdk. javaLibsSdkMemberType = &librarySdkMemberType{ - android.SdkMemberTypeBase{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ PropertyName: "java_libs", }, - exportImplementationClassesJar, - sdkSnapshotFilePathForJar, - copyEverythingToSnapshot, + jarToExportGetter: exportImplementationClassesJar, + snapshotPathGetter: sdkSnapshotFilePathForJar, + onlyCopyJarToSnapshot: copyEverythingToSnapshot, } snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool { @@ -143,11 +146,11 @@ var ( // necessary. The java_boot_libs property to allow those modules to be exported as part of the // sdk/module_exports without exposing any unnecessary information. javaBootLibsSdkMemberType = &librarySdkMemberType{ - android.SdkMemberTypeBase{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ PropertyName: "java_boot_libs", SupportsSdk: true, }, - func(ctx android.SdkMemberContext, j *Library) android.Path { + jarToExportGetter: func(ctx android.SdkMemberContext, j *Library) android.Path { if snapshotRequiresImplementationJar(ctx) { return exportImplementationClassesJar(ctx, j) } @@ -156,9 +159,9 @@ var ( // jar for use by dexpreopting and boot jars package check. They do not need to provide an // actual implementation jar but the java_import will need a file that exists so just copy an // empty file. Any attempt to use that file as a jar will cause a build error. - return ctx.SnapshotBuilder().EmptyFile() + return nil }, - func(ctx android.SdkMemberContext, osPrefix, name string) string { + snapshotPathGetter: func(ctx android.SdkMemberContext, osPrefix, name string) string { if snapshotRequiresImplementationJar(ctx) { return sdkSnapshotFilePathForJar(ctx, osPrefix, name) } @@ -168,7 +171,7 @@ var ( // TODO(b/175714559): Provide a proper error message in Soong not ninja. return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix) }, - onlyCopyJarToSnapshot, + onlyCopyJarToSnapshot: onlyCopyJarToSnapshot, } // Supports adding java systemserver libraries to module_exports and sdk. @@ -182,27 +185,27 @@ var ( // necessary. The java_systemserver_libs property to allow those modules to be exported as part of // the sdk/module_exports without exposing any unnecessary information. javaSystemserverLibsSdkMemberType = &librarySdkMemberType{ - android.SdkMemberTypeBase{ + SdkMemberTypeBase: android.SdkMemberTypeBase{ PropertyName: "java_systemserver_libs", SupportsSdk: true, // This was only added in Tiramisu. SupportedBuildReleaseSpecification: "Tiramisu+", }, - func(ctx android.SdkMemberContext, j *Library) android.Path { + jarToExportGetter: func(ctx android.SdkMemberContext, j *Library) android.Path { // Java systemserver libs are only provided in the SDK to provide access to their dex // implementation jar for use by dexpreopting. They do not need to provide an actual // implementation jar but the java_import will need a file that exists so just copy an empty // file. Any attempt to use that file as a jar will cause a build error. - return ctx.SnapshotBuilder().EmptyFile() + return nil }, - func(_ android.SdkMemberContext, osPrefix, name string) string { + snapshotPathGetter: func(_ android.SdkMemberContext, osPrefix, name string) string { // Create a special name for the implementation jar to try and provide some useful information // to a developer that attempts to compile against this. // TODO(b/175714559): Provide a proper error message in Soong not ninja. return filepath.Join(osPrefix, "java_systemserver_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix) }, - onlyCopyJarToSnapshot, + onlyCopyJarToSnapshot: onlyCopyJarToSnapshot, } // Supports adding java test libraries to module_exports but not sdk. @@ -232,7 +235,7 @@ type JavaInfo struct { ImplementationAndResourcesJars android.Paths // ImplementationJars is a list of jars that contain the implementations of classes in the - //module. + // module. ImplementationJars android.Paths // ResourceJars is a list of jars that contain the resources included in the module. @@ -718,7 +721,8 @@ type librarySdkMemberType struct { android.SdkMemberTypeBase // Function to retrieve the appropriate output jar (implementation or header) from - // the library. + // the library, if this returns nil then it is assumed that the snapshot must not provide access + // to the jar. jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path // Function to compute the snapshot relative path to which the named library's @@ -755,7 +759,11 @@ func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMembe type librarySdkMemberProperties struct { android.SdkMemberPropertiesBase - JarToExport android.Path `android:"arch_variant"` + JarToExport android.Path `android:"arch_variant"` + + // The path to a script to use when the jar is invalid. + InvalidJarScript android.Path + AidlIncludeDirs android.Paths // The list of permitted packages that need to be passed to the prebuilts as they are used to @@ -766,7 +774,15 @@ type librarySdkMemberProperties struct { func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { j := variant.(*Library) - p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j) + memberType := ctx.MemberType().(*librarySdkMemberType) + p.JarToExport = memberType.jarToExportGetter(ctx, j) + + // If no jar was provided for export then disallow access to it completely. + if p.JarToExport == nil { + // Copy the script to prevent access to the jar into the snapshot. + p.InvalidJarScript = android.PathForSource(ctx.SdkModuleContext(), + "build/soong/java/invalid_implementation_jar.sh") + } p.AidlIncludeDirs = j.AidlIncludeDirs() @@ -789,6 +805,21 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) } + if scriptSrc := p.InvalidJarScript; scriptSrc != nil { + // Copy the script to prevent access to the jar into the snapshot. + scriptDest := filepath.Join("scripts", scriptSrc.Base()) + builder.CopyToSnapshot(scriptSrc, scriptDest) + + // Generate a genrule module that will invoke the script passing in the module name. + genrule := builder.AddInternalModule(p, "genrule", "error") + genRuleName := genrule.Name() + genrule.AddProperty("out", []string{"this-file-will-never-be-created.jar"}) + genrule.AddProperty("tool_files", []string{scriptDest}) + genrule.AddProperty("cmd", fmt.Sprintf("$(location %s) %s", scriptDest, p.Name())) + + propertySet.AddPropertyWithTag("jars", []string{":" + genRuleName}, builder.SdkMemberReferencePropertyTag(true)) + } + if len(p.PermittedPackages) > 0 { propertySet.AddProperty("permitted_packages", p.PermittedPackages) } @@ -1501,6 +1532,182 @@ func BinaryHostFactory() android.Module { return module } +type JavaApiContribution struct { + android.ModuleBase + android.DefaultableModuleBase + + properties struct { + // name of the API surface + Api_surface *string + + // relative path to the API signature text file + Api_file *string `android:"path"` + } +} + +func ApiContributionFactory() android.Module { + module := &JavaApiContribution{} + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + return module +} + +type JavaApiImportInfo struct { + ApiFile android.Path +} + +var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{}) + +func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) { + apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file)) + ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{ + ApiFile: apiFile, + }) +} + +type ApiLibrary struct { + android.ModuleBase + android.DefaultableModuleBase + + properties JavaApiLibraryProperties + + stubsSrcJar android.WritablePath + stubsJar android.WritablePath +} + +type JavaApiLibraryProperties struct { + // name of the API surface + Api_surface *string + + // list of API provider modules that consists this API surface + Api_providers []string + + // List of flags to be passed to the javac compiler to generate jar file + Javacflags []string +} + +func ApiLibraryFactory() android.Module { + module := &ApiLibrary{} + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + return module +} + +func (al *ApiLibrary) ApiSurface() *string { + return al.properties.Api_surface +} + +func (al *ApiLibrary) StubsJar() android.Path { + return al.stubsJar +} + +func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, + srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand { + rule.Command().Text("rm -rf").Flag(homeDir.String()) + rule.Command().Text("mkdir -p").Flag(homeDir.String()) + + cmd := rule.Command() + cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String()) + + if metalavaUseRbe(ctx) { + rule.Remoteable(android.RemoteRuleSupports{RBE: true}) + execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy) + labels := map[string]string{"type": "tool", "name": "metalava"} + + pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16") + rule.Rewrapper(&remoteexec.REParams{ + Labels: labels, + ExecStrategy: execStrategy, + ToolchainInputs: []string{config.JavaCmd(ctx).String()}, + Platform: map[string]string{remoteexec.PoolKey: pool}, + }) + } + + cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")). + Flag(config.JavacVmFlags). + Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED"). + FlagWithArg("-encoding ", "UTF-8"). + FlagWithInputList("--source-files ", srcs, " ") + + cmd.Flag("--no-banner"). + Flag("--color"). + Flag("--quiet"). + Flag("--format=v2"). + FlagWithArg("--repeat-errors-max ", "10"). + FlagWithArg("--hide ", "UnresolvedImport"). + FlagWithArg("--hide ", "InvalidNullabilityOverride"). + FlagWithArg("--hide ", "ChangedDefault") + + return cmd +} + +func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) { + if stubsDir.Valid() { + cmd.FlagWithArg("--stubs ", stubsDir.String()) + } +} + +var javaApiProviderTag = dependencyTag{name: "java-api-provider"} + +func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + apiProviders := al.properties.Api_providers + for _, apiProviderName := range apiProviders { + ctx.AddDependency(ctx.Module(), javaApiProviderTag, apiProviderName) + } +} + +func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + + rule := android.NewRuleBuilder(pctx, ctx) + + rule.Sbox(android.PathForModuleOut(ctx, "metalava"), + android.PathForModuleOut(ctx, "metalava.sbox.textproto")). + SandboxInputs() + + var stubsDir android.OptionalPath + stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir")) + rule.Command().Text("rm -rf").Text(stubsDir.String()) + rule.Command().Text("mkdir -p").Text(stubsDir.String()) + + homeDir := android.PathForModuleOut(ctx, "metalava", "home") + + apiProviders := al.properties.Api_providers + srcFiles := make([]android.Path, len(apiProviders)) + for i, apiProviderName := range apiProviders { + apiProvider := ctx.GetDirectDepWithTag(apiProviderName, javaApiProviderTag) + if apiProvider == nil { + panic(fmt.Errorf("Java API provider module %s not found, called from %s", apiProviderName, al.Name())) + } + provider := ctx.OtherModuleProvider(apiProvider, JavaApiImportProvider).(JavaApiImportInfo) + srcFiles[i] = android.PathForModuleSrc(ctx, provider.ApiFile.String()) + } + + cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir) + + al.stubsFlags(ctx, cmd, stubsDir) + + al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar") + rule.Command(). + BuiltTool("soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", al.stubsSrcJar). + FlagWithArg("-C ", stubsDir.String()). + FlagWithArg("-D ", stubsDir.String()) + + rule.Build("metalava", "metalava merged") + + al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar") + + var flags javaBuilderFlags + flags.javacFlags = strings.Join(al.properties.Javacflags, " ") + + TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{}, + android.Paths{al.stubsSrcJar}, flags, android.Paths{}) +} + // // Java prebuilts // @@ -1650,7 +1857,7 @@ func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { } func (j *Import) commonBuildActions(ctx android.ModuleContext) { - //TODO(b/231322772) these should come from Bazel once available + // TODO(b/231322772) these should come from Bazel once available j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) @@ -2253,7 +2460,7 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources)) } - //TODO(b/179889880) handle case where glob includes files outside package + // TODO(b/179889880) handle case where glob includes files outside package resDeps := ResourceDirsToFiles( ctx, m.properties.Java_resource_dirs, @@ -2307,11 +2514,21 @@ type javaAidlLibraryAttributes struct { Deps bazel.LabelListAttribute } -// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules -// and also separates dependencies into dynamic dependencies and static dependencies. -// Each corresponding Bazel target type, can have a different method for handling -// dynamic vs. static dependencies, and so these are returned to the calling function. -func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { +// bp2BuildJavaInfo has information needed for the conversion of java*_modules +// that is needed bor Bp2Build conversion but that requires different handling +// depending on the module type. +type bp2BuildJavaInfo struct { + // separates dependencies into dynamic dependencies and static dependencies. + DepLabels *javaDependencyLabels + hasKotlinSrcs bool +} + +// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with +// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct +// which has other non-attribute information needed for bp2build conversion +// that needs different handling depending on the module types, and thus needs +// to be returned to the calling function. +func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) { var srcs bazel.LabelListAttribute var deps bazel.LabelList var staticDeps bazel.LabelList @@ -2330,14 +2547,18 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) protoSrcPartition := "proto" logtagSrcPartition := "logtag" aidlSrcPartition := "aidl" + kotlinPartition := "kotlin" srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true}, logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, protoSrcPartition: android.ProtoSrcLabelPartition, aidlSrcPartition: android.AidlSrcLabelPartition, + kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}}, }) javaSrcs := srcPartitions[javaSrcPartition] + kotlinSrcs := srcPartitions[kotlinPartition] + javaSrcs.Append(kotlinSrcs) if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" @@ -2401,7 +2622,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } epEnabled := m.properties.Errorprone.Enabled - //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable + // TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable if Bool(epEnabled) { javacopts = append(javacopts, m.properties.Errorprone.Javacflags...) } @@ -2447,18 +2668,25 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) depLabels.Deps = bazel.MakeLabelListAttribute(deps) depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) - return commonAttrs, depLabels + bp2BuildInfo := &bp2BuildJavaInfo{ + DepLabels: depLabels, + hasKotlinSrcs: !kotlinSrcs.IsEmpty(), + } + + return commonAttrs, bp2BuildInfo } type javaLibraryAttributes struct { *javaCommonAttributes - Deps bazel.LabelListAttribute - Exports bazel.LabelListAttribute - Neverlink bazel.BoolAttribute + Deps bazel.LabelListAttribute + Exports bazel.LabelListAttribute + Neverlink bazel.BoolAttribute + Common_srcs bazel.LabelListAttribute } func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { - commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps if !commonAttrs.Srcs.IsEmpty() { @@ -2473,15 +2701,25 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") } + var props bazel.BazelTargetModuleProperties attrs := &javaLibraryAttributes{ javaCommonAttributes: commonAttrs, Deps: deps, Exports: depLabels.StaticDeps, } - props := bazel.BazelTargetModuleProperties{ - Rule_class: "java_library", - Bzl_load_location: "//build/bazel/rules/java:library.bzl", + if !bp2BuildInfo.hasKotlinSrcs && len(m.properties.Common_srcs) == 0 { + props = bazel.BazelTargetModuleProperties{ + Rule_class: "java_library", + Bzl_load_location: "//build/bazel/rules/java:library.bzl", + } + } else { + attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)) + + props = bazel.BazelTargetModuleProperties{ + Rule_class: "kt_jvm_library", + Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl", + } } name := m.Name() @@ -2498,7 +2736,8 @@ type javaBinaryHostAttributes struct { // JavaBinaryHostBp2Build is for java_binary_host bp2build. func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { - commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps deps.Append(depLabels.StaticDeps) @@ -2637,7 +2876,7 @@ func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) { HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile), ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile), ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile), - //TODO(b/240308299) include AIDL information from Bazel + // TODO(b/240308299) include AIDL information from Bazel }) i.maybeInstall(ctx, jarName, outputFile) diff --git a/java/java_test.go b/java/java_test.go index f06b520d5..3f8cd8e90 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1806,3 +1806,108 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) { srcs: ["foo.java"], }`) } + +func TestJavaApiLibraryAndProviderLink(t *testing.T) { + provider_bp_a := ` + java_api_contribution { + name: "foo1", + api_file: "foo1.txt", + } + ` + provider_bp_b := `java_api_contribution { + name: "foo2", + api_file: "foo2.txt", + } + ` + ctx, _ := testJavaWithFS(t, ` + java_api_library { + name: "bar1", + api_surface: "public", + api_providers: ["foo1"], + } + + java_api_library { + name: "bar2", + api_surface: "system", + api_providers: ["foo1", "foo2"], + } + `, + map[string][]byte{ + "a/Android.bp": []byte(provider_bp_a), + "b/Android.bp": []byte(provider_bp_b), + }) + + testcases := []struct { + moduleName string + sourceTextFileDirs []string + }{ + { + moduleName: "bar1", + sourceTextFileDirs: []string{"a/foo1.txt"}, + }, + { + moduleName: "bar2", + sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"}, + }, + } + for _, c := range testcases { + m := ctx.ModuleForTests(c.moduleName, "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ") + android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) + } +} + +func TestJavaApiLibraryJarGeneration(t *testing.T) { + provider_bp_a := ` + java_api_contribution { + name: "foo1", + api_file: "foo1.txt", + } + ` + provider_bp_b := `java_api_contribution { + name: "foo2", + api_file: "foo2.txt", + } + ` + ctx, _ := testJavaWithFS(t, ` + java_api_library { + name: "bar1", + api_surface: "public", + api_providers: ["foo1"], + } + + java_api_library { + name: "bar2", + api_surface: "system", + api_providers: ["foo1", "foo2"], + } + `, + map[string][]byte{ + "a/Android.bp": []byte(provider_bp_a), + "b/Android.bp": []byte(provider_bp_b), + }) + + testcases := []struct { + moduleName string + outputJarName string + }{ + { + moduleName: "bar1", + outputJarName: "bar1/android.jar", + }, + { + moduleName: "bar2", + outputJarName: "bar2/android.jar", + }, + } + for _, c := range testcases { + m := ctx.ModuleForTests(c.moduleName, "android_common") + outputs := fmt.Sprint(m.AllOutputs()) + if !strings.Contains(outputs, c.outputJarName) { + t.Errorf("Module output does not contain expected jar %s", c.outputJarName) + } + } +} diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go index 8e224914d..1f374b42e 100644 --- a/java/legacy_core_platform_api_usage.go +++ b/java/legacy_core_platform_api_usage.go @@ -20,155 +20,39 @@ import ( ) var legacyCorePlatformApiModules = []string{ - "AAECarSystemUI", - "AAECarSystemUI-tests", "ArcSettings", - "ahat-test-dump", - "android.car", - "android.test.mock", - "android.test.mock.impl", - "AoapTestDeviceApp", - "AoapTestHostApp", - "api-stubs-docs", - "art_cts_jvmti_test_library", - "art-gtest-jars-MyClassNatives", - "BackupEncryption", - "BackupFrameworksServicesRoboTests", - "backuplib", - "BandwidthEnforcementTest", - "BlockedNumberProvider", - "BluetoothInstrumentationTests", - "BluetoothMidiLib", - "BluetoothMidiService", "BTTestApp", - "CallEnhancement", "CapCtrlInterface", - "CarService", - "CarServiceTest", - "car-service-test-lib", - "car-service-test-static-lib", - "CertInstaller", "com.qti.location.sdk", - "com.qti.media.secureprocessor", - "ConnectivityManagerTest", - "ContactsProvider", - "CorePerfTests", - "core-tests-support", - "cronet_impl_common_java", - "cronet_impl_native_java", - "cronet_impl_platform_java", - "CtsAppExitTestCases", - "CtsContentTestCases", - "CtsLibcoreWycheproofBCTestCases", - "CtsMediaTestCases", - "CtsNetTestCases", - "CtsNetTestCasesLatestSdk", - "CtsSecurityTestCases", - "CtsSuspendAppsTestCases", - "CtsUsageStatsTestCases", - "DeadpoolService", - "DeadpoolServiceBtServices", - "DeviceInfo", - "DiagnosticTools", - "DisplayCutoutEmulationEmu01Overlay", - "DocumentsUIGoogleTests", - "DocumentsUIPerfTests", - "DocumentsUITests", - "DocumentsUIUnitTests", - "DownloadProvider", - "DownloadProviderTests", - "DownloadProviderUi", - "ds-car-docs", // for AAOS API documentation only - "DynamicSystemInstallationService", - "EmergencyInfo-lib", - "EthernetServiceTests", - "ExternalStorageProvider", "face-V1-0-javalib", "FloralClocks", "framework-jobscheduler", "framework-minus-apex", "framework-minus-apex-intdefs", - "FrameworkOverlayG6QU3", "FrameworksCoreTests", - "FrameworksIkeTests", - "FrameworksNetCommonTests", - "FrameworksNetTests", - "FrameworksServicesRoboTests", - "FrameworksServicesTests", - "FrameworksMockingServicesTests", - "FrameworksUtilTests", - "GtsIncrementalInstallTestCases", - "GtsIncrementalInstallTriggerApp", - "GtsInstallerV2TestCases", "HelloOslo", - "hid", - "hidl_test_java_java", - "hwbinder", - "imssettings", "izat.lib.glue", - "KeyChain", - "LocalSettingsLib", - "LocalTransport", - "lockagent", - "mediaframeworktest", "mediatek-ims-base", - "MmsService", "ModemTestMode", "MtkCapCtrl", - "MtpService", - "MultiDisplayProvider", "my.tests.snapdragonsdktest", "NetworkSetting", - "NetworkStackIntegrationTestsLib", - "NetworkStackNextIntegrationTests", - "NetworkStackNextTests", - "NetworkStackTests", - "NetworkStackTestsLib", - "online-gcm-ref-docs", - "online-gts-docs", "PerformanceMode", - "platform_library-docs", - "PowerStatsService", - "PrintSpooler", "pxp-monitor", "QColor", "qcom.fmradio", - "QDCMMobileApp", "Qmmi", "QPerformance", - "remotesimlockmanagerlibrary", - "RollbackTest", "sam", "saminterfacelibrary", "sammanagerlibrary", - "service-blobstore", - "service-connectivity-pre-jarjar", - "service-jobscheduler", "services", - "services.accessibility", - "services.backup", "services.core.unboosted", - "services.devicepolicy", - "services.print", - "services.usage", - "services.usb", "Settings-core", "SettingsGoogle", "SettingsGoogleOverlayCoral", "SettingsGoogleOverlayFlame", "SettingsLib", - "SettingsOverlayG020A", - "SettingsOverlayG020B", - "SettingsOverlayG020C", - "SettingsOverlayG020D", - "SettingsOverlayG020E", - "SettingsOverlayG020E_VN", - "SettingsOverlayG020F", - "SettingsOverlayG020F_VN", - "SettingsOverlayG020G", - "SettingsOverlayG020G_VN", - "SettingsOverlayG020H", - "SettingsOverlayG020H_VN", "SettingsOverlayG020I", "SettingsOverlayG020I_VN", "SettingsOverlayG020J", @@ -177,45 +61,15 @@ var legacyCorePlatformApiModules = []string{ "SettingsOverlayG020P", "SettingsOverlayG020Q", "SettingsOverlayG025H", - "SettingsOverlayG025J", - "SettingsOverlayG025M", - "SettingsOverlayG025N", "SettingsOverlayG5NZ6", - "SettingsProvider", - "SettingsProviderTest", "SettingsRoboTests", - "Shell", - "ShellTests", "SimContact", "SimContacts", "SimSettings", - "sl4a.Common", - "StatementService", - "SystemUI-core", - "SystemUISharedLib", - "SystemUI-tests", "tcmiface", - "Telecom", - "TelecomUnitTests", "telephony-common", - "TelephonyProviderTests", "TeleService", - "testables", - "TetheringTests", - "TetheringTestsLib", - "time_zone_distro_installer", - "time_zone_distro_installer-tests", - "time_zone_distro-tests", - "time_zone_updater", - "TMobilePlanProvider", - "TvProvider", - "uiautomator-stubs-docs", - "uimgbamanagerlibrary", - "UsbHostExternalManagementTestApp", - "UserDictionaryProvider", "UxPerformance", - "WallpaperBackup", - "WallpaperBackupAgentTests", "WfdCommon", } diff --git a/java/plugin.go b/java/plugin.go index 123dbd4c0..731dfda00 100644 --- a/java/plugin.go +++ b/java/plugin.go @@ -66,7 +66,8 @@ type pluginAttributes struct { // ConvertWithBp2build is used to convert android_app to Bazel. func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) { pluginName := p.Name() - commonAttrs, depLabels := p.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := p.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps deps.Append(depLabels.StaticDeps) |