diff options
Diffstat (limited to 'java')
80 files changed, 4230 insertions, 1843 deletions
diff --git a/java/Android.bp b/java/Android.bp index 885e6825a..911af8336 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -51,6 +51,7 @@ bootstrap_go_package { "gen.go", "generated_java_library.go", "genrule.go", + "genrule_combiner.go", "hiddenapi.go", "hiddenapi_modular.go", "hiddenapi_monolithic.go", @@ -95,6 +96,7 @@ bootstrap_go_package { "droiddoc_test.go", "droidstubs_test.go", "fuzz_test.go", + "genrule_combiner_test.go", "genrule_test.go", "generated_java_library_test.go", "hiddenapi_singleton_test.go", diff --git a/java/aar.go b/java/aar.go index e0e642e36..f7c5c13de 100644 --- a/java/aar.go +++ b/java/aar.go @@ -257,7 +257,7 @@ func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool { } func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext, - manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, + manifestPath android.Path, doNotIncludeAssetDirImplicitly bool) (compileFlags, linkFlags []string, linkDeps android.Paths, resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code") @@ -274,7 +274,12 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte Paths: a.aaptProperties.Assets, IncludeDirs: false, }) - assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") + var assetDirs android.Paths + if doNotIncludeAssetDirImplicitly { + assetDirs = android.PathsForModuleSrc(ctx, a.aaptProperties.Asset_dirs) + } else { + assetDirs = android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") + } resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs.GetOrDefault(ctx, nil), "res") resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips) @@ -386,8 +391,9 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte versionName = proptools.NinjaEscape(versionName) linkFlags = append(linkFlags, "--version-name ", versionName) } - - linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"}) + // Split the flags by prefix, as --png-compression-level has the "=value" suffix. + linkFlags, compileFlags = android.FilterListByPrefix(linkFlags, + []string{"--legacy", "--png-compression-level"}) // Always set --pseudo-localize, it will be stripped out later for release // builds that don't want it. @@ -494,7 +500,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio a.mergedManifestFile = manifestPath } - compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath) + // do not include assets in autogenerated RRO. + compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath, opts.rroDirs != nil) a.rroDirsDepSet = depset.NewBuilder[rroDir](depset.TOPOLOGICAL). Direct(rroDirs...). @@ -588,14 +595,16 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio } } - for _, dir := range overlayDirs { - compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, - compileFlags, a.filterProduct(), opts.aconfigTextFiles).Paths()...) - } - var compiledRro, compiledRroOverlay android.Paths if opts.rroDirs != nil { compiledRro, compiledRroOverlay = a.compileResInDir(ctx, *opts.rroDirs, compileFlags, opts.aconfigTextFiles) + } else { + // RRO enforcement is done based on module name. Compile the overlayDirs only if rroDirs is nil. + // This ensures that the autogenerated RROs do not compile the overlay dirs twice. + for _, dir := range overlayDirs { + compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, + compileFlags, a.filterProduct(), opts.aconfigTextFiles).Paths()...) + } } var splitPackages android.WritablePaths @@ -867,13 +876,15 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, rroDirsDepSetBuilder := depset.NewBuilder[rroDir](depset.TOPOLOGICAL) manifestsDepSetBuilder := depset.NewBuilder[android.Path](depset.TOPOLOGICAL) - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { depTag := ctx.OtherModuleDependencyTag(module) var exportPackage android.Path - aarDep, _ := module.(AndroidLibraryDependency) - if aarDep != nil { - exportPackage = aarDep.ExportPackage() + var aarDep *AndroidLibraryDependencyInfo + javaInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider) + if ok && javaInfo.AndroidLibraryDependencyInfo != nil { + aarDep = javaInfo.AndroidLibraryDependencyInfo + exportPackage = aarDep.ExportPackage } switch depTag { @@ -881,7 +892,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2. case sdkLibTag, libTag, rroDepTag: if exportPackage != nil { - sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet()) + sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet) sharedLibs = append(sharedLibs, exportPackage) } case frameworkResTag: @@ -890,9 +901,9 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, } case staticLibTag: if exportPackage != nil { - staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet()) - rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet()) - manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet()) + staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet) + rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet) + manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet) } } @@ -928,6 +939,12 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, return staticResourcesNodes, sharedResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags } +type AndroidLibraryInfo struct { + // Empty for now +} + +var AndroidLibraryInfoProvider = blueprint.NewProvider[AndroidLibraryInfo]() + type AndroidLibrary struct { Library aapt @@ -1014,7 +1031,7 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) extraSrcJars = android.Paths{a.aapt.aaptSrcJar} } - a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil) + javaInfo := a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil) a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar") var res android.Paths @@ -1023,7 +1040,7 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } prebuiltJniPackages := android.Paths{} - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok { prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...) } @@ -1038,7 +1055,16 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) AconfigTextFiles: aconfigTextFilePaths, }) + android.SetProvider(ctx, AndroidLibraryInfoProvider, AndroidLibraryInfo{}) + + if javaInfo != nil { + setExtraJavaInfo(ctx, a, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + } + a.setOutputFiles(ctx) + + buildComplianceMetadata(ctx) } func (a *AndroidLibrary) setOutputFiles(ctx android.ModuleContext) { @@ -1431,7 +1457,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { var transitiveStaticLibsImplementationJars []depset.DepSet[android.Path] var transitiveStaticLibsResourceJars []depset.DepSet[android.Path] - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { tag := ctx.OtherModuleDependencyTag(module) switch tag { @@ -1526,7 +1552,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.CheckbuildFile(a.implementationJarFile) } - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + javaInfo := &JavaInfo{ HeaderJars: android.PathsIfNonNil(a.headerJarFile), LocalHeaderJars: android.PathsIfNonNil(classpathFile), TransitiveStaticLibsHeaderJars: completeStaticLibsHeaderJars, @@ -1539,7 +1565,9 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { ImplementationJars: android.PathsIfNonNil(a.implementationJarFile), StubsLinkType: Implementation, // TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts - }) + } + setExtraJavaInfo(ctx, a, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) if proptools.Bool(a.properties.Extract_jni) { for _, t := range ctx.MultiTargets() { @@ -1568,6 +1596,8 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.SetOutputFiles([]android.Path{a.implementationAndResourcesJarFile}, "") ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar") + + buildComplianceMetadata(ctx) } func (a *AARImport) HeaderJars() android.Paths { @@ -1595,14 +1625,21 @@ var _ UsesLibraryDependency = (*AARImport)(nil) var _ android.ApexModule = (*AARImport)(nil) // Implements android.ApexModule -func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - return a.depIsInSameApex(ctx, dep) +func (m *AARImport) GetDepInSameApexChecker() android.DepInSameApexChecker { + return AARImportDepInSameApexChecker{} +} + +type AARImportDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m AARImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + return depIsInSameApex(tag) } // Implements android.ApexModule -func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { - return nil +func (a *AARImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } var _ android.PrebuiltInterface = (*AARImport)(nil) @@ -1632,5 +1669,5 @@ func AARImportFactory() android.Module { } func (a *AARImport) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { - dpInfo.Jars = append(dpInfo.Jars, a.headerJarFile.String(), a.rJar.String()) + dpInfo.Jars = append(dpInfo.Jars, a.implementationJarFile.String(), a.rJar.String()) } diff --git a/java/aar_test.go b/java/aar_test.go index aa4f0af10..088ad6c92 100644 --- a/java/aar_test.go +++ b/java/aar_test.go @@ -21,6 +21,7 @@ import ( ) func TestAarImportProducesJniPackages(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -50,8 +51,9 @@ func TestAarImportProducesJniPackages(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() appMod := ctx.Module(tc.name, "android_common") - appTestMod := ctx.ModuleForTests(tc.name, "android_common") + appTestMod := ctx.ModuleForTests(t, tc.name, "android_common") info, ok := android.OtherModuleProvider(ctx, appMod, JniPackageProvider) if !ok { @@ -84,6 +86,7 @@ func TestAarImportProducesJniPackages(t *testing.T) { } func TestLibraryFlagsPackages(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, ).RunTestWithBp(t, ` @@ -114,7 +117,7 @@ func TestLibraryFlagsPackages(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") // android_library module depends on aconfig_declarations listed in flags_packages android.AssertBoolEquals(t, "foo expected to depend on bar", true, @@ -133,6 +136,7 @@ func TestLibraryFlagsPackages(t *testing.T) { } func TestAndroidLibraryOutputFilesRel(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -155,9 +159,9 @@ func TestAndroidLibraryOutputFilesRel(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") - bar := result.ModuleForTests("bar", "android_common") - baz := result.ModuleForTests("baz", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") + bar := result.ModuleForTests(t, "bar", "android_common") + baz := result.ModuleForTests(t, "baz", "android_common") fooOutputPaths := foo.OutputFiles(result.TestContext, t, "") barOutputPaths := bar.OutputFiles(result.TestContext, t, "") diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go index 7c9188462..ce227b9c8 100644 --- a/java/android_manifest_test.go +++ b/java/android_manifest_test.go @@ -21,6 +21,7 @@ import ( ) func TestManifestMerger(t *testing.T) { + t.Parallel() bp := ` android_app { name: "app", @@ -80,7 +81,7 @@ func TestManifestMerger(t *testing.T) { result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp) - manifestMergerRule := result.ModuleForTests("app", "android_common").Rule("manifestMerger") + manifestMergerRule := result.ModuleForTests(t, "app", "android_common").Rule("manifestMerger") android.AssertPathRelativeToTopEquals(t, "main manifest", "out/soong/.intermediates/app/android_common/manifest_fixer/AndroidManifest.xml", manifestMergerRule.Input) @@ -100,6 +101,7 @@ func TestManifestMerger(t *testing.T) { } func TestManifestValuesApplicationIdSetsPackageName(t *testing.T) { + t.Parallel() bp := ` android_test { name: "test", @@ -127,7 +129,7 @@ func TestManifestValuesApplicationIdSetsPackageName(t *testing.T) { result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp) - manifestMergerRule := result.ModuleForTests("test", "android_common").Rule("manifestMerger") + manifestMergerRule := result.ModuleForTests(t, "test", "android_common").Rule("manifestMerger") android.AssertStringMatches(t, "manifest merger args", manifestMergerRule.Args["args"], diff --git a/java/androidmk.go b/java/androidmk.go index 2ad30b132..c9de7e6d2 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -23,13 +23,12 @@ import ( "github.com/google/blueprint/proptools" ) -func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries { - hostDexNeeded := Bool(library.deviceProperties.Hostdex) && !library.Host() - if library.hideApexVariantFromMake { - hostDexNeeded = false - } +func (library *Library) hostDexNeeded() bool { + return Bool(library.deviceProperties.Hostdex) && !library.Host() && !library.hideApexVariantFromMake +} - if hostDexNeeded { +func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries { + if library.hostDexNeeded() { var output android.Path if library.dexJarFile.IsSet() { output = library.dexJarFile.Path() @@ -71,11 +70,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.hideApexVariantFromMake { // For a java library built for an APEX, we don't need a Make module for itself. Otherwise, it // will conflict with the platform variant because they have the same module name in the - // makefile. However, we need to add its dexpreopt outputs as sub-modules, if it is preopted. - dexpreoptEntries := library.dexpreopter.AndroidMkEntriesForApex() - if len(dexpreoptEntries) > 0 { - entriesList = append(entriesList, dexpreoptEntries...) - } + // makefile. entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true}) } else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) { // Platform variant. If not available for the platform, we don't need Make module. @@ -125,6 +120,14 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { } }, }, + ExtraFooters: []android.AndroidMkExtraFootersFunc{ + func(w io.Writer, name, prefix, moduleDir string) { + if library.apiXmlFile != nil { + fmt.Fprintf(w, "$(call declare-1p-target,%s,)\n", library.apiXmlFile.String()) + fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,$(TARGET_OUT_COMMON_INTERMEDIATES)/%s))\n", library.apiXmlFile.String(), library.apiXmlFile.Base()) + } + }, + }, }) } @@ -307,15 +310,11 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { Disabled: true, }} } - var required []string - if proptools.Bool(app.appProperties.Generate_product_characteristics_rro) { - required = []string{app.productCharacteristicsRROPackageName()} - } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "APPS", OutputFile: android.OptionalPathForPath(app.outputFile), Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk", - Required: required, + Required: app.requiredModuleNames, ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { // App module names can be overridden. @@ -350,31 +349,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { entries.SetBoolIfTrue("LOCAL_NO_STANDARD_LIBRARIES", true) } - filterRRO := func(filter overlayType) android.Paths { - var paths android.Paths - seen := make(map[android.Path]bool) - for _, d := range app.rroDirsDepSet.ToList() { - if d.overlayType == filter { - if seen[d.path] { - continue - } - seen[d.path] = true - paths = append(paths, d.path) - } - } - // Reverse the order, Soong stores rroDirs in aapt2 order (low to high priority), but Make - // expects it in LOCAL_RESOURCE_DIRS order (high to low priority). - return android.ReversePaths(paths) - } - deviceRRODirs := filterRRO(device) - if len(deviceRRODirs) > 0 { - entries.AddStrings("LOCAL_SOONG_DEVICE_RRO_DIRS", deviceRRODirs.Strings()...) - } - productRRODirs := filterRRO(product) - if len(productRRODirs) > 0 { - entries.AddStrings("LOCAL_SOONG_PRODUCT_RRO_DIRS", productRRODirs.Strings()...) - } - entries.SetBoolIfTrue("LOCAL_EXPORT_PACKAGE_RESOURCES", Bool(app.appProperties.Export_package_resources)) entries.SetPath("LOCAL_FULL_MANIFEST_FILE", app.manifestPath) @@ -437,7 +411,7 @@ func (a *AutogenRuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEn Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_CERTIFICATE", "presigned") // The apk will be signed by soong + entries.SetString("LOCAL_CERTIFICATE", a.certificate.AndroidMkString()) }, }, }} @@ -584,73 +558,11 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries { }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ func(w io.Writer, name, prefix, moduleDir string) { - if dstubs.apiFile != nil { - fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name()) - fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.apiFile) - } - if dstubs.removedApiFile != nil { - fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name()) - fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.removedApiFile) - } - if dstubs.checkCurrentApiTimestamp != nil { - fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-current-api") - fmt.Fprintln(w, dstubs.Name()+"-check-current-api:", - dstubs.checkCurrentApiTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - dstubs.checkCurrentApiTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - } - if dstubs.updateCurrentApiTimestamp != nil { - fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-update-current-api") - fmt.Fprintln(w, dstubs.Name()+"-update-current-api:", - dstubs.updateCurrentApiTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: update-api") - fmt.Fprintln(w, "update-api:", - dstubs.updateCurrentApiTimestamp.String()) - } - if dstubs.checkLastReleasedApiTimestamp != nil { - fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-last-released-api") - fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:", - dstubs.checkLastReleasedApiTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - dstubs.checkLastReleasedApiTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - } if dstubs.apiLintTimestamp != nil { - fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint") - fmt.Fprintln(w, dstubs.Name()+"-api-lint:", - dstubs.apiLintTimestamp.String()) - - fmt.Fprintln(w, ".PHONY: checkapi") - fmt.Fprintln(w, "checkapi:", - dstubs.Name()+"-api-lint") - - fmt.Fprintln(w, ".PHONY: droidcore") - fmt.Fprintln(w, "droidcore: checkapi") - if dstubs.apiLintReport != nil { - fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n", dstubs.Name()+"-api-lint", - dstubs.apiLintReport.String(), "apilint/"+dstubs.Name()+"-lint-report.txt") fmt.Fprintf(w, "$(call declare-0p-target,%s)\n", dstubs.apiLintReport.String()) } } - if dstubs.checkNullabilityWarningsTimestamp != nil { - fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings") - fmt.Fprintln(w, dstubs.Name()+"-check-nullability-warnings:", - dstubs.checkNullabilityWarningsTimestamp.String()) - - fmt.Fprintln(w, ".PHONY:", "droidcore") - fmt.Fprintln(w, "droidcore: ", dstubs.Name()+"-check-nullability-warnings") - } }, }, }} diff --git a/java/androidmk_test.go b/java/androidmk_test.go index 1d98b180d..b4b13b11a 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -23,6 +23,7 @@ import ( ) func TestRequired(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -31,7 +32,7 @@ func TestRequired(t *testing.T) { } `) - mod := ctx.ModuleForTests("foo", "android_common").Module() + mod := ctx.ModuleForTests(t, "foo", "android_common").Module() entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] expected := []string{"libfoo"} @@ -42,6 +43,7 @@ func TestRequired(t *testing.T) { } func TestHostdex(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -50,7 +52,7 @@ func TestHostdex(t *testing.T) { } `) - mod := ctx.ModuleForTests("foo", "android_common").Module() + mod := ctx.ModuleForTests(t, "foo", "android_common").Module() entriesList := android.AndroidMkEntriesForTest(t, ctx, mod) if len(entriesList) != 2 { t.Errorf("two entries are expected, but got %d", len(entriesList)) @@ -72,6 +74,7 @@ func TestHostdex(t *testing.T) { } func TestHostdexRequired(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -81,7 +84,7 @@ func TestHostdexRequired(t *testing.T) { } `) - mod := ctx.ModuleForTests("foo", "android_common").Module() + mod := ctx.ModuleForTests(t, "foo", "android_common").Module() entriesList := android.AndroidMkEntriesForTest(t, ctx, mod) if len(entriesList) != 2 { t.Errorf("two entries are expected, but got %d", len(entriesList)) @@ -103,6 +106,7 @@ func TestHostdexRequired(t *testing.T) { } func TestHostdexSpecificRequired(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -116,7 +120,7 @@ func TestHostdexSpecificRequired(t *testing.T) { } `) - mod := ctx.ModuleForTests("foo", "android_common").Module() + mod := ctx.ModuleForTests(t, "foo", "android_common").Module() entriesList := android.AndroidMkEntriesForTest(t, ctx, mod) if len(entriesList) != 2 { t.Errorf("two entries are expected, but got %d", len(entriesList)) @@ -136,6 +140,7 @@ func TestHostdexSpecificRequired(t *testing.T) { } func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -153,7 +158,7 @@ func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { `) // Verify the existence of internal modules - result.ModuleForTests("foo-shared_library.xml", "android_common") + result.ModuleForTests(t, "foo-shared_library.xml", "android_common") testCases := []struct { moduleName string @@ -163,7 +168,7 @@ func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { {"foo-no_shared_library", []string{"foo-no_shared_library.impl"}}, } for _, tc := range testCases { - mod := result.ModuleForTests(tc.moduleName, "android_common").Module() + mod := result.ModuleForTests(t, tc.moduleName, "android_common").Module() entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0] actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"] if !reflect.DeepEqual(tc.expected, actual) { @@ -173,6 +178,7 @@ func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) { } func TestImportSoongDexJar(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` java_import { name: "my-java-import", @@ -191,6 +197,7 @@ func TestImportSoongDexJar(t *testing.T) { } func TestAndroidTestHelperApp_LocalDisableTestConfig(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_test_helper_app { name: "foo", @@ -198,7 +205,7 @@ func TestAndroidTestHelperApp_LocalDisableTestConfig(t *testing.T) { } `) - mod := ctx.ModuleForTests("foo", "android_common").Module() + mod := ctx.ModuleForTests(t, "foo", "android_common").Module() entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] expected := []string{"true"} @@ -209,6 +216,7 @@ func TestAndroidTestHelperApp_LocalDisableTestConfig(t *testing.T) { } func TestGetOverriddenPackages(t *testing.T) { + t.Parallel() ctx, _ := testJava( t, ` android_app { @@ -246,7 +254,7 @@ func TestGetOverriddenPackages(t *testing.T) { } for _, expected := range expectedVariants { - mod := ctx.ModuleForTests(expected.name, expected.variantName).Module() + mod := ctx.ModuleForTests(t, expected.name, expected.variantName).Module() entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0] actual := entries.EntryMap["LOCAL_OVERRIDES_PACKAGES"] @@ -255,6 +263,7 @@ func TestGetOverriddenPackages(t *testing.T) { } func TestJniAsRequiredDeps(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, cc.PrepareForTestWithCcDefaultModules, @@ -295,7 +304,7 @@ func TestJniAsRequiredDeps(t *testing.T) { } for _, tc := range testcases { - mod := ctx.ModuleForTests(tc.name, "android_common").Module() + mod := ctx.ModuleForTests(t, tc.name, "android_common").Module() entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0] required := entries.EntryMap["LOCAL_REQUIRED_MODULES"] android.AssertDeepEquals(t, "unexpected required deps", tc.expected, required) diff --git a/java/app.go b/java/app.go index 4dea7dc1b..02e65be37 100644 --- a/java/app.go +++ b/java/app.go @@ -70,6 +70,8 @@ type AppInfo struct { // EmbeddedJNILibs is the list of paths to JNI libraries that were embedded in the APK. EmbeddedJNILibs android.Paths + + MergedManifestFile android.Path } var AppInfoProvider = blueprint.NewProvider[*AppInfo]() @@ -223,6 +225,8 @@ type AndroidApp struct { javaApiUsedByOutputFile android.ModuleOutPath privAppAllowlist android.OptionalPath + + requiredModuleNames []string } func (a *AndroidApp) IsInstallable() bool { @@ -401,6 +405,14 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon Updatable: Bool(a.appProperties.Updatable), TestHelperApp: true, }) + + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests") + if len(a.appTestHelperAppProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.appTestHelperAppProperties.Test_suites...) + } else { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") + } } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -417,10 +429,29 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } android.SetProvider(ctx, AppInfoProvider, &AppInfo{ - Updatable: Bool(a.appProperties.Updatable), - TestHelperApp: false, - EmbeddedJNILibs: embeddedJniLibs, + Updatable: Bool(a.appProperties.Updatable), + TestHelperApp: false, + EmbeddedJNILibs: embeddedJniLibs, + MergedManifestFile: a.mergedManifest, }) + + a.requiredModuleNames = a.getRequiredModuleNames(ctx) +} + +func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string { + var required []string + if proptools.Bool(a.appProperties.Generate_product_characteristics_rro) { + required = []string{a.productCharacteristicsRROPackageName()} + } + // Install the vendor overlay variant if this app is installed. + if len(filterRRO(a.rroDirsDepSet, device)) > 0 { + required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "vendor")) + } + // Install the product overlay variant if this app is installed. + if len(filterRRO(a.rroDirsDepSet, product)) > 0 { + required = append(required, AutogeneratedRroModuleName(ctx, ctx.Module().Name(), "product")) + } + return required } func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { @@ -467,18 +498,28 @@ func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) { // This check is enforced for "updatable" APKs (including APK-in-APEX). func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) { // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() - ctx.VisitDirectDeps(func(m android.Module) { + ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) { if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { return } - dep, _ := m.(*cc.Module) + if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); !ok { + panic(fmt.Errorf("jni dependency is not a cc module: %v", m)) + } + commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoKey) + if !ok { + panic(fmt.Errorf("jni dependency doesn't have CommonModuleInfo provider: %v", m)) + } // The domain of cc.sdk_version is "current" and <number> // We can rely on android.SdkSpec to convert it to <number> so that "current" is // handled properly regardless of sdk finalization. - jniSdkVersion, err := android.SdkSpecFrom(ctx, dep.MinSdkVersion()).EffectiveVersion(ctx) + ver := "" + if !commonInfo.MinSdkVersion.IsPlatform { + ver = commonInfo.MinSdkVersion.ApiLevel.String() + } + jniSdkVersion, err := android.SdkSpecFrom(ctx, ver).EffectiveVersion(ctx) if err != nil || minSdkVersion.LessThan(jniSdkVersion) { - ctx.OtherModuleErrorf(dep, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", - dep.MinSdkVersion(), minSdkVersion, ctx.ModuleName()) + ctx.OtherModuleErrorf(m, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", + ver, minSdkVersion, ctx.ModuleName()) return } @@ -541,7 +582,7 @@ func (a *AndroidApp) renameResourcesPackage() bool { } func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) { - ctx.VisitDirectDeps(func(dep android.Module) { + ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(dep) switch tag { case staticLibTag: @@ -647,7 +688,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) { var staticLibProguardFlagFiles android.Paths - ctx.VisitDirectDeps(func(m android.Module) { + ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) { depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider) staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...) if ctx.OtherModuleDependencyTag(m) == staticLibTag { @@ -681,7 +722,7 @@ func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") } -func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path) { +func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path, *JavaInfo) { a.dexpreopter.installPath = a.installPath(ctx) a.dexpreopter.isApp = true if a.dexProperties.Uncompress_dex == nil { @@ -696,6 +737,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a var packageResources = a.exportPackage + javaInfo := &JavaInfo{} if ctx.ModuleName() != "framework-res" { if a.dexProperties.resourceShrinkingEnabled(ctx) { protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk") @@ -719,7 +761,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a extraSrcJars = android.Paths{a.aapt.aaptSrcJar} } - a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil) + javaInfo = a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil) if a.dexProperties.resourceShrinkingEnabled(ctx) { binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk") aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary") @@ -727,7 +769,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, a } } - return a.dexJarFile.PathOrNil(), packageResources + return a.dexJarFile.PathOrNil(), packageResources, javaInfo } func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath { @@ -934,7 +976,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.linter.resources = a.aapt.resourceFiles a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps() - dexJarFile, packageResources := a.dexBuildActions(ctx) + dexJarFile, packageResources, javaInfo := a.dexBuildActions(ctx) // No need to check the SDK version of the JNI deps unless we embed them checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis) @@ -1050,7 +1092,23 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { }, ) + if javaInfo != nil { + javaInfo.OutputFile = a.outputFile + setExtraJavaInfo(ctx, a, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + } + + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Class = []string{"APPS"} + if !a.embeddedJniLibs { + for _, jniLib := range a.jniLibs { + moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, jniLib.name) + } + } + a.setOutputFiles(ctx) + + buildComplianceMetadata(ctx) } func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) { @@ -1082,29 +1140,35 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx) } jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps, - checkNativeSdkVersion, func(parent, child android.Module) bool { + checkNativeSdkVersion, func(parent, child android.ModuleProxy) bool { apkInApex := ctx.Module().(android.ApexModule).NotInPlatform() - childLinkable, _ := child.(cc.LinkableInterface) - parentLinkable, _ := parent.(cc.LinkableInterface) - useStubsOfDep := childLinkable.IsStubs() - if apkInApex && parentLinkable != nil { + childLinkable, _ := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider) + parentIsLinkable := false + if ctx.EqualModules(ctx.Module(), parent) { + parentLinkable, _ := ctx.Module().(cc.LinkableInterface) + parentIsLinkable = parentLinkable != nil + } else { + _, parentIsLinkable = android.OtherModuleProvider(ctx, parent, cc.LinkableInfoProvider) + } + useStubsOfDep := childLinkable.IsStubs + if apkInApex && parentIsLinkable { // APK-in-APEX // If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary. - useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child)) + useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants && cc.ShouldUseStubForApex(ctx, parent, child)) } - return !childLinkable.IsNdk(ctx.Config()) && !useStubsOfDep + return !childLinkable.IsNdk && !useStubsOfDep }) var certificates []Certificate var directImplementationDeps android.Paths var transitiveImplementationDeps []depset.DepSet[android.Path] - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) if tag == certificateTag { - if dep, ok := module.(*AndroidAppCertificate); ok { + if dep, ok := android.OtherModuleProvider(ctx, module, AndroidAppCertificateInfoProvider); ok { certificates = append(certificates, dep.Certificate) } else { ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName) @@ -1128,22 +1192,25 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, func collectJniDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool, checkNativeSdkVersion bool, - filter func(parent, child android.Module) bool) ([]jniLib, android.Paths) { + filter func(parent, child android.ModuleProxy) bool) ([]jniLib, android.Paths) { var jniLibs []jniLib var prebuiltJniPackages android.Paths seenModulePaths := make(map[string]bool) - ctx.WalkDeps(func(module android.Module, parent android.Module) bool { + ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool { + if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + return false + } otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) { - if dep, ok := module.(cc.LinkableInterface); ok { + if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok { if filter != nil && !filter(parent, module) { return false } - lib := dep.OutputFile() + lib := dep.OutputFile if lib.Valid() { path := lib.Path() if seenModulePaths[path.String()] { @@ -1151,7 +1218,8 @@ func collectJniDeps(ctx android.ModuleContext, } seenModulePaths[path.String()] = true - if checkNativeSdkVersion && dep.SdkVersion() == "" { + commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + if checkNativeSdkVersion && commonInfo.SdkVersion == "" { ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", otherName) } @@ -1159,11 +1227,11 @@ func collectJniDeps(ctx android.ModuleContext, jniLibs = append(jniLibs, jniLib{ name: ctx.OtherModuleName(module), path: path, - target: module.Target(), - coverageFile: dep.CoverageOutputFile(), - unstrippedFile: dep.UnstrippedOutputFile(), - partition: dep.Partition(), - installPaths: android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles, + target: commonInfo.Target, + coverageFile: dep.CoverageOutputFile, + unstrippedFile: dep.UnstrippedOutputFile, + partition: dep.Partition, + installPaths: android.OtherModuleProviderOrDefault(ctx, module, android.InstallFilesProvider).InstallFiles, }) } else if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{otherName}) @@ -1189,7 +1257,10 @@ func collectJniDeps(ctx android.ModuleContext, func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { ctx.WalkDeps(func(child, parent android.Module) bool { - isExternal := !a.DepIsInSameApex(ctx, child) + // TODO(ccross): Should this use android.DepIsInSameApex? Right now it is applying the android app + // heuristics to every transitive dependency, when it should probably be using the heuristics of the + // immediate parent. + isExternal := !a.GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child)) if am, ok := child.(android.ApexModule); ok { if !do(ctx, parent, am, isExternal) { return false @@ -1205,12 +1276,12 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { } depsInfo := android.DepNameToDepInfoMap{} - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { depName := to.Name() // Skip dependencies that are only available to APEXes; they are developed with updatability // in mind and don't need manual approval. - if to.(android.ApexModule).NotAvailableForPlatform() { + if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform { return true } @@ -1220,18 +1291,9 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { depsInfo[depName] = info } else { toMinSdkVersion := "(no version)" - if m, ok := to.(interface { - MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel - }); ok { - if v := m.MinSdkVersion(ctx); !v.IsNone() { - toMinSdkVersion = v.String() - } - } else if m, ok := to.(interface{ MinSdkVersion() string }); ok { - // TODO(b/175678607) eliminate the use of MinSdkVersion returning - // string - if v := m.MinSdkVersion(); v != "" { - toMinSdkVersion = v - } + if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok && + !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil { + toMinSdkVersion = info.MinSdkVersion.ApiLevel.String() } depsInfo[depName] = android.ApexModuleDepInfo{ To: depName, @@ -1266,11 +1328,19 @@ func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string { return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "") } -func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) { +func (m *AndroidApp) GetDepInSameApexChecker() android.DepInSameApexChecker { + return AppDepInSameApexChecker{} +} + +type AppDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m AppDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + if IsJniDepTag(tag) { return true } - return a.Library.DepIsInSameApex(ctx, dep) + return depIsInSameApex(tag) } func (a *AndroidApp) Privileged() bool { @@ -1388,6 +1458,11 @@ func AndroidAppFactory() android.Module { } } ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties) + + }) + + module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + createInternalRuntimeOverlays(ctx, module.ModuleBase) }) return module @@ -1397,6 +1472,68 @@ func AutogeneratedRroModuleName(ctx android.EarlyModuleContext, moduleName, part return fmt.Sprintf("%s__%s__auto_generated_rro_%s", moduleName, ctx.Config().DeviceProduct(), partition) } +type createModuleContext interface { + android.EarlyModuleContext + CreateModule(android.ModuleFactory, ...interface{}) android.Module +} + +func createInternalRuntimeOverlays(ctx createModuleContext, a android.ModuleBase) { + if !ctx.Config().HasDeviceProduct() { + return + } + // vendor + vendorOverlayProps := struct { + Name *string + Base *string + Vendor *bool + Product_specific *bool + System_ext_specific *bool + Manifest *string + Sdk_version *string + Compile_multilib *string + Enabled proptools.Configurable[bool] + }{ + Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "vendor")), + Base: proptools.StringPtr(a.Name()), + Vendor: proptools.BoolPtr(true), + Product_specific: proptools.BoolPtr(false), + System_ext_specific: proptools.BoolPtr(false), + Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"), + Sdk_version: proptools.StringPtr("current"), + Compile_multilib: proptools.StringPtr("first"), + Enabled: a.EnabledProperty().Clone(), + } + ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &vendorOverlayProps) + + // product + productOverlayProps := struct { + Name *string + Base *string + Vendor *bool + Proprietary *bool + Soc_specific *bool + Product_specific *bool + System_ext_specific *bool + Manifest *string + Sdk_version *string + Compile_multilib *string + Enabled proptools.Configurable[bool] + }{ + Name: proptools.StringPtr(AutogeneratedRroModuleName(ctx, a.Name(), "product")), + Base: proptools.StringPtr(a.Name()), + Vendor: proptools.BoolPtr(false), + Proprietary: proptools.BoolPtr(false), + Soc_specific: proptools.BoolPtr(false), + Product_specific: proptools.BoolPtr(true), + System_ext_specific: proptools.BoolPtr(false), + Manifest: proptools.StringPtr(":" + a.Name() + "{.manifest.xml}"), + Sdk_version: proptools.StringPtr("current"), + Compile_multilib: proptools.StringPtr("first"), + Enabled: a.EnabledProperty().Clone(), + } + ctx.CreateModule(AutogenRuntimeResourceOverlayFactory, &productOverlayProps) +} + // A dictionary of values to be overridden in the manifest. type Manifest_values struct { // Overrides the value of package_name in the manifest @@ -1467,6 +1604,9 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } a.generateAndroidBuildActions(ctx) + for _, c := range a.testProperties.Test_options.Tradefed_options { + configs = append(configs, c) + } for _, module := range a.testProperties.Test_mainline_modules { configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) } @@ -1481,6 +1621,23 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...) a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...) + // Install test deps + if !ctx.Config().KatiEnabled() { + pathInTestCases := android.PathForModuleInstall(ctx, ctx.Module().Name()) + if a.testConfig != nil { + ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig) + } + dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml") + if dynamicConfig.Valid() { + ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path()) + } + testDeps := append(a.data, a.extraTestConfigs...) + for _, data := range android.SortedUniquePaths(testDeps) { + dataPath := android.DataPath{SrcPath: data} + ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath}) + } + } + android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{ TestcaseRelDataFiles: testcaseRel(a.data), OutputFile: a.OutputFile(), @@ -1498,6 +1655,22 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { TopLevelTarget: true, }) + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests") + if a.testConfig != nil { + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.testConfig.String()) + } + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.extraTestConfigs.Strings()...) + if len(a.testProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.testProperties.Test_suites...) + } else { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") + } + + if _, ok := testConfig.(android.WritablePath); ok { + moduleInfoJSON.AutoTestConfig = []string{"true"} + } + moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...) } func testcaseRel(paths android.Paths) []string { @@ -1586,7 +1759,7 @@ func AndroidTestFactory() android.Module { module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.addHostAndDeviceProperties() module.AddProperties( @@ -1637,12 +1810,14 @@ func AndroidTestHelperAppFactory() android.Module { // TODO(b/192032291): Disable by default after auditing downstream usage. module.Module.dexProperties.Optimize.EnabledByDefault = true + module.Module.dexProperties.Optimize.Ignore_library_extends_program = proptools.BoolPtr(true) + module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false) module.Module.properties.Installable = proptools.BoolPtr(true) module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.addHostAndDeviceProperties() module.AddProperties( @@ -1669,6 +1844,12 @@ type AndroidAppCertificateProperties struct { Certificate *string } +type AndroidAppCertificateInfo struct { + Certificate Certificate +} + +var AndroidAppCertificateInfoProvider = blueprint.NewProvider[AndroidAppCertificateInfo]() + // android_app_certificate modules can be referenced by the certificates property of android_app modules to select // the signing key. func AndroidAppCertificateFactory() android.Module { @@ -1684,6 +1865,10 @@ func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleCo Pem: android.PathForModuleSrc(ctx, cert+".x509.pem"), Key: android.PathForModuleSrc(ctx, cert+".pk8"), } + + android.SetProvider(ctx, AndroidAppCertificateInfoProvider, AndroidAppCertificateInfo{ + Certificate: c.Certificate, + }) } type OverrideAndroidApp struct { @@ -1707,6 +1892,10 @@ func OverrideAndroidAppModuleFactory() android.Module { android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon) android.InitOverrideModule(m) + android.AddLoadHookWithPriority(m, func(ctx android.LoadHookContext) { + createInternalRuntimeOverlays(ctx, m.ModuleBase) + }, 1) // Run after soong config load hoook + return m } @@ -1834,7 +2023,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext return clcMap } - ctx.VisitDirectDeps(func(m android.Module) { + ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) { tag, isUsesLibTag := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag) if !isUsesLibTag { return @@ -1842,31 +2031,35 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext dep := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(m)) + javaInfo, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider) + if !ok { + return + } // Skip stub libraries. A dependency on the implementation library has been added earlier, // so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed // from implementation libraries by their name, which is different as it has a suffix. - if comp, ok := m.(SdkLibraryComponentDependency); ok { - if impl := comp.OptionalSdkLibraryImplementation(); impl != nil && *impl != dep { + if comp := javaInfo.SdkLibraryComponentDependencyInfo; comp != nil { + if impl := comp.OptionalSdkLibraryImplementation; impl != nil && *impl != dep { return } } - if lib, ok := m.(UsesLibraryDependency); ok { + if lib := javaInfo.UsesLibraryDependencyInfo; lib != nil { if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok { // Skip java_sdk_library dependencies that provide stubs, but not an implementation. // This will be restricted to optional_uses_libs - if tag == usesLibOptTag && lib.DexJarBuildPath(ctx).PathOrNil() == nil { + if tag == usesLibOptTag && lib.DexJarBuildPath.PathOrNil() == nil { u.shouldDisableDexpreopt = true return } } libName := dep - if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil { - libName = *ulib.ProvidesUsesLib() + if ulib := javaInfo.ProvidesUsesLibInfo; ulib != nil && ulib.ProvidesUsesLib != nil { + libName = *ulib.ProvidesUsesLib } clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, - lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(), - lib.ClassLoaderContexts()) + lib.DexJarBuildPath.PathOrNil(), lib.DexJarInstallPath, + lib.ClassLoaderContexts) } else if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{dep}) } else { diff --git a/java/app_import.go b/java/app_import.go index 8951c7d9c..919266f28 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -43,6 +43,12 @@ var ( Description: "Uncompress embedded JNI libs", }) + stripEmbeddedJniLibsUnusedArchRule = pctx.AndroidStaticRule("strip-embedded-jni-libs-from-unused-arch", blueprint.RuleParams{ + Command: `${config.Zip2ZipCmd} -i $in -o $out -x 'lib/**/*.so' $extraArgs`, + CommandDeps: []string{"${config.Zip2ZipCmd}"}, + Description: "Remove all JNI libs from unused architectures", + }, "extraArgs") + uncompressDexRule = pctx.AndroidStaticRule("uncompress-dex", blueprint.RuleParams{ Command: `if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` + `${config.Zip2ZipCmd} -i $in -o $out -0 'classes*.dex'` + @@ -56,6 +62,18 @@ var ( CommandDeps: []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"}, Description: "Check presigned apk", }, "extraArgs") + + extractApkRule = pctx.AndroidStaticRule("extract-apk", blueprint.RuleParams{ + Command: "unzip -p $in $extract_apk > $out", + Description: "Extract specific sub apk", + }, "extract_apk") + + gzipRule = pctx.AndroidStaticRule("gzip", + blueprint.RuleParams{ + Command: "prebuilts/build-tools/path/linux-x86/gzip -9 -c $in > $out", + CommandDeps: []string{"prebuilts/build-tools/path/linux-x86/gzip"}, + Description: "gzip $out", + }) ) func RegisterAppImportBuildComponents(ctx android.RegistrationContext) { @@ -150,10 +168,19 @@ type AndroidAppImportProperties struct { // the prebuilt is Name() without "prebuilt_" prefix Source_module_name *string + // Whether stripping all libraries from unused architectures. + Strip_unused_jni_arch *bool + // Path to the .prebuilt_info file of the prebuilt app. // In case of mainline modules, the .prebuilt_info file contains the build_id that was used // to generate the prebuilt. Prebuilt_info *string `android:"path"` + + // Path of extracted apk which is extracted from prebuilt apk. Use this extracted to import. + Extract_apk *string + + // Compress the output APK using gzip. Defaults to false. + Compress_apk proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` } func (a *AndroidAppImport) IsInstallable() bool { @@ -278,6 +305,19 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( }) } +func (a *AndroidAppImport) extractSubApk( + ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) { + extractApkPath := *a.properties.Extract_apk + ctx.Build(pctx, android.BuildParams{ + Rule: extractApkRule, + Input: inputPath, + Output: outputPath, + Args: map[string]string{ + "extract_apk": extractApkPath, + }, + }) +} + // Returns whether this module should have the dex file stored uncompressed in the APK. func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool { if ctx.Config().UnbundledBuild() || proptools.Bool(a.properties.Preprocessed) { @@ -292,6 +332,26 @@ func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool { return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter) } +func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch( + ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) { + var wantedJniLibSlice []string + for _, target := range ctx.MultiTargets() { + supported_abis := target.Arch.Abi + for _, arch := range supported_abis { + wantedJniLibSlice = append(wantedJniLibSlice, " -X lib/"+arch+"/*.so") + } + } + wantedJniLibString := strings.Join(wantedJniLibSlice, " ") + ctx.Build(pctx, android.BuildParams{ + Rule: stripEmbeddedJniLibsUnusedArchRule, + Input: inputPath, + Output: outputPath, + Args: map[string]string{ + "extraArgs": wantedJniLibString, + }, + }) +} + func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.generateAndroidBuildActions(ctx) } @@ -336,10 +396,14 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set") } - // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) + if a.properties.Extract_apk != nil { + extract_apk := android.PathForModuleOut(ctx, "extract-apk", ctx.ModuleName()+".apk") + a.extractSubApk(ctx, srcApk, extract_apk) + srcApk = extract_apk + } // TODO: Install or embed JNI libraries @@ -347,6 +411,13 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk") a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed) + // Strip all embedded JNI libs and include only required ones accordingly to the module's compile_multilib + if Bool(a.properties.Strip_unused_jni_arch) { + jnisStripped := android.PathForModuleOut(ctx, "jnis-stripped", ctx.ModuleName()+".apk") + a.stripEmbeddedJniLibsUnusedArch(ctx, jnisUncompressed, jnisStripped) + jnisUncompressed = jnisStripped + } + var pathFragments []string relInstallPath := String(a.properties.Relative_install_path) @@ -366,7 +437,9 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx) a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) - if a.usesLibrary.shouldDisableDexpreopt { + + // Disable Dexpreopt if Compress_apk is true. It follows the build/make/core/app_prebuilt_internal.mk + if a.usesLibrary.shouldDisableDexpreopt || a.properties.Compress_apk.GetOrDefault(ctx, false) { a.dexpreopter.disableDexpreopt() } @@ -385,7 +458,13 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext jnisUncompressed = dexUncompressed } - apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk") + defaultApkFilename := a.BaseModuleName() + if a.properties.Compress_apk.GetOrDefault(ctx, false) { + defaultApkFilename += ".apk.gz" + } else { + defaultApkFilename += ".apk" + } + apkFilename := proptools.StringDefault(a.properties.Filename, defaultApkFilename) // TODO: Handle EXTERNAL @@ -425,7 +504,16 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext a.certificate = PresignedCertificate } - // TODO: Optionally compress the output apk. + if a.properties.Compress_apk.GetOrDefault(ctx, false) { + outputFile := android.PathForModuleOut(ctx, "compressed_apk", apkFilename) + ctx.Build(pctx, android.BuildParams{ + Rule: gzipRule, + Input: a.outputFile, + Output: outputFile, + Description: "Compressing " + a.outputFile.Base(), + }) + a.outputFile = outputFile + } if apexInfo.IsForPlatform() { a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile) @@ -443,6 +531,8 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext ctx.SetOutputFiles([]android.Path{a.outputFile}, "") + buildComplianceMetadata(ctx) + // TODO: androidmk converter jni libs } @@ -538,7 +628,15 @@ func (a *AndroidAppImport) Privileged() bool { return Bool(a.properties.Privileged) } -func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool { +func (m *AndroidAppImport) GetDepInSameApexChecker() android.DepInSameApexChecker { + return AppImportDepInSameApexChecker{} +} + +type AppImportDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m AppImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { // android_app_import might have extra dependencies via uses_libs property. // Don't track the dependency as we don't automatically add those libraries // to the classpath. It should be explicitly added to java_libs property of APEX @@ -556,10 +654,8 @@ func (a *AndroidAppImport) MinSdkVersion(ctx android.EarlyModuleContext) android var _ android.ApexModule = (*AndroidAppImport)(nil) // Implements android.ApexModule -func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { - // Do not check for prebuilts against the min_sdk_version of enclosing APEX - return nil +func (m *AndroidAppImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { @@ -682,9 +778,27 @@ type AndroidTestImport struct { func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.generateAndroidBuildActions(ctx) + a.updateModuleInfoJSON(ctx) + a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) } +func (a *AndroidTestImport) updateModuleInfoJSON(ctx android.ModuleContext) { + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Class = []string{"APPS"} + moduleInfoJSON.CompatibilitySuites = []string{"null-suite"} + if len(a.testProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = a.testProperties.Test_suites + } + moduleInfoJSON.SystemSharedLibs = []string{"none"} + moduleInfoJSON.Tags = []string{"tests"} + moduleInfoJSON.RegisterNameOverride = a.BaseModuleName() + testConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml") + if testConfig.Valid() { + moduleInfoJSON.TestConfig = []string{testConfig.String()} + } +} + func (a *AndroidTestImport) InstallInTestcases() bool { return true } diff --git a/java/app_import_test.go b/java/app_import_test.go index 54a5e7518..2600767c1 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -26,6 +26,7 @@ import ( ) func TestAndroidAppImport(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -37,7 +38,47 @@ func TestAndroidAppImport(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") + + // Check dexpreopt outputs. + if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil || + variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil { + t.Errorf("can't find dexpreopt outputs") + } + + // Check cert signing flag. + signedApk := variant.Output("signed/foo.apk") + signingFlag := signedApk.Args["certificates"] + expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" + if expected != signingFlag { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) + } + rule := variant.Rule("genProvenanceMetaData") + android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String()) + android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String()) + android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"]) + android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"]) +} + +func TestAndroidAppImportWithDefaults(t *testing.T) { + t.Parallel() + ctx, _ := testJava(t, ` + android_app_import { + name: "foo", + defaults: ["foo_defaults"], + } + + java_defaults { + name: "foo_defaults", + apk: "prebuilts/apk/app.apk", + certificate: "platform", + dex_preopt: { + enabled: true, + }, + } + `) + + variant := ctx.ModuleForTests(t, "foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil || @@ -60,6 +101,7 @@ func TestAndroidAppImport(t *testing.T) { } func TestAndroidAppImport_NoDexPreopt(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -71,7 +113,7 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") // Check dexpreopt outputs. They shouldn't exist. if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil || @@ -87,6 +129,7 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) { } func TestAndroidAppImport_Presigned(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -98,7 +141,7 @@ func TestAndroidAppImport_Presigned(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil || @@ -121,6 +164,7 @@ func TestAndroidAppImport_Presigned(t *testing.T) { } func TestAndroidAppImport_SigningLineage(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -137,7 +181,7 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") signedApk := variant.Output("signed/foo.apk") // Check certificates @@ -164,6 +208,7 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) { } func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -178,7 +223,7 @@ func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") signedApk := variant.Output("signed/foo.apk") // Check cert signing lineage flag. @@ -196,6 +241,7 @@ func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) { } func TestAndroidAppImport_DefaultDevCert(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -207,7 +253,7 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") // Check dexpreopt outputs. if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil || @@ -231,6 +277,7 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) { } func TestAndroidAppImport_DpiVariants(t *testing.T) { + t.Parallel() bp := ` android_app_import { name: "foo", @@ -302,7 +349,7 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { }), ).RunTestWithBp(t, bp) - variant := result.ModuleForTests("foo", "android_common") + variant := result.ModuleForTests(t, "foo", "android_common") input := variant.Output("jnis-uncompressed/foo.apk").Input.String() if strings.HasSuffix(input, test.expected) { t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input) @@ -317,6 +364,7 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { } func TestAndroidAppImport_Filename(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app_import { name: "foo", @@ -325,10 +373,25 @@ func TestAndroidAppImport_Filename(t *testing.T) { } android_app_import { + name: "foo_compressed", + apk: "prebuilts/apk/app.apk", + presigned: true, + compress_apk: true, + } + + android_app_import { name: "bar", apk: "prebuilts/apk/app.apk", presigned: true, - filename: "bar_sample.apk" + filename: "bar_sample.apk", + } + + android_app_import { + name: "compressed_bar", + apk: "prebuilts/apk/app.apk", + presigned: true, + filename: "bar_sample.apk", + compress_apk: true, } `) @@ -347,16 +410,30 @@ func TestAndroidAppImport_Filename(t *testing.T) { expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", }, { + name: "foo_compressed", + expected: "foo_compressed.apk.gz", + onDevice: "/system/app/foo_compressed/foo_compressed.apk.gz", + expectedArtifactPath: "prebuilts/apk/app.apk", + expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo_compressed/provenance_metadata.textproto", + }, + { name: "bar", expected: "bar_sample.apk", onDevice: "/system/app/bar/bar_sample.apk", expectedArtifactPath: "prebuilts/apk/app.apk", expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto", }, + { + name: "compressed_bar", + expected: "bar_sample.apk", + onDevice: "/system/app/compressed_bar/bar_sample.apk", + expectedArtifactPath: "prebuilts/apk/app.apk", + expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/compressed_bar/provenance_metadata.textproto", + }, } for _, test := range testCases { - variant := ctx.ModuleForTests(test.name, "android_common") + variant := ctx.ModuleForTests(t, test.name, "android_common") if variant.MaybeOutput(test.expected).Rule == nil { t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs()) } @@ -380,6 +457,7 @@ func TestAndroidAppImport_Filename(t *testing.T) { } func TestAndroidAppImport_ArchVariants(t *testing.T) { + t.Parallel() // The test config's target arch is ARM64. testCases := []struct { name string @@ -505,9 +583,10 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, test.bp) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") if test.expected == "" { if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) { t.Error("module should have been disabled, but wasn't") @@ -530,6 +609,7 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) { } func TestAndroidAppImport_SoongConfigVariables(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -572,6 +652,7 @@ func TestAndroidAppImport_SoongConfigVariables(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( prepareForJavaTest, android.PrepareForTestWithSoongConfigModuleBuildComponents, @@ -584,7 +665,7 @@ func TestAndroidAppImport_SoongConfigVariables(t *testing.T) { }), ).RunTestWithBp(t, test.bp).TestContext - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") if test.expected == "" { if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) { t.Error("module should have been disabled, but wasn't") @@ -607,6 +688,7 @@ func TestAndroidAppImport_SoongConfigVariables(t *testing.T) { } func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app { name: "foo", @@ -622,7 +704,7 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) { } `) - variant := ctx.ModuleForTests("prebuilt_foo", "android_common") + variant := ctx.ModuleForTests(t, "prebuilt_foo", "android_common") a := variant.Module().(*AndroidAppImport) // The prebuilt module should still be enabled and active even if the source-based counterpart // is disabled. @@ -635,6 +717,7 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) { } func TestAndroidAppImport_relativeInstallPath(t *testing.T) { + t.Parallel() bp := ` android_app_import { name: "no_relative_install_path", @@ -664,28 +747,49 @@ func TestAndroidAppImport_relativeInstallPath(t *testing.T) { }{ { name: "no_relative_install_path", - expectedInstallPath: "out/soong/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk", + expectedInstallPath: "out/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk", errorMessage: "Install path is not correct when relative_install_path is missing", }, { name: "relative_install_path", - expectedInstallPath: "out/soong/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk", + expectedInstallPath: "out/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk", errorMessage: "Install path is not correct for app when relative_install_path is present", }, { name: "privileged_relative_install_path", - expectedInstallPath: "out/soong/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk", + expectedInstallPath: "out/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk", errorMessage: "Install path is not correct for privileged app when relative_install_path is present", }, } for _, testCase := range testCases { - ctx, _ := testJava(t, bp) - mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*AndroidAppImport) - android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath) + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + ctx, _ := testJava(t, bp) + mod := ctx.ModuleForTests(t, testCase.name, "android_common").Module().(*AndroidAppImport) + android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath) + }) } } +func TestAndroidAppImport_ExtractApk(t *testing.T) { + t.Parallel() + ctx, _ := testJava(t, ` + android_app_import { + name: "foo", + apk: "prebuilts/apk/app.apk", + certificate: "platform", + extract_apk: "extract_path/sub_app.apk" + } + `) + + variant := ctx.ModuleForTests(t, "foo", "android_common") + extractRuleArgs := variant.Output("extract-apk/foo.apk").BuildParams.Args + if extractRuleArgs["extract_apk"] != "extract_path/sub_app.apk" { + t.Errorf("Unexpected extract apk args: %s", extractRuleArgs["extract_apk"]) + } +} func TestAndroidTestImport(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_test_import { name: "foo", @@ -697,7 +801,7 @@ func TestAndroidTestImport(t *testing.T) { } `) - test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport) + test := ctx.ModuleForTests(t, "foo", "android_common").Module().(*AndroidTestImport) // Check android mks. entries := android.AndroidMkEntriesForTest(t, ctx, test)[0] @@ -714,6 +818,7 @@ func TestAndroidTestImport(t *testing.T) { } func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_test_import { name: "foo", @@ -734,16 +839,16 @@ func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { } `) - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String() if jniRule == android.Cp.String() { - t.Errorf("Unexpected JNI uncompress rule command: " + jniRule) + t.Errorf("Unexpected JNI uncompress rule command: %s", jniRule) } - variant = ctx.ModuleForTests("foo_presigned", "android_common") + variant = ctx.ModuleForTests(t, "foo_presigned", "android_common") jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String() if jniRule != android.Cp.String() { - t.Errorf("Unexpected JNI uncompress rule: " + jniRule) + t.Errorf("Unexpected JNI uncompress rule: %s", jniRule) } if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil { t.Errorf("Presigned test apk should be aligned") @@ -751,6 +856,7 @@ func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { } func TestAndroidTestImport_Preprocessed(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_test_import { name: "foo", @@ -761,10 +867,10 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) { `) apkName := "foo.apk" - variant := ctx.ModuleForTests("foo", "android_common") + variant := ctx.ModuleForTests(t, "foo", "android_common") jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String() if jniRule != android.Cp.String() { - t.Errorf("Unexpected JNI uncompress rule: " + jniRule) + t.Errorf("Unexpected JNI uncompress rule: %s", jniRule) } // Make sure signing and aligning were skipped. @@ -777,9 +883,11 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) { } func TestAndroidAppImport_Preprocessed(t *testing.T) { + t.Parallel() for _, dontUncompressPrivAppDexs := range []bool{false, true} { name := fmt.Sprintf("dontUncompressPrivAppDexs:%t", dontUncompressPrivAppDexs) t.Run(name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -804,10 +912,10 @@ func TestAndroidAppImport_Preprocessed(t *testing.T) { // non-privileged app apkName := "foo.apk" - variant := result.ModuleForTests("foo", "android_common") + variant := result.ModuleForTests(t, "foo", "android_common") outputBuildParams := variant.Output(apkName).BuildParams if outputBuildParams.Rule.String() != android.Cp.String() { - t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String()) + t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String()) } // Make sure compression and aligning were validated. @@ -817,7 +925,7 @@ func TestAndroidAppImport_Preprocessed(t *testing.T) { validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams if validationBuildParams.Rule.String() != checkPresignedApkRule.String() { - t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String()) + t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String()) } expectedScriptArgs := "--preprocessed" @@ -826,10 +934,10 @@ func TestAndroidAppImport_Preprocessed(t *testing.T) { // privileged app apkName = "bar.apk" - variant = result.ModuleForTests("bar", "android_common") + variant = result.ModuleForTests(t, "bar", "android_common") outputBuildParams = variant.Output(apkName).BuildParams if outputBuildParams.Rule.String() != android.Cp.String() { - t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String()) + t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String()) } // Make sure compression and aligning were validated. @@ -839,7 +947,7 @@ func TestAndroidAppImport_Preprocessed(t *testing.T) { validationBuildParams = variant.Output("validated-prebuilt/check.stamp").BuildParams if validationBuildParams.Rule.String() != checkPresignedApkRule.String() { - t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String()) + t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String()) } expectedScriptArgs = "--privileged" @@ -854,6 +962,7 @@ func TestAndroidAppImport_Preprocessed(t *testing.T) { } func TestAndroidTestImport_UncompressDex(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -894,7 +1003,7 @@ func TestAndroidTestImport_UncompressDex(t *testing.T) { }), ).RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") actual := foo.MaybeRule("uncompress-dex").Rule != nil expect := !unbundled @@ -917,6 +1026,7 @@ func TestAndroidTestImport_UncompressDex(t *testing.T) { name := fmt.Sprintf("%s,unbundled:%t,dontUncompressPrivAppDexs:%t", tt.name, unbundled, dontUncompressPrivAppDexs) t.Run(name, func(t *testing.T) { + t.Parallel() test(t, tt.bp, unbundled, dontUncompressPrivAppDexs) }) } @@ -925,6 +1035,7 @@ func TestAndroidTestImport_UncompressDex(t *testing.T) { } func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.PrepareForTestWithAllowMissingDependencies, @@ -936,7 +1047,7 @@ func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) { certificate: ":missing_certificate", }`) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") fooApk := foo.Output("signed/foo.apk") if fooApk.Rule != android.ErrorRule { t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String()) diff --git a/java/app_set_test.go b/java/app_set_test.go index c02b3593b..9b4c44bc9 100644 --- a/java/app_set_test.go +++ b/java/app_set_test.go @@ -24,13 +24,14 @@ import ( ) func TestAndroidAppSet(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` android_app_set { name: "foo", set: "prebuilts/apks/app.apks", prerelease: true, }`) - module := result.ModuleForTests("foo", "android_common") + module := result.ModuleForTests(t, "foo", "android_common") const packedSplitApks = "foo.zip" params := module.Output(packedSplitApks) if params.Rule == nil { @@ -65,6 +66,7 @@ func TestAndroidAppSet(t *testing.T) { } func TestAndroidAppSet_Variants(t *testing.T) { + t.Parallel() bp := ` android_app_set { name: "foo", @@ -113,24 +115,24 @@ func TestAndroidAppSet_Variants(t *testing.T) { } for _, test := range testCases { - ctx := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI - variables.Platform_sdk_version = &test.sdkVersion - }), - android.FixtureModifyConfig(func(config android.Config) { - config.Targets[android.Android] = test.targets - }), - ).RunTestWithBp(t, bp) + t.Run(test.name, func(t *testing.T) { + ctx := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI + variables.Platform_sdk_version = &test.sdkVersion + }), + android.FixtureModifyConfig(func(config android.Config) { + config.Targets[android.Android] = test.targets + }), + ).RunTestWithBp(t, bp) - module := ctx.ModuleForTests("foo", "android_common") - const packedSplitApks = "foo.zip" - params := module.Output(packedSplitApks) - for k, v := range test.expected { - t.Run(test.name, func(t *testing.T) { + module := ctx.ModuleForTests(t, "foo", "android_common") + const packedSplitApks = "foo.zip" + params := module.Output(packedSplitApks) + for k, v := range test.expected { android.AssertStringEquals(t, fmt.Sprintf("arg value for `%s`", k), v, params.Args[k]) - }) - } + } + }) } } diff --git a/java/app_test.go b/java/app_test.go index 3d83ea1dc..4f23f61a4 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -18,6 +18,7 @@ import ( "fmt" "path/filepath" "reflect" + "regexp" "sort" "strings" "testing" @@ -41,6 +42,7 @@ func testApp(t *testing.T, bp string) *android.TestContext { } func TestApp(t *testing.T) { + t.Parallel() resourceFiles := []string{ "res/layout/layout.xml", "res/values/strings.xml", @@ -55,6 +57,7 @@ func TestApp(t *testing.T) { for _, moduleType := range []string{"android_app", "android_library"} { t.Run(moduleType, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, android.FixtureModifyMockFS(func(fs android.MockFS) { @@ -69,14 +72,14 @@ func TestApp(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") var expectedLinkImplicits []string manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml") expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String()) - frameworkRes := result.ModuleForTests("framework-res", "android_common") + frameworkRes := result.ModuleForTests(t, "framework-res", "android_common") expectedLinkImplicits = append(expectedLinkImplicits, frameworkRes.Output("package-res.apk").Output.String()) @@ -93,13 +96,14 @@ func TestApp(t *testing.T) { expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String()) // Check that the link rule uses - res := result.ModuleForTests("foo", "android_common").Output("package-res.apk") + res := result.ModuleForTests(t, "foo", "android_common").Output("package-res.apk") android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings()) }) } } func TestAppSplits(t *testing.T) { + t.Parallel() ctx := testApp(t, ` android_app { name: "foo", @@ -108,7 +112,7 @@ func TestAppSplits(t *testing.T) { sdk_version: "current" }`) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") expectedOutputs := []string{ "out/soong/.intermediates/foo/android_common/foo.apk", @@ -124,6 +128,7 @@ func TestAppSplits(t *testing.T) { } func TestPlatformAPIs(t *testing.T) { + t.Parallel() testJava(t, ` android_app { name: "foo", @@ -158,6 +163,7 @@ func TestPlatformAPIs(t *testing.T) { } func TestAndroidAppLinkType(t *testing.T) { + t.Parallel() testJava(t, ` android_app { name: "foo", @@ -247,6 +253,7 @@ func TestAndroidAppLinkType(t *testing.T) { } func TestUpdatableApps(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -358,6 +365,7 @@ func TestUpdatableApps(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() errorHandler := android.FixtureExpectsNoErrors if test.expectedError != "" { errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError) @@ -372,6 +380,7 @@ func TestUpdatableApps(t *testing.T) { } func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) { + t.Parallel() testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+` android_app { name: "foo", @@ -390,6 +399,7 @@ func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) { } func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { + t.Parallel() testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` android_app { name: "foo", @@ -410,6 +420,7 @@ func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { } func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { + t.Parallel() bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", @@ -437,11 +448,11 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { ctx, _ := testJavaWithFS(t, bp, fs) - inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits + inputs := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits var crtbeginFound, crtendFound bool - expectedCrtBegin := ctx.ModuleForTests("crtbegin_so", + expectedCrtBegin := ctx.ModuleForTests(t, "crtbegin_so", "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output - expectedCrtEnd := ctx.ModuleForTests("crtend_so", + expectedCrtEnd := ctx.ModuleForTests(t, "crtend_so", "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output implicits := []string{} for _, input := range inputs { @@ -465,6 +476,7 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { } func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { + t.Parallel() bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", @@ -486,6 +498,7 @@ func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { } func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) { + t.Parallel() bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", @@ -517,6 +530,7 @@ func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) { } func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -528,7 +542,7 @@ func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) { updatable: true, } `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") + foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer") android.AssertStringDoesContain(t, "com.android.foo: expected manifest fixer to set override-placeholder-version to RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", foo.BuildParams.Args["args"], @@ -537,6 +551,7 @@ func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) { } func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureMergeEnv(map[string]string{ @@ -551,7 +566,7 @@ func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) { updatable: true, } `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") + foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer") android.AssertStringDoesContain(t, "com.android.foo: expected manifest fixer to set override-placeholder-version to 1234", foo.BuildParams.Args["args"], @@ -560,6 +575,7 @@ func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) { } func TestResourceDirs(t *testing.T) { + t.Parallel() testCases := []struct { name string prop string @@ -596,12 +612,13 @@ func TestResourceDirs(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, fs.AddToFixture(), ).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop)) - module := result.ModuleForTests("foo", "android_common") + module := result.ModuleForTests(t, "foo", "android_common") resourceList := module.MaybeOutput("aapt2/res.list") var resources []string @@ -617,6 +634,7 @@ func TestResourceDirs(t *testing.T) { } func TestLibraryAssets(t *testing.T) { + t.Parallel() bp := ` android_app { name: "foo", @@ -711,7 +729,8 @@ func TestLibraryAssets(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - m := ctx.ModuleForTests(test.name, "android_common") + t.Parallel() + m := ctx.ModuleForTests(t, test.name, "android_common") // Check asset flag in aapt2 link flags var aapt2link android.TestingBuildParams @@ -746,6 +765,7 @@ func TestLibraryAssets(t *testing.T) { } func TestAppJavaResources(t *testing.T) { + t.Parallel() bp := ` android_app { name: "foo", @@ -763,7 +783,7 @@ func TestAppJavaResources(t *testing.T) { ctx := testApp(t, bp) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") fooResources := foo.Output("res/foo.jar") fooDexJar := foo.Output("dex-withres/foo.jar") fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar") @@ -781,7 +801,7 @@ func TestAppJavaResources(t *testing.T) { t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g) } - bar := ctx.ModuleForTests("bar", "android_common") + bar := ctx.ModuleForTests(t, "bar", "android_common") barResources := bar.Output("res/bar.jar") barApk := bar.Rule("combineApk") @@ -791,6 +811,7 @@ func TestAppJavaResources(t *testing.T) { } func TestAndroidResourceProcessor(t *testing.T) { + t.Parallel() testCases := []struct { name string appUsesRP bool @@ -1223,6 +1244,7 @@ func TestAndroidResourceProcessor(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() bp := fmt.Sprintf(` android_app { name: "app", @@ -1330,7 +1352,7 @@ func TestAndroidResourceProcessor(t *testing.T) { } getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) { - mod := result.ModuleForTests(moduleName, "android_common") + mod := result.ModuleForTests(t, moduleName, "android_common") resourceListRule := mod.MaybeOutput("aapt2/res.list") overlayListRule := mod.MaybeOutput("aapt2/overlay.list") aaptRule := mod.Rule("aapt2Link") @@ -1419,6 +1441,7 @@ func TestAndroidResourceProcessor(t *testing.T) { } func TestAndroidResourceOverlays(t *testing.T) { + t.Parallel() type moduleAndVariant struct { module string variant string @@ -1615,6 +1638,7 @@ func TestAndroidResourceOverlays(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, fs.AddToFixture(), @@ -1646,7 +1670,7 @@ func TestAndroidResourceOverlays(t *testing.T) { } getResources := func(moduleName, variantName string) (resourceFiles, overlayFiles, rroDirs []string) { - module := result.ModuleForTests(moduleName, variantName) + module := result.ModuleForTests(t, moduleName, variantName) resourceList := module.MaybeOutput("aapt2/res.list") if resourceList.Rule != nil { resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs)) @@ -1705,7 +1729,7 @@ func TestAndroidResourceOverlays(t *testing.T) { } func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) { - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") link := foo.Output("package-res.apk") linkFlags := strings.Split(link.Args["flags"], " ") min := android.IndexList("--min-sdk-version", linkFlags) @@ -1724,6 +1748,7 @@ func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersio } func TestAppSdkVersion(t *testing.T) { + t.Parallel() testCases := []struct { name string sdkVersion string @@ -1791,6 +1816,7 @@ func TestAppSdkVersion(t *testing.T) { for _, moduleType := range []string{"android_app", "android_library"} { for _, test := range testCases { t.Run(moduleType+" "+test.name, func(t *testing.T) { + t.Parallel() platformApiProp := "" if test.platformApis { platformApiProp = "platform_apis: true," @@ -1827,6 +1853,7 @@ func TestAppSdkVersion(t *testing.T) { } func TestVendorAppSdkVersion(t *testing.T) { + t.Parallel() testCases := []struct { name string sdkVersion string @@ -1869,6 +1896,7 @@ func TestVendorAppSdkVersion(t *testing.T) { for _, sdkKind := range []string{"", "system_"} { for _, test := range testCases { t.Run(moduleType+" "+test.name, func(t *testing.T) { + t.Parallel() bp := fmt.Sprintf(`%s { name: "foo", srcs: ["a.java"], @@ -1900,6 +1928,7 @@ func TestVendorAppSdkVersion(t *testing.T) { } func TestJNIABI(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", @@ -1956,7 +1985,8 @@ func TestJNIABI(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - app := ctx.ModuleForTests(test.name, "android_common") + t.Parallel() + app := ctx.ModuleForTests(t, test.name, "android_common") jniLibZip := app.Output("jnilibs.zip") var abis []string args := strings.Fields(jniLibZip.Args["jarArgs"]) @@ -1974,6 +2004,7 @@ func TestJNIABI(t *testing.T) { } func TestAppSdkVersionByPartition(t *testing.T) { + t.Parallel() testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` android_app { name: "foo", @@ -2018,6 +2049,7 @@ func TestAppSdkVersionByPartition(t *testing.T) { } func TestJNIPackaging(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", @@ -2089,7 +2121,8 @@ func TestJNIPackaging(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - app := ctx.ModuleForTests(test.name, "android_common") + t.Parallel() + app := ctx.ModuleForTests(t, test.name, "android_common") jniLibZip := app.MaybeOutput("jnilibs.zip") if g, w := (jniLibZip.Rule != nil), test.packaged; g != w { t.Errorf("expected jni packaged %v, got %v", w, g) @@ -2109,6 +2142,7 @@ func TestJNIPackaging(t *testing.T) { } func TestJNISDK(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", @@ -2170,16 +2204,17 @@ func TestJNISDK(t *testing.T) { {name: "app_vendor", vendorJNI: true}, } - platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). + platformJNI := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_shared"). Output("libjni.so").Output.String() - sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). + sdkJNI := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_sdk_shared"). Output("libjni.so").Output.String() - vendorJNI := ctx.ModuleForTests("libvendorjni", "android_vendor_arm64_armv8-a_shared"). + vendorJNI := ctx.ModuleForTests(t, "libvendorjni", "android_vendor_arm64_armv8-a_shared"). Output("libvendorjni.so").Output.String() for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - app := ctx.ModuleForTests(test.name, "android_common") + t.Parallel() + app := ctx.ModuleForTests(t, test.name, "android_common") jniLibZip := app.MaybeOutput("jnilibs.zip") if len(jniLibZip.Implicits) != 1 { @@ -2204,6 +2239,7 @@ func TestJNISDK(t *testing.T) { } t.Run("jni_uses_platform_apis_error", func(t *testing.T) { + t.Parallel() testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, ` android_test { name: "app_platform", @@ -2214,6 +2250,7 @@ func TestJNISDK(t *testing.T) { }) t.Run("jni_uses_sdk_apis_error", func(t *testing.T) { + t.Parallel() testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, ` android_test { name: "app_sdk", @@ -2226,6 +2263,7 @@ func TestJNISDK(t *testing.T) { } func TestCertificates(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -2363,6 +2401,7 @@ func TestCertificates(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -2378,7 +2417,7 @@ func TestCertificates(t *testing.T) { }), ).RunTestWithBp(t, test.bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") certificate := foo.Module().(*AndroidApp).certificate android.AssertPathRelativeToTopEquals(t, "certificates key", test.expectedCertificate+".pk8", certificate.Key) @@ -2400,6 +2439,7 @@ func TestCertificates(t *testing.T) { } func TestRequestV4SigningFlag(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -2444,11 +2484,12 @@ func TestRequestV4SigningFlag(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, test.bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") signapk := foo.Output("foo.apk") signFlags := signapk.Args["flags"] @@ -2458,6 +2499,7 @@ func TestRequestV4SigningFlag(t *testing.T) { } func TestPackageNameOverride(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -2476,7 +2518,7 @@ func TestPackageNameOverride(t *testing.T) { packageNameOverride: "", expected: []string{ "out/soong/.intermediates/foo/android_common/foo.apk", - "out/soong/target/product/test_device/system/app/foo/foo.apk", + "out/target/product/test_device/system/app/foo/foo.apk", }, }, { @@ -2492,7 +2534,7 @@ func TestPackageNameOverride(t *testing.T) { expected: []string{ // The package apk should be still be the original name for test dependencies. "out/soong/.intermediates/foo/android_common/bar.apk", - "out/soong/target/product/test_device/system/app/bar/bar.apk", + "out/target/product/test_device/system/app/bar/bar.apk", }, }, { @@ -2508,13 +2550,14 @@ func TestPackageNameOverride(t *testing.T) { packageNameOverride: "", expected: []string{ "out/soong/.intermediates/foo/android_common/bar.apk", - "out/soong/target/product/test_device/system/app/bar/bar.apk", + "out/target/product/test_device/system/app/bar/bar.apk", }, }, } for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -2524,7 +2567,7 @@ func TestPackageNameOverride(t *testing.T) { }), ).RunTestWithBp(t, test.bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") outSoongDir := result.Config.SoongOutDir() @@ -2543,6 +2586,7 @@ func TestPackageNameOverride(t *testing.T) { } func TestInstrumentationTargetOverridden(t *testing.T) { + t.Parallel() bp := ` android_app { name: "foo", @@ -2564,7 +2608,7 @@ func TestInstrumentationTargetOverridden(t *testing.T) { }), ).RunTestWithBp(t, bp) - bar := result.ModuleForTests("bar", "android_common") + bar := result.ModuleForTests(t, "bar", "android_common") res := bar.Output("package-res.apk") aapt2Flags := res.Args["flags"] e := "--rename-instrumentation-target-package org.dandroid.bp" @@ -2574,6 +2618,7 @@ func TestInstrumentationTargetOverridden(t *testing.T) { } func TestOverrideAndroidApp(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp( t, ` android_app { @@ -2651,7 +2696,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo", moduleName: "foo", variantName: "android_common", - apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk", + apkPath: "out/target/product/test_device/system/app/foo/foo.apk", certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", certSigningFlags: "", overrides: []string{"qux"}, @@ -2663,7 +2708,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo", moduleName: "bar", variantName: "android_common_bar", - apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk", + apkPath: "out/target/product/test_device/system/app/bar/bar.apk", certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", certSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32", overrides: []string{"qux", "foo"}, @@ -2675,7 +2720,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo", moduleName: "baz", variantName: "android_common_baz", - apkPath: "out/soong/target/product/test_device/system/app/baz/baz.apk", + apkPath: "out/target/product/test_device/system/app/baz/baz.apk", certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", certSigningFlags: "", overrides: []string{"qux", "foo"}, @@ -2687,7 +2732,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo", moduleName: "baz_no_rename_resources", variantName: "android_common_baz_no_rename_resources", - apkPath: "out/soong/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk", + apkPath: "out/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk", certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", certSigningFlags: "", overrides: []string{"qux", "foo"}, @@ -2699,7 +2744,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo_no_rename_resources", moduleName: "baz_base_no_rename_resources", variantName: "android_common_baz_base_no_rename_resources", - apkPath: "out/soong/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk", + apkPath: "out/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk", certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", certSigningFlags: "", overrides: []string{"qux", "foo_no_rename_resources"}, @@ -2711,7 +2756,7 @@ func TestOverrideAndroidApp(t *testing.T) { name: "foo_no_rename_resources", moduleName: "baz_override_base_rename_resources", variantName: "android_common_baz_override_base_rename_resources", - apkPath: "out/soong/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk", + apkPath: "out/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk", certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", certSigningFlags: "", overrides: []string{"qux", "foo_no_rename_resources"}, @@ -2721,7 +2766,7 @@ func TestOverrideAndroidApp(t *testing.T) { }, } for _, expected := range expectedVariants { - variant := result.ModuleForTests(expected.name, expected.variantName) + variant := result.ModuleForTests(t, expected.name, expected.variantName) // Check the final apk name variant.Output(expected.apkPath) @@ -2756,6 +2801,7 @@ func TestOverrideAndroidApp(t *testing.T) { } func TestOverrideAndroidAppOverrides(t *testing.T) { + t.Parallel() ctx, _ := testJava( t, ` android_app { @@ -2805,7 +2851,7 @@ func TestOverrideAndroidAppOverrides(t *testing.T) { }, } for _, expected := range expectedVariants { - variant := ctx.ModuleForTests(expected.name, expected.variantName) + variant := ctx.ModuleForTests(t, expected.name, expected.variantName) // Check if the overrides field values are correctly aggregated. mod := variant.Module().(*AndroidApp) @@ -2814,6 +2860,7 @@ func TestOverrideAndroidAppOverrides(t *testing.T) { } func TestOverrideAndroidAppWithPrebuilt(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp( t, ` android_app { @@ -2836,19 +2883,20 @@ func TestOverrideAndroidAppWithPrebuilt(t *testing.T) { `) // An app that has an override that also has a prebuilt should not be hidden. - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") if foo.Module().IsHideFromMake() { t.Errorf("expected foo to have HideFromMake false") } // An override that also has a prebuilt should be hidden. - barOverride := result.ModuleForTests("foo", "android_common_bar") + barOverride := result.ModuleForTests(t, "foo", "android_common_bar") if !barOverride.Module().IsHideFromMake() { t.Errorf("expected bar override variant of foo to have HideFromMake true") } } func TestOverrideAndroidAppStem(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app { name: "foo", @@ -2888,41 +2936,42 @@ func TestOverrideAndroidAppStem(t *testing.T) { { moduleName: "foo", variantName: "android_common", - apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk", + apkPath: "out/target/product/test_device/system/app/foo/foo.apk", }, { moduleName: "foo", variantName: "android_common_bar", - apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk", + apkPath: "out/target/product/test_device/system/app/bar/bar.apk", }, { moduleName: "foo", variantName: "android_common_baz", - apkPath: "out/soong/target/product/test_device/system/app/baz_stem/baz_stem.apk", + apkPath: "out/target/product/test_device/system/app/baz_stem/baz_stem.apk", }, { moduleName: "foo2", variantName: "android_common", - apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk", + apkPath: "out/target/product/test_device/system/app/foo2_stem/foo2_stem.apk", }, { moduleName: "foo2", variantName: "android_common_bar2", // Note that this may cause the duplicate output error. - apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk", + apkPath: "out/target/product/test_device/system/app/foo2_stem/foo2_stem.apk", }, { moduleName: "foo2", variantName: "android_common_baz2", - apkPath: "out/soong/target/product/test_device/system/app/baz2_stem/baz2_stem.apk", + apkPath: "out/target/product/test_device/system/app/baz2_stem/baz2_stem.apk", }, } { - variant := ctx.ModuleForTests(expected.moduleName, expected.variantName) + variant := ctx.ModuleForTests(t, expected.moduleName, expected.variantName) variant.Output(expected.apkPath) } } func TestOverrideAndroidAppDependency(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app { name: "foo", @@ -2950,14 +2999,14 @@ func TestOverrideAndroidAppDependency(t *testing.T) { `) // Verify baz, which depends on the overridden module foo, has the correct classpath javac arg. - javac := ctx.ModuleForTests("baz", "android_common").Rule("javac") + javac := ctx.ModuleForTests(t, "baz", "android_common").Rule("javac") fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar" if !strings.Contains(javac.Args["classpath"], fooTurbine) { t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine) } // Verify qux, which depends on the overriding module bar, has the correct classpath javac arg. - javac = ctx.ModuleForTests("qux", "android_common").Rule("javac") + javac = ctx.ModuleForTests(t, "qux", "android_common").Rule("javac") barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar" if !strings.Contains(javac.Args["classpath"], barTurbine) { t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine) @@ -3021,10 +3070,10 @@ func TestOverrideAndroidTest(t *testing.T) { }, } for _, expected := range expectedVariants { - variant := ctx.ModuleForTests("foo_test", expected.variantName) + variant := ctx.ModuleForTests(t, "foo_test", expected.variantName) // Check the final apk name - variant.Output("out/soong" + expected.apkPath) + variant.Output("out" + expected.apkPath) // Check if the overrides field values are correctly aggregated. mod := variant.Module().(*AndroidTest) @@ -3112,7 +3161,7 @@ func TestAndroidTest_FixTestConfig(t *testing.T) { } for _, test := range testCases { - variant := ctx.ModuleForTests(test.moduleName, test.variantName) + variant := ctx.ModuleForTests(t, test.moduleName, test.variantName) params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml") if len(test.expectedFlags) > 0 { @@ -3158,6 +3207,7 @@ func TestInstrumentationTargetPrebuilt(t *testing.T) { } func TestStl(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", @@ -3200,7 +3250,8 @@ func TestStl(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - app := ctx.ModuleForTests(test.name, "android_common") + t.Parallel() + app := ctx.ModuleForTests(t, test.name, "android_common") jniLibZip := app.Output("jnilibs.zip") var jnis []string args := strings.Fields(jniLibZip.Args["jarArgs"]) @@ -3377,8 +3428,8 @@ func TestUsesLibraries(t *testing.T) { }), ).RunTestWithBp(t, bp) - app := result.ModuleForTests("app", "android_common") - prebuilt := result.ModuleForTests("prebuilt", "android_common") + app := result.ModuleForTests(t, "app", "android_common") + prebuilt := result.ModuleForTests(t, "prebuilt", "android_common") // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. // These also include explicit `uses_libs`/`optional_uses_libs` entries, as they may be @@ -3430,6 +3481,7 @@ func TestUsesLibraries(t *testing.T) { } func TestDexpreoptBcp(t *testing.T) { + t.Parallel() bp := ` java_sdk_library { name: "foo", @@ -3472,6 +3524,7 @@ func TestDexpreoptBcp(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -3481,7 +3534,7 @@ func TestDexpreoptBcp(t *testing.T) { dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with), ).RunTestWithBp(t, bp) - app := result.ModuleForTests("app", "android_common") + app := result.ModuleForTests(t, "app", "android_common") cmd := app.Rule("dexpreopt").RuleParams.Command bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp) @@ -3490,6 +3543,7 @@ func TestDexpreoptBcp(t *testing.T) { } func TestCodelessApp(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -3554,9 +3608,10 @@ func TestCodelessApp(t *testing.T) { for _, test := range testCases { t.Run(test.name, func(t *testing.T) { + t.Parallel() ctx := testApp(t, test.bp) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode { t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs) @@ -3566,6 +3621,7 @@ func TestCodelessApp(t *testing.T) { } func TestUncompressDex(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -3653,7 +3709,7 @@ func TestUncompressDex(t *testing.T) { }), ).RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") dex := foo.Rule("r8") uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0") aligned := foo.MaybeRule("zipalign").Rule != nil @@ -3665,10 +3721,13 @@ func TestUncompressDex(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + t.Parallel() t.Run("platform", func(t *testing.T) { + t.Parallel() test(t, tt.bp, tt.uncompressedPlatform, false) }) t.Run("unbundled", func(t *testing.T) { + t.Parallel() test(t, tt.bp, tt.uncompressedUnbundled, true) }) }) @@ -3690,6 +3749,7 @@ func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string } func TestExportedProguardFlagFiles(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` android_app { name: "foo", @@ -3735,7 +3795,7 @@ func TestExportedProguardFlagFiles(t *testing.T) { `) - m := ctx.ModuleForTests("foo", "android_common") + m := ctx.ModuleForTests(t, "foo", "android_common") r8 := m.Rule("java.r8") implicits := r8.Implicits.RelativeToTop().Strings() android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg") @@ -3751,6 +3811,7 @@ func TestExportedProguardFlagFiles(t *testing.T) { } func TestTargetSdkVersionManifestFixer(t *testing.T) { + t.Parallel() platform_sdk_codename := "Tiramisu" platform_sdk_version := 33 testCases := []struct { @@ -3803,43 +3864,47 @@ func TestTargetSdkVersionManifestFixer(t *testing.T) { }, } for _, testCase := range testCases { - targetSdkVersionTemplate := "" - if testCase.targetSdkVersionInBp != "" { - targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp) - } - bp := fmt.Sprintf(` + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + targetSdkVersionTemplate := "" + if testCase.targetSdkVersionInBp != "" { + targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp) + } + bp := fmt.Sprintf(` android_app { name: "foo", sdk_version: "current", %s } `, targetSdkVersionTemplate) - fixture := android.GroupFixturePreparers( - prepareForJavaTest, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - if testCase.platformSdkFinal { - variables.Platform_sdk_final = proptools.BoolPtr(true) - } - // explicitly set platform_sdk_codename to make the test deterministic - variables.Platform_sdk_codename = &platform_sdk_codename - variables.Platform_sdk_version = &platform_sdk_version - variables.Platform_version_active_codenames = []string{platform_sdk_codename} - // create a non-empty list if unbundledBuild==true - if testCase.unbundledBuild { - variables.Unbundled_build_apps = []string{"apex_a", "apex_b"} - } - }), - ) + fixture := android.GroupFixturePreparers( + prepareForJavaTest, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + if testCase.platformSdkFinal { + variables.Platform_sdk_final = proptools.BoolPtr(true) + } + // explicitly set platform_sdk_codename to make the test deterministic + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_version_active_codenames = []string{platform_sdk_codename} + // create a non-empty list if unbundledBuild==true + if testCase.unbundledBuild { + variables.Unbundled_build_apps = []string{"apex_a", "apex_b"} + } + }), + ) - result := fixture.RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + result := fixture.RunTestWithBp(t, bp) + foo := result.ModuleForTests(t, "foo", "android_common") - manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + }) } } func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) { + t.Parallel() platform_sdk_codename := "Tiramisu" platform_sdk_version := 33 testCases := []struct { @@ -3895,11 +3960,13 @@ func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) { }, } for _, testCase := range testCases { - targetSdkVersionTemplate := "" - if testCase.targetSdkVersionInBp != nil { - targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp) - } - bp := fmt.Sprintf(` + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + targetSdkVersionTemplate := "" + if testCase.targetSdkVersionInBp != nil { + targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp) + } + bp := fmt.Sprintf(` android_app { name: "foo", sdk_version: "current", @@ -3910,30 +3977,32 @@ func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) { } `, targetSdkVersionTemplate, testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable - fixture := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - android.PrepareForTestWithAllowMissingDependencies, - android.PrepareForTestWithAndroidMk, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - // explicitly set following platform variables to make the test deterministic - variables.Platform_sdk_final = &testCase.platform_sdk_final - variables.Platform_sdk_version = &platform_sdk_version - variables.Platform_sdk_codename = &platform_sdk_codename - variables.Platform_version_active_codenames = []string{platform_sdk_codename} - variables.Unbundled_build = proptools.BoolPtr(true) - variables.Unbundled_build_apps = []string{"sampleModule"} - }), - ) + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Platform_version_active_codenames = []string{platform_sdk_codename} + variables.Unbundled_build = proptools.BoolPtr(true) + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) - result := fixture.RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + result := fixture.RunTestWithBp(t, bp) + foo := result.ModuleForTests(t, "foo", "android_common") - manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected) + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected) + }) } } func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { + t.Parallel() platform_sdk_codename := "Tiramisu" platform_sdk_version := 33 testCases := []struct { @@ -3978,8 +4047,10 @@ func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { }, } for _, testCase := range testCases { - errExpected := testCase.expectedError != "" - bp := fmt.Sprintf(` + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + errExpected := testCase.expectedError != "" + bp := fmt.Sprintf(` android_app { name: "foo", enforce_default_target_sdk_version: %t, @@ -3990,35 +4061,37 @@ func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { } `, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable) - fixture := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - android.PrepareForTestWithAllowMissingDependencies, - android.PrepareForTestWithAndroidMk, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - // explicitly set following platform variables to make the test deterministic - variables.Platform_sdk_final = &testCase.platform_sdk_final - variables.Platform_sdk_version = &platform_sdk_version - variables.Platform_sdk_codename = &platform_sdk_codename - variables.Unbundled_build = proptools.BoolPtr(true) - variables.Unbundled_build_apps = []string{"sampleModule"} - }), - ) + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build = proptools.BoolPtr(true) + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) - errorHandler := android.FixtureExpectsNoErrors - if errExpected { - errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) - } - result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) + errorHandler := android.FixtureExpectsNoErrors + if errExpected { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) + } + result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) - if !errExpected { - foo := result.ModuleForTests("foo", "android_common") - manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) - } + if !errExpected { + foo := result.ModuleForTests(t, "foo", "android_common") + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + } + }) } } func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) { + t.Parallel() platform_sdk_codename := "Tiramisu" platform_sdk_version := 33 testCases := []struct { @@ -4051,8 +4124,10 @@ func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) { }, } for _, testCase := range testCases { - errExpected := testCase.expectedError != "" - bp := fmt.Sprintf(` + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + errExpected := testCase.expectedError != "" + bp := fmt.Sprintf(` android_test { name: "foo", enforce_default_target_sdk_version: %t, @@ -4061,35 +4136,37 @@ func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) { } `, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp) - fixture := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - android.PrepareForTestWithAllowMissingDependencies, - android.PrepareForTestWithAndroidMk, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - // explicitly set following platform variables to make the test deterministic - variables.Platform_sdk_final = &testCase.platform_sdk_final - variables.Platform_sdk_version = &platform_sdk_version - variables.Platform_sdk_codename = &platform_sdk_codename - variables.Unbundled_build = proptools.BoolPtr(true) - variables.Unbundled_build_apps = []string{"sampleModule"} - }), - ) + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build = proptools.BoolPtr(true) + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) - errorHandler := android.FixtureExpectsNoErrors - if errExpected { - errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) - } - result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) + errorHandler := android.FixtureExpectsNoErrors + if errExpected { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) + } + result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) - if !errExpected { - foo := result.ModuleForTests("foo", "android_common") - manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) - } + if !errExpected { + foo := result.ModuleForTests(t, "foo", "android_common") + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + } + }) } } func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.PrepareForTestWithAllowMissingDependencies, @@ -4110,7 +4187,7 @@ func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) { sdk_version: "current", }`) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") fooApk := foo.Output("foo.apk") if fooApk.Rule != android.ErrorRule { t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String()) @@ -4119,6 +4196,7 @@ func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) { } func TestAppIncludesJniPackages(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -4181,7 +4259,8 @@ func TestAppIncludesJniPackages(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - app := ctx.ModuleForTests(tc.name, "android_common") + t.Parallel() + app := ctx.ModuleForTests(t, tc.name, "android_common") outputFile := "jnilibs.zip" jniOutputLibZip := app.MaybeOutput(outputFile) @@ -4205,6 +4284,7 @@ func TestAppIncludesJniPackages(t *testing.T) { } func TestTargetSdkVersionMtsTests(t *testing.T) { + t.Parallel() platformSdkCodename := "Tiramisu" android_test := "android_test" android_test_helper_app := "android_test_helper_app" @@ -4260,14 +4340,18 @@ func TestTargetSdkVersionMtsTests(t *testing.T) { }), ) for _, testCase := range testCases { - result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites)) - mytest := result.ModuleForTests("mytest", "android_common") - manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + t.Run(testCase.desc, func(t *testing.T) { + t.Parallel() + result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites)) + mytest := result.ModuleForTests(t, "mytest", "android_common") + manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + }) } } func TestPrivappAllowlist(t *testing.T) { + t.Parallel() testJavaError(t, "privileged must be set in order to use privapp_allowlist", ` android_app { name: "foo", @@ -4293,8 +4377,8 @@ func TestPrivappAllowlist(t *testing.T) { } `, ) - app := result.ModuleForTests("foo", "android_common") - overrideApp := result.ModuleForTests("foo", "android_common_bar") + app := result.ModuleForTests(t, "foo", "android_common") + overrideApp := result.ModuleForTests(t, "foo", "android_common_bar") // verify that privapp allowlist is created for override apps overrideApp.Output("out/soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml") @@ -4305,11 +4389,12 @@ func TestPrivappAllowlist(t *testing.T) { } // verify that permissions are copied to device - app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml") - overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml") + app.Output("out/target/product/test_device/system/etc/permissions/foo.xml") + overrideApp.Output("out/target/product/test_device/system/etc/permissions/bar.xml") } func TestPrivappAllowlistAndroidMk(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.PrepareForTestWithAndroidMk, @@ -4330,8 +4415,8 @@ func TestPrivappAllowlistAndroidMk(t *testing.T) { } `, ) - baseApp := result.ModuleForTests("foo", "android_common") - overrideApp := result.ModuleForTests("foo", "android_common_bar") + baseApp := result.ModuleForTests(t, "foo", "android_common") + overrideApp := result.ModuleForTests(t, "foo", "android_common_bar") baseAndroidApp := baseApp.Module().(*AndroidApp) baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0] @@ -4389,6 +4474,7 @@ func TestPrivappAllowlistAndroidMk(t *testing.T) { } func TestAppFlagsPackages(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( prepareForJavaTest, android.FixtureMergeMockFs( @@ -4426,7 +4512,7 @@ func TestAppFlagsPackages(t *testing.T) { } `) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") // android_app module depends on aconfig_declarations listed in flags_packages android.AssertBoolEquals(t, "foo expected to depend on bar", true, @@ -4453,6 +4539,7 @@ func TestAppFlagsPackages(t *testing.T) { } func TestAppFlagsPackagesPropagation(t *testing.T) { + t.Parallel() ctx := testApp(t, ` aconfig_declarations { name: "foo", @@ -4510,7 +4597,7 @@ func TestAppFlagsPackagesPropagation(t *testing.T) { } `) - bazApp := ctx.ModuleForTests("baz_app", "android_common") + bazApp := ctx.ModuleForTests(t, "baz_app", "android_common") // android_app module depends on aconfig_declarations listed in flags_packages // and that of static libs, but not libs @@ -4530,6 +4617,7 @@ func TestAppFlagsPackagesPropagation(t *testing.T) { // Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation. func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) { + t.Parallel() bp := ` java_sdk_library_import { name: "sdklib_noimpl", @@ -4547,7 +4635,7 @@ func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) { } ` result := prepareForJavaTest.RunTestWithBp(t, bp) - dexpreopt := result.ModuleForTests("app", "android_common").MaybeRule("dexpreopt").Rule + dexpreopt := result.ModuleForTests(t, "app", "android_common").MaybeRule("dexpreopt").Rule android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil) } @@ -4589,7 +4677,77 @@ func TestTestOnlyApp(t *testing.T) { assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel) } +func TestTestConfigTemplate(t *testing.T) { + t.Parallel() + ctx := android.GroupFixturePreparers( + prepareForJavaTest, + ).RunTestWithBp(t, ` + android_test { + name: "android-test", + test_config_template: "AndroidTestTemplate.xml", + test_options: { + tradefed_options: [ + { + name: "name1", + key: "key1", + value: "value1", + }, + { + name: "name2", + key: "key2", + value: "value2", + }, + ], + test_runner_options: [ + { + name: "name3", + key: "key3", + value: "value3", + }, + { + name: "name4", + key: "key4", + value: "value4", + }, + ], + }, + } + `) + type option struct { + name string + key string + value string + } + re := regexp.MustCompile(`<option name="(.*)" key="(.*)" value="(.*)" />`) + parse_options := func(optionsString string) []option { + lines := strings.Split(optionsString, `\n`) + var ret []option + for _, l := range lines { + sm := re.FindStringSubmatch(l) + if sm == nil { + continue + } + ret = append(ret, option{sm[1], sm[2], sm[3]}) + } + return ret + } + rule := ctx.ModuleForTests(t, "android-test", "android_common").Rule("autogenInstrumentationTest") + android.AssertSameArray(t, "extraConfigs mismatch", + []option{ + {"name1", "key1", "value1"}, + {"name2", "key2", "value2"}, + }, + parse_options(rule.Args["extraConfigs"])) + android.AssertSameArray(t, "extraTestRunnerConfigs mismatch", + []option{ + {"name3", "key3", "value3"}, + {"name4", "key4", "value4"}, + }, + parse_options(rule.Args["extraTestRunnerConfigs"])) +} + func TestAppStem(t *testing.T) { + t.Parallel() ctx := testApp(t, ` android_app { name: "foo", @@ -4598,7 +4756,7 @@ func TestAppStem(t *testing.T) { sdk_version: "current", }`) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") outputs := fmt.Sprint(foo.AllOutputs()) if !strings.Contains(outputs, "foo-new.apk") { @@ -4607,6 +4765,7 @@ func TestAppStem(t *testing.T) { } func TestAppMinSdkVersionOverride(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -4623,8 +4782,8 @@ func TestAppMinSdkVersionOverride(t *testing.T) { min_sdk_version: "33", } `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") - fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer") + foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer") + fooOverride := result.ModuleForTests(t, "com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer") android.AssertStringDoesContain(t, "com.android.foo: expected manifest fixer to set minSdkVersion to T", @@ -4640,6 +4799,7 @@ func TestAppMinSdkVersionOverride(t *testing.T) { } func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -4650,7 +4810,7 @@ func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) { min_sdk_version: "31", } `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") + foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer") android.AssertStringDoesNotContain(t, "com.android.foo: expected manifest fixer to not set override-placeholder-version", foo.BuildParams.Args["args"], @@ -4659,6 +4819,7 @@ func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) { } func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureMergeEnv(map[string]string{ @@ -4672,7 +4833,7 @@ func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) { min_sdk_version: "31", } `) - foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer") + foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer") android.AssertStringDoesNotContain(t, "com.android.foo: expected manifest fixer to not set override-placeholder-version", foo.BuildParams.Args["args"], @@ -4681,6 +4842,7 @@ func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) { } func TestResourcesWithFlagDirectories(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureMergeMockFs(android.MockFS{ @@ -4699,7 +4861,7 @@ func TestResourcesWithFlagDirectories(t *testing.T) { ], } `) - fooModule := result.ModuleForTests("foo", "android_common") + fooModule := result.ModuleForTests(t, "foo", "android_common") compileOutputPaths := fooModule.Rule("aapt2Compile").Outputs.Strings() android.AssertStringListContains( @@ -4727,3 +4889,153 @@ func TestResourcesWithFlagDirectories(t *testing.T) { "out/soong/.intermediates/foo/android_common/aapt2/res/values_strings.(test.package.flag1).arsc.flat", ) } + +func TestAutogeneratedStaticRro(t *testing.T) { + t.Parallel() + bp := ` +android_app { + name: "foo", + srcs: ["foo.java"], + platform_apis: true, +} +override_android_app { + name: "override_foo", + base: "foo", +} +` + testCases := []struct { + desc string + preparer android.FixturePreparer + overlayApkExpected bool + }{ + { + desc: "No DEVICE_PACKAGE_OVERLAYS, no overlay .apk file", + overlayApkExpected: false, + }, + { + desc: "DEVICE_PACKAGE_OVERLAYS exists, but the directory is empty", + overlayApkExpected: false, + preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.DeviceResourceOverlays = []string{"device/company/test_product"} + }), + }, + { + desc: "DEVICE_PACKAGE_OVERLAYS exists, directory is non-empty, but does not contain a matching resource dir", + overlayApkExpected: false, + preparer: android.GroupFixturePreparers( + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.DeviceResourceOverlays = []string{"device/company/test_product"} + }), + android.MockFS{ + "res/foo.xml": nil, + "device/company/test_product/different_res/foo.xml": nil, // different dir + }.AddToFixture(), + ), + }, + { + desc: "DEVICE_PACKAGE_OVERLAYS and the directory contain a matching resource dir", + overlayApkExpected: true, + preparer: android.GroupFixturePreparers( + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.DeviceResourceOverlays = []string{"device/company/test_product"} + }), + android.MockFS{ + "res/foo.xml": nil, + "device/company/test_product/res/foo.xml": nil, + }.AddToFixture(), + ), + }, + } + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.EnforceRROTargets = []string{"*"} + }), + android.OptionalFixturePreparer(tc.preparer), + ).RunTestWithBp(t, bp) + vendorOverlayApk := result.ModuleForTests(t, "foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("foo__test_product__auto_generated_rro_vendor.apk") + android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, vendorOverlayApk.Rule != nil) + overrideVendorOverlayApk := result.ModuleForTests(t, "override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("override_foo__test_product__auto_generated_rro_vendor.apk") + android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil) + }) + } +} + +func TestNoAutogeneratedStaticRroForDisabledOverrideApps(t *testing.T) { + t.Parallel() + bp := ` +soong_config_module_type { + name: "my_custom_override_android_app", + module_type: "override_android_app", + config_namespace: "my_namespace", + value_variables: ["my_app_enabled"], + properties: ["enabled"], +} +soong_config_bool_variable { + name: "my_app_enabled", +} +android_app { + name: "foo", + srcs: ["foo.java"], + platform_apis: true, +} +my_custom_override_android_app { + name: "override_foo", + base: "foo", + soong_config_variables: { + my_app_enabled: { + enabled: true, + conditions_default: { + enabled: false + }, + }, + } +} +` + testCases := []struct { + desc string + preparer android.FixturePreparer + overlayApkExpected bool + }{ + { + desc: "my_app_enabled is empty", + overlayApkExpected: false, + }, + { + desc: "my_app_enabled is true", + overlayApkExpected: true, + preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "my_namespace": { + "my_app_enabled": "true", + }, + } + }), + }, + } + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithSoongConfigModuleBuildComponents, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.EnforceRROTargets = []string{"*"} + }), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.DeviceResourceOverlays = []string{"device/company/test_product"} + }), + android.MockFS{ + "res/foo.xml": nil, + "device/company/test_product/res/foo.xml": nil, + }.AddToFixture(), + android.OptionalFixturePreparer(tc.preparer), + ).RunTestWithBp(t, bp) + overrideVendorOverlayApk := result.ModuleForTests(t, "override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").Module().(*AutogenRuntimeResourceOverlay) + android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.exportPackage != nil) + }) + } +} diff --git a/java/base.go b/java/base.go index c0ac4ab99..21ad73f84 100644 --- a/java/base.go +++ b/java/base.go @@ -60,6 +60,9 @@ type CommonProperties struct { // This is most useful in the arch/multilib variants to remove non-common files Exclude_srcs []string `android:"path,arch_variant"` + // list of Kotlin source files that should excluded from the list of common_srcs. + Exclude_common_srcs []string `android:"path,arch_variant"` + // list of directories containing Java resources Java_resource_dirs []string `android:"arch_variant"` @@ -87,6 +90,10 @@ type CommonProperties struct { // list of module-specific flags that will be used for kotlinc compiles Kotlincflags []string `android:"arch_variant"` + // Kotlin language version to target. Currently only 1.9 and 2 are supported. + // See kotlinc's `-language-version` flag. + Kotlin_lang_version *string + // list of java libraries that will be in the classpath Libs []string `android:"arch_variant"` @@ -106,6 +113,10 @@ type CommonProperties struct { // if not blank, used as prefix to generate repackage rule Jarjar_prefix *string + // Number of shards for jarjar. It needs to be an integer represented as a string. + // TODO(b/383559945) change it to int, once Configurable supports the type. + Jarjar_shards proptools.Configurable[string] + // If not blank, set the java version passed to javac as -source and -target Java_version *string @@ -362,13 +373,13 @@ func (e *embeddableInModuleAndImport) initModuleAndImport(module android.Module) e.initSdkLibraryComponent(module) } -// Module/Import's DepIsInSameApex(...) delegates to this method. +// Module/Import's OutgoingDepIsInSameApex(...) delegates to this method. // -// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with +// This cannot implement OutgoingDepIsInSameApex(...) directly as that leads to ambiguity with // the one provided by ApexModuleBase. -func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { +func depIsInSameApex(tag blueprint.DependencyTag) bool { // dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + if tag == staticLibTag { return true } return false @@ -645,14 +656,17 @@ func (j *Module) checkSdkVersions(ctx android.ModuleContext) { // Make sure this module doesn't statically link to modules with lower-ranked SDK link type. // See rank() for details. - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(module) - switch module.(type) { - // TODO(satayev): cover other types as well, e.g. imports - case *Library, *AndroidLibrary: + _, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider) + _, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider) + _, isJavaAconfigLibrary := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider) + // Exclude java_aconfig_library modules to maintain consistency with existing behavior. + if (isJavaLibrary && !isJavaAconfigLibrary) || isAndroidLibrary { + // TODO(satayev): cover other types as well, e.g. imports switch tag { case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag: - j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag)) + j.checkSdkLinkType(ctx, module) } } }) @@ -835,13 +849,18 @@ func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLev } func (j *Module) AvailableFor(what string) bool { - if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) { + return android.CheckAvailableForApex(what, j.ApexAvailableFor()) +} + +func (j *Module) ApexAvailableFor() []string { + list := j.ApexModuleBase.ApexAvailable() + if Bool(j.deviceProperties.Hostdex) { // Exception: for hostdex: true libraries, the platform variant is created // even if it's not marked as available to platform. In that case, the platform // variant is used only for the hostdex and not installed to the device. - return true + list = append(list, android.AvailableToPlatform) } - return j.ApexModuleBase.AvailableFor(what) + return android.FirstUniqueStrings(list) } func (j *Module) staticLibs(ctx android.BaseModuleContext) []string { @@ -922,7 +941,7 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { if j.useCompose(ctx) { ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, - "androidx.compose.compiler_compiler-hosted-plugin") + "kotlin-compose-compiler-plugin") } } @@ -1141,7 +1160,7 @@ func (j *Module) addGeneratedSrcJars(path android.Path) { j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path) } -func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) { +func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) *JavaInfo { // Auto-propagating jarjar rules jarjarProviderData := j.collectJarJarRules(ctx) if jarjarProviderData != nil { @@ -1182,7 +1201,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags) } - kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil) + kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, j.properties.Exclude_common_srcs) if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 { ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files") } @@ -1229,7 +1248,6 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...) uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...) j.uniqueSrcFiles = uniqueSrcFiles - android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()}) // We don't currently run annotation processors in turbine, which means we can't use turbine // generated header jars when an annotation processor that generates API is enabled. One @@ -1265,7 +1283,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath localHeaderJars, combinedHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraCombinedJars) - combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine") + combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false) if jarjared { localHeaderJars = android.Paths{combinedHeaderJarFile} transitiveStaticLibsHeaderJars = nil @@ -1276,7 +1294,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath transitiveStaticLibsHeaderJars = nil } if ctx.Failed() { - return + return nil } j.headerJarFile = combinedHeaderJarFile @@ -1291,7 +1309,8 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ctx.CheckbuildFile(j.headerJarFile) } - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + j.outputFile = j.headerJarFile + return &JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), LocalHeaderJars: localHeaderJars, TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars), @@ -1304,10 +1323,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath StubsLinkType: j.stubsLinkType, AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles, SdkVersion: j.SdkVersion(ctx), - }) - - j.outputFile = j.headerJarFile - return + } } if srcFiles.HasExt(".kt") { @@ -1320,6 +1336,26 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath kotlincFlags := j.properties.Kotlincflags CheckKotlincFlags(ctx, kotlincFlags) + // Available kotlin versions can be found at + // https://github.com/JetBrains/kotlin/blob/master/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt#L560 + // in the `LanguageVersion` class. + // For now, avoid targeting language versions directly, as we'd like to kee our source + // code version aligned as much as possible. Ideally, after defaulting to "2", we + // can remove the "1.9" option entirely, or at least make it emit a warning. + kotlin_default_lang_version := "1.9" + if build_flag_lang_version, ok := ctx.Config().GetBuildFlag("RELEASE_KOTLIN_LANG_VERSION"); ok { + kotlin_default_lang_version = build_flag_lang_version + } + kotlin_lang_version := proptools.StringDefault(j.properties.Kotlin_lang_version, kotlin_default_lang_version) + switch kotlin_lang_version { + case "1.9": + kotlincFlags = append(kotlincFlags, "-language-version 1.9") + case "2": + kotlincFlags = append(kotlincFlags, "-Xsuppress-version-warnings", "-Xconsistent-data-class-copy-visibility") + default: + ctx.PropertyErrorf("kotlin_lang_version", "Must be one of `1.9` or `2`") + } + // Workaround for KT-46512 kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class") @@ -1364,7 +1400,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName) j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) if ctx.Failed() { - return + return nil } kotlinJarPath, _ := j.repackageFlagsIfNecessary(ctx, kotlinJar, jarName, "kotlinc") @@ -1401,7 +1437,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath shardingHeaderJars = localHeaderJars var jarjared bool - j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine") + j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false) if jarjared { // jarjar modifies transitive static dependencies, use the combined header jar and drop the transitive // static libs header jars. @@ -1434,20 +1470,27 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath // build. flags = enableErrorproneFlags(flags) } else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil { - // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create - // a new jar file just for compiling with the errorprone compiler to. - // This is because we don't want to cause the java files to get completely - // rebuilt every time the state of the RUN_ERROR_PRONE variable changes. - // We also don't want to run this if errorprone is enabled by default for - // this module, or else we could have duplicated errorprone messages. - errorproneFlags := enableErrorproneFlags(flags) - errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) - errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar") - - transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil, - "errorprone", "errorprone") - - extraJarDeps = append(extraJarDeps, errorprone) + if ctx.Config().RunErrorProneInline() { + // On CI, we're not going to toggle back/forth between errorprone and non-errorprone + // builds, so it's faster if we don't compile the module twice and instead always + // compile the module with errorprone. + flags = enableErrorproneFlags(flags) + } else { + // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create + // a new jar file just for compiling with the errorprone compiler to. + // This is because we don't want to cause the java files to get completely + // rebuilt every time the state of the RUN_ERROR_PRONE variable changes. + // We also don't want to run this if errorprone is enabled by default for + // this module, or else we could have duplicated errorprone messages. + errorproneFlags := enableErrorproneFlags(flags) + errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) + errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar") + + transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil, + "errorprone", "errorprone") + + extraJarDeps = append(extraJarDeps, errorprone) + } } if enableSharding { @@ -1484,7 +1527,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath localImplementationJars = append(localImplementationJars, classes) } if ctx.Failed() { - return + return nil } } @@ -1524,7 +1567,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath resourceJar := android.PathForModuleOut(ctx, "res", jarName) TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps) if ctx.Failed() { - return + return nil } localResourceJars = append(localResourceJars, resourceJar) } @@ -1628,7 +1671,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath } // jarjar implementation jar if necessary - jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "") + jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "", true) if jarjarred { localImplementationJars = android.Paths{jarjarFile} completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil) @@ -1637,7 +1680,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath // jarjar resource jar if necessary if combinedResourceJar != nil { - resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource") + resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource", false) combinedResourceJar = resourceJarJarFile if jarjarred { localResourceJars = android.Paths{resourceJarJarFile} @@ -1646,7 +1689,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath } if ctx.Failed() { - return + return nil } if j.ravenizer.enabled { @@ -1710,7 +1753,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages) if ctx.Failed() { - return + return nil } } @@ -1735,7 +1778,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath // enforce syntax check to jacoco filters for any build (http://b/183622051) specs := j.jacocoModuleToZipCommand(ctx) if ctx.Failed() { - return + return nil } completeStaticLibsImplementationJarsToCombine := completeStaticLibsImplementationJars @@ -1803,7 +1846,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath } dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params) if ctx.Failed() { - return + return nil } // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt. @@ -1862,7 +1905,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath } if ctx.Failed() { - return + return nil } } @@ -1909,7 +1952,10 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ctx.CheckbuildFile(j.headerJarFile) } - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource + j.outputFile = outputFile.WithoutRel() + + return &JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), RepackagedHeaderJars: android.PathsIfNonNil(repackagedHeaderJarFile), @@ -1934,10 +1980,8 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath StubsLinkType: j.stubsLinkType, AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles, SdkVersion: j.SdkVersion(ctx), - }) - - // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource - j.outputFile = outputFile.WithoutRel() + OutputFile: j.outputFile, + } } func (j *Module) useCompose(ctx android.BaseModuleContext) bool { @@ -1945,7 +1989,7 @@ func (j *Module) useCompose(ctx android.BaseModuleContext) bool { } func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []depset.DepSet[android.Path]) { - ctx.VisitDirectDeps(func(m android.Module) { + ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) { depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider) depTag := ctx.OtherModuleDependencyTag(m) @@ -2041,7 +2085,9 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) { } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") { ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, only use internal compiler for consistency.", flag) - } else if inList(flag, config.KotlincIllegalFlags) { + } else if slices.ContainsFunc(config.KotlincIllegalFlags, func(f string) bool { + return strings.HasPrefix(flag, f) + }) { ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag) } else if flag == "-include-runtime" { ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag) @@ -2116,7 +2162,7 @@ func (j *providesTransitiveHeaderJarsForR8) collectTransitiveHeaderJarsForR8(ctx directStaticLibs := android.Paths{} transitiveLibs := []depset.DepSet[android.Path]{} transitiveStaticLibs := []depset.DepSet[android.Path]{} - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { // don't add deps of the prebuilt version of the same library if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) { return @@ -2184,6 +2230,8 @@ func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { if j.expandJarjarRules != nil { dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) + } + if j.headerJarFile != nil { // Add the header jar so that the rdeps can be resolved to the repackaged classes. dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String()) } @@ -2202,29 +2250,33 @@ func (j *Module) CompilerDeps() []string { func (j *Module) hasCode(ctx android.ModuleContext) bool { srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) - return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0 + return len(srcFiles) > 0 || len(ctx.GetDirectDepsProxyWithTag(staticLibTag)) > 0 } // Implements android.ApexModule -func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - return j.depIsInSameApex(ctx, dep) +func (m *Module) GetDepInSameApexChecker() android.DepInSameApexChecker { + return JavaDepInSameApexChecker{} +} + +type JavaDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m JavaDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + return depIsInSameApex(tag) } // Implements android.ApexModule -func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { +func (j *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { sdkVersionSpec := j.SdkVersion(ctx) minSdkVersion := j.MinSdkVersion(ctx) - if !minSdkVersion.Specified() { - return fmt.Errorf("min_sdk_version is not specified") - } + // If the module is compiling against core (via sdk_version), skip comparison check. if sdkVersionSpec.Kind == android.SdkCore { - return nil - } - if minSdkVersion.GreaterThan(sdkVersion) { - return fmt.Errorf("newer SDK(%v)", minSdkVersion) + return android.MinApiLevel } - return nil + + return minSdkVersion } func (j *Module) Stem() string { @@ -2240,7 +2292,7 @@ func (j *Module) JacocoReportClassesFile() android.Path { func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) { var fromDeps []depset.DepSet[android.Path] - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(module) if tag == staticLibTag { if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { @@ -2359,7 +2411,7 @@ func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret // checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than // this module's. See the comment on rank() for details and an example. func (j *Module) checkSdkLinkType( - ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) { + ctx android.ModuleContext, dep android.ModuleProxy) { if ctx.Host() { return } @@ -2368,7 +2420,12 @@ func (j *Module) checkSdkLinkType( if stubs { return } - depLinkType, _ := dep.getSdkLinkType(ctx, ctx.OtherModuleName(dep)) + info, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider) + if !ok || info.ModuleWithSdkDepInfo == nil { + panic(fmt.Errorf("dependency doesn't have ModuleWithSdkDepInfo: %v", dep)) + } + + depLinkType := info.ModuleWithSdkDepInfo.SdkLinkType if myLinkType.rank() < depLinkType.rank() { ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+ @@ -2393,7 +2450,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { var transitiveStaticJarsImplementationLibs []depset.DepSet[android.Path] var transitiveStaticJarsResourceLibs []depset.DepSet[android.Path] - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2427,7 +2484,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...) transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars) case sdkLibTag, libTag, instrumentationForTag: - if _, ok := module.(*Plugin); ok { + if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok { ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName) } deps.classpath = append(deps.classpath, dep.HeaderJars...) @@ -2445,7 +2502,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...) transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars) case staticLibTag: - if _, ok := module.(*Plugin); ok { + if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok { ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName) } deps.classpath = append(deps.classpath, dep.HeaderJars...) @@ -2465,40 +2522,40 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, dep.TransitiveStaticLibsImplementationJars) transitiveStaticJarsResourceLibs = append(transitiveStaticJarsResourceLibs, dep.TransitiveStaticLibsResourceJars) case pluginTag: - if plugin, ok := module.(*Plugin); ok { - if plugin.pluginProperties.Processor_class != nil { - addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class) + if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok { + if plugin.ProcessorClass != nil { + addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.ProcessorClass) } else { addPlugins(&deps, dep.ImplementationAndResourcesJars) } // Turbine doesn't run annotation processors, so any module that uses an // annotation processor that generates API is incompatible with the turbine // optimization. - deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api) + deps.disableTurbine = deps.disableTurbine || plugin.GeneratesApi } else { ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName) } case errorpronePluginTag: - if _, ok := module.(*Plugin); ok { + if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok { deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...) } else { ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName) } case exportedPluginTag: - if plugin, ok := module.(*Plugin); ok { + if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok { j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...) - if plugin.pluginProperties.Processor_class != nil { - j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class) + if plugin.ProcessorClass != nil { + j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.ProcessorClass) } // Turbine doesn't run annotation processors, so any module that uses an // annotation processor that generates API is incompatible with the turbine // optimization. - j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api) + j.exportedDisableTurbine = plugin.GeneratesApi } else { ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName) } case kotlinPluginTag: - if _, ok := module.(*KotlinPlugin); ok { + if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok { deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...) } else { ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName) @@ -2510,21 +2567,21 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { JavaInfo: dep, }) } - } else if dep, ok := module.(android.SourceFileProducer); ok { + } else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok { switch tag { case sdkLibTag, libTag: - checkProducesJars(ctx, dep) - deps.classpath = append(deps.classpath, dep.Srcs()...) - deps.dexClasspath = append(deps.classpath, dep.Srcs()...) + checkProducesJars(ctx, dep, module) + deps.classpath = append(deps.classpath, dep.Srcs...) + deps.dexClasspath = append(deps.classpath, dep.Srcs...) transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, - depset.New(depset.PREORDER, dep.Srcs(), nil)) + depset.New(depset.PREORDER, dep.Srcs, nil)) case staticLibTag: - checkProducesJars(ctx, dep) - deps.classpath = append(deps.classpath, dep.Srcs()...) - deps.staticJars = append(deps.staticJars, dep.Srcs()...) - deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...) + checkProducesJars(ctx, dep, module) + deps.classpath = append(deps.classpath, dep.Srcs...) + deps.staticJars = append(deps.staticJars, dep.Srcs...) + deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs...) - depHeaderJars := depset.New(depset.PREORDER, dep.Srcs(), nil) + depHeaderJars := depset.New(depset.PREORDER, dep.Srcs, nil) transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJars) transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, depHeaderJars) transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, depHeaderJars) @@ -2625,18 +2682,11 @@ const ( RenameUseExclude ) -type RenameUseElement struct { - DepName string - RenameUse DependencyUse - Why string // token for determining where in the logic the decision was made. -} - type JarJarProviderData struct { // Mapping of class names: original --> renamed. If the value is "", the class will be // renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has // attribute). Rdeps of that module will inherit the renaming. - Rename map[string]string - RenameUse []RenameUseElement + Rename map[string]string } func (this JarJarProviderData) GetDebugString() string { @@ -2707,7 +2757,7 @@ func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProvid module := ctx.Module() moduleName := module.Name() - ctx.VisitDirectDeps(func(m android.Module) { + ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(m) // This logic mirrors that in (*Module).collectDeps above. There are several places // where we explicitly return RenameUseExclude, even though it is the default, to @@ -2715,93 +2765,89 @@ func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProvid // // Note well: there are probably cases that are getting to the unconditional return // and are therefore wrong. - shouldIncludeRenames := func() (DependencyUse, string) { + shouldIncludeRenames := func() DependencyUse { if moduleName == m.Name() { - return RenameUseInclude, "name" // If we have the same module name, include the renames. + return RenameUseInclude // If we have the same module name, include the renames. } if sc, ok := module.(android.SdkContext); ok { if ctx.Device() { sdkDep := decodeSdkDep(ctx, sc) if !sdkDep.invalidVersion && sdkDep.useFiles { - return RenameUseExclude, "useFiles" + return RenameUseExclude } } } if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag { - return RenameUseExclude, "tags" + return RenameUseExclude } if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok { switch tag { case sdkLibTag, libTag: - return RenameUseExclude, "sdklibdep" // matches collectDeps() + return RenameUseExclude // matches collectDeps() } - return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps() + return RenameUseInvalid // dep is not used in collectDeps() } else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { switch ji.StubsLinkType { case Stubs: - return RenameUseExclude, "info" + return RenameUseExclude case Implementation: - return RenameUseInclude, "info" + return RenameUseInclude default: //fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m) // Fall through to the heuristic logic. } - switch reflect.TypeOf(m).String() { - case "*java.GeneratedJavaLibraryModule": + if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok { // Probably a java_aconfig_library module. - // TODO: make this check better. - return RenameUseInclude, "reflect" + return RenameUseInclude } switch tag { case bootClasspathTag: - return RenameUseExclude, "tagswitch" + return RenameUseExclude case sdkLibTag, libTag, instrumentationForTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude case java9LibTag: - return RenameUseExclude, "tagswitch" + return RenameUseExclude case staticLibTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude case pluginTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude case errorpronePluginTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude case exportedPluginTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude case kotlinPluginTag: - return RenameUseInclude, "tagswitch" + return RenameUseInclude default: - return RenameUseExclude, "tagswitch" + return RenameUseExclude } - } else if _, ok := m.(android.SourceFileProducer); ok { + } else if _, ok := android.OtherModuleProvider(ctx, m, android.SourceFilesInfoProvider); ok { switch tag { case sdkLibTag, libTag, staticLibTag: - return RenameUseInclude, "srcfile" + return RenameUseInclude default: - return RenameUseExclude, "srcfile" + return RenameUseExclude } } else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok { - return RenameUseInclude, "aconfig_declarations_group" + return RenameUseInclude } else { switch tag { case bootClasspathTag: - return RenameUseExclude, "else" + return RenameUseExclude case systemModulesTag: - return RenameUseInclude, "else" + return RenameUseInclude } } // If we got here, choose the safer option, which may lead to a build failure, rather // than runtime failures on the device. - return RenameUseExclude, "end" + return RenameUseExclude } if result == nil { result = &JarJarProviderData{ - Rename: make(map[string]string), - RenameUse: make([]RenameUseElement, 0), + Rename: make(map[string]string), } } - how, why := shouldIncludeRenames() - result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why}) + how := shouldIncludeRenames() if how != RenameUseInclude { // Nothing to merge. return @@ -2906,14 +2952,18 @@ func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProvi // Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map // to "" won't be in this list because they shouldn't be renamed yet. func getJarJarRuleText(provider *JarJarProviderData) string { - result := "" + result := strings.Builder{} for _, orig := range android.SortedKeys(provider.Rename) { renamed := provider.Rename[orig] if renamed != "" { - result += "rule " + orig + " " + renamed + "\n" + result.WriteString("rule ") + result.WriteString(orig) + result.WriteString(" ") + result.WriteString(renamed) + result.WriteString("\n") } } - return result + return result.String() } // Repackage the flags if the jarjar rule txt for the flags is generated @@ -2926,12 +2976,23 @@ func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile and return repackagedJarjarFile, true } -func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string) (android.Path, bool) { +func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string, useShards bool) (android.Path, bool) { if j.expandJarjarRules == nil { return infile, false } jarjarFile := android.PathForModuleOut(ctx, "jarjar", info, jarName) - TransformJarJar(ctx, jarjarFile, infile, j.expandJarjarRules) + + totalShards := 1 + if useShards { + totalShardsStr := j.properties.Jarjar_shards.GetOrDefault(ctx, "1") + ts, err := strconv.Atoi(totalShardsStr) + if err != nil { + ctx.PropertyErrorf("jarjar_shards", "jarjar_shards must be an integer represented as a string") + return infile, false + } + totalShards = ts + } + TransformJarJarWithShards(ctx, jarjarFile, infile, j.expandJarjarRules, totalShards) return jarjarFile, true } diff --git a/java/bootclasspath.go b/java/bootclasspath.go index 3413cf350..98fb417d0 100644 --- a/java/bootclasspath.go +++ b/java/bootclasspath.go @@ -15,6 +15,8 @@ package java import ( + "fmt" + "android/soong/android" "github.com/google/blueprint" @@ -23,36 +25,9 @@ import ( // Contains code that is common to both platform_bootclasspath and bootclasspath_fragment. -func init() { - registerBootclasspathBuildComponents(android.InitRegistrationContext) -} - -func registerBootclasspathBuildComponents(ctx android.RegistrationContext) { - ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator) - }) -} - -// BootclasspathDepsMutator is the interface that a module must implement if it wants to add -// dependencies onto APEX specific variants of bootclasspath fragments or bootclasspath contents. -type BootclasspathDepsMutator interface { - // BootclasspathDepsMutator implementations should add dependencies using - // addDependencyOntoApexModulePair and addDependencyOntoApexVariants. - BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) -} - -// bootclasspathDepsMutator is called during the final deps phase after all APEX variants have -// been created so can add dependencies onto specific APEX variants of modules. -func bootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { - m := ctx.Module() - if p, ok := m.(BootclasspathDepsMutator); ok { - p.BootclasspathDepsMutator(ctx) - } -} - // addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of // the module as specified in the ApexVariantReference list. -func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tag blueprint.DependencyTag) { +func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tagType bootclasspathDependencyTagType) { for i, ref := range refs { apex := proptools.StringDefault(ref.Apex, "platform") @@ -62,7 +37,7 @@ func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyN } name := proptools.String(ref.Module) - addDependencyOntoApexModulePair(ctx, apex, name, tag) + addDependencyOntoApexModulePair(ctx, apex, name, tagType) } } @@ -75,68 +50,154 @@ func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyN // module when both source and prebuilt modules are available. // // Use gatherApexModulePairDepsWithTag to retrieve the dependencies. -func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) { - var variations []blueprint.Variation - if !android.IsConfiguredJarForPlatform(apex) { - // Pick the correct apex variant. - variations = []blueprint.Variation{ - {Mutator: "apex", Variation: apex}, - } +func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tagType bootclasspathDependencyTagType) { + tag := bootclasspathDependencyTag{ + typ: tagType, } - target := ctx.Module().Target() - variations = append(variations, target.Variations()...) - - addedDep := false - if ctx.OtherModuleDependencyVariantExists(variations, name) { - ctx.AddFarVariationDependencies(variations, tag, name) - addedDep = true + if android.IsConfiguredJarForPlatform(apex) { + // Platform variant, add a direct dependency. + ctx.AddFarVariationDependencies(target.Variations(), tag, name) + } else { + // A module in an apex. Dependencies can't be added directly onto an apex variation, as that would + // require constructing a full ApexInfo configuration, which can't be predicted here. Add a dependency + // on the apex instead, and annotate the dependency tag with the desired module in the apex. + tag.moduleInApex = name + ctx.AddFarVariationDependencies(target.Variations(), tag, apex) } - // Add a dependency on the prebuilt module if it exists. - prebuiltName := android.PrebuiltNameFromSource(name) - if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) { - ctx.AddVariationDependencies(variations, tag, prebuiltName) - addedDep = true +} + +// gatherFragments collects fragments that are direct dependencies of this module, as well as +// any fragments in apexes via the dependency on the apex. It returns a list of the fragment +// modules and map from apex name to the fragment in that apex. +func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[string]android.Module) { + var fragments []android.Module + + type fragmentInApex struct { + module string + apex string } - // If no appropriate variant existing for this, so no dependency could be added, then it is an - // error, unless missing dependencies are allowed. The simplest way to handle that is to add a - // dependency that will not be satisfied and the default behavior will handle it. - if !addedDep { - // Add dependency on the unprefixed (i.e. source or renamed prebuilt) module which we know does - // not exist. The resulting error message will contain useful information about the available - // variants. - reportMissingVariationDependency(ctx, variations, name) - - // Add dependency on the missing prefixed prebuilt variant too if a module with that name exists - // so that information about its available variants will be reported too. - if ctx.OtherModuleExists(prebuiltName) { - reportMissingVariationDependency(ctx, variations, prebuiltName) + var fragmentsInApexes []fragmentInApex + + // Find any direct dependencies, as well as a list of the modules in apexes. + ctx.VisitDirectDeps(func(module android.Module) { + t := ctx.OtherModuleDependencyTag(module) + if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment { + if bcpTag.moduleInApex != "" { + fragmentsInApexes = append(fragmentsInApexes, fragmentInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)}) + } else { + fragments = append(fragments, module) + } } - } -} + }) -// reportMissingVariationDependency intentionally adds a dependency on a missing variation in order -// to generate an appropriate error message with information about the available variations. -func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) { - ctx.AddFarVariationDependencies(variations, nil, name) + fragmentsMap := make(map[string]android.Module) + for _, fragmentInApex := range fragmentsInApexes { + var found android.Module + // Find a desired module in an apex. + ctx.WalkDeps(func(child, parent android.Module) bool { + t := ctx.OtherModuleDependencyTag(child) + if parent == ctx.Module() { + if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment && ctx.OtherModuleName(child) == fragmentInApex.apex { + // This is the dependency from this module to the apex, recurse into it. + return true + } + } else if android.IsDontReplaceSourceWithPrebuiltTag(t) { + return false + } else if t == android.PrebuiltDepTag { + return false + } else if IsBootclasspathFragmentContentDepTag(t) { + return false + } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == fragmentInApex.module { + // This is the desired module inside the apex. + if found != nil && child != found { + panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s", + fragmentInApex.module, fragmentInApex.apex, found, child)) + } + found = child + } + return false + }) + if found != nil { + if existing, exists := fragmentsMap[fragmentInApex.apex]; exists { + ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", fragmentInApex.apex, fragmentInApex.module, existing) + } else { + fragmentsMap[fragmentInApex.apex] = found + fragments = append(fragments, found) + } + } else if !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf("failed to find fragment %q in apex %q\n", + fragmentInApex.module, fragmentInApex.apex) + } + } + return fragments, fragmentsMap } // gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was // added by addDependencyOntoApexModulePair. -func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module { +func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) { var modules []android.Module - isActiveModulePred := func(module android.Module) bool { - return isActiveModule(ctx, module) + modulesToApex := make(map[android.Module]string) + + type moduleInApex struct { + module string + apex string } - ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) { + + var modulesInApexes []moduleInApex + + ctx.VisitDirectDeps(func(module android.Module) { t := ctx.OtherModuleDependencyTag(module) - if t == tag { - modules = append(modules, module) + if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType { + if bcpTag.moduleInApex != "" { + modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)}) + } else { + modules = append(modules, module) + } } }) - return modules + + for _, moduleInApex := range modulesInApexes { + var found android.Module + ctx.WalkDeps(func(child, parent android.Module) bool { + t := ctx.OtherModuleDependencyTag(child) + if parent == ctx.Module() { + if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex { + // recurse into the apex + return true + } + } else if tagType != fragment && android.IsFragmentInApexTag(t) { + return true + } else if android.IsDontReplaceSourceWithPrebuiltTag(t) { + return false + } else if t == android.PrebuiltDepTag { + return false + } else if IsBootclasspathFragmentContentDepTag(t) { + return false + } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module { + if found != nil && child != found { + panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s", + moduleInApex.module, moduleInApex.apex, found, child)) + } + found = child + } + return false + }) + if found != nil { + modules = append(modules, found) + if existing, exists := modulesToApex[found]; exists && existing != moduleInApex.apex { + ctx.ModuleErrorf("module %s is in two apexes, %s and %s", moduleInApex.module, existing, moduleInApex.apex) + } else { + modulesToApex[found] = moduleInApex.apex + } + } else if !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf("failed to find module %q in apex %q\n", + moduleInApex.module, moduleInApex.apex) + } + } + return modules, modulesToApex } // ApexVariantReference specifies a particular apex variant of a module. @@ -165,7 +226,7 @@ type BootclasspathFragmentsDepsProperties struct { // addDependenciesOntoFragments adds dependencies to the fragments specified in this properties // structure. func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx android.BottomUpMutatorContext) { - addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, bootclasspathFragmentDepTag) + addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, fragment) } // bootclasspathDependencyTag defines dependencies from/to bootclasspath_fragment, @@ -174,23 +235,38 @@ func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx type bootclasspathDependencyTag struct { blueprint.BaseDependencyTag - name string + typ bootclasspathDependencyTagType + + // moduleInApex is set to the name of the desired module when this dependency points + // to the apex that the modules is contained in. + moduleInApex string } +type bootclasspathDependencyTagType int + +const ( + // The tag used for dependencies onto bootclasspath_fragments. + fragment bootclasspathDependencyTagType = iota + // The tag used for dependencies onto platform_bootclasspath. + platform + dexpreoptBootJar + artBootJar + platformBootJar + apexBootJar +) + func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() { } +func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation { + return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency} +} + // Dependencies that use the bootclasspathDependencyTag instances are only added after all the // visibility checking has been done so this has no functional effect. However, it does make it // clear that visibility is not being enforced on these tags. var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{} -// The tag used for dependencies onto bootclasspath_fragments. -var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"} - -// The tag used for dependencies onto platform_bootclasspath. -var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"} - // BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the // bootclasspath that are nested within the main BootclasspathAPIProperties. type BootclasspathNestedAPIProperties struct { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 375a1aaf1..7a3c21e44 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -89,6 +89,19 @@ func (b bootclasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex // The tag used for the dependency between the bootclasspath_fragment module and its contents. var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{} +type moduleInFragmentDependencyTag struct { + blueprint.DependencyTag +} + +func (m moduleInFragmentDependencyTag) ExcludeFromVisibilityEnforcement() { +} + +// moduleInFragmentDepTag is added alongside bootclasspathFragmentContentDependencyTag, +// but doesn't set ReplaceSourceWithPrebuilt. It is used to find modules in the fragment +// by traversing from the apex to the fragment to the module, which prevents having to +// construct a dependency on the apex variant of the fragment directly. +var moduleInFragmentDepTag = moduleInFragmentDependencyTag{} + var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag var _ android.SdkMemberDependencyTag = bootclasspathFragmentContentDepTag @@ -239,6 +252,8 @@ type BootclasspathFragmentModule struct { profilePathErr error } +var _ android.ApexModule = (*BootclasspathFragmentModule)(nil) + // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt // bootclasspath fragment modules. type commonBootclasspathFragment interface { @@ -290,6 +305,10 @@ func testBootclasspathFragmentFactory() android.Module { return m } +func (m *BootclasspathFragmentModule) UniqueApexVariations() bool { + return true +} + func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.ModuleContext) { contents := m.properties.Contents.GetOrDefault(ctx, nil) if len(contents) == 0 { @@ -393,11 +412,17 @@ func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string return i.profileInstallPathInApex } -func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - tag := ctx.OtherModuleDependencyTag(dep) +func (m *BootclasspathFragmentModule) GetDepInSameApexChecker() android.DepInSameApexChecker { + return BootclasspathFragmentDepInSameApexChecker{} +} + +type BootclasspathFragmentDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} +func (b BootclasspathFragmentDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { // If the module is a default module, do not check the tag - if _, ok := dep.(*Defaults); ok { + if tag == android.DefaultsDepTag { return true } if IsBootclasspathFragmentContentDepTag(tag) { @@ -408,17 +433,31 @@ func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleCont // Cross-cutting metadata dependencies are metadata. return false } + if tag == moduleInFragmentDepTag { + return true + } // Dependency to the bootclasspath fragment of another apex // e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment - if tag == bootclasspathFragmentDepTag { + if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment { + return false + } + if tag == moduleInFragmentDepTag { return false - } - panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag))) + if tag == dexpreopt.Dex2oatDepTag { + return false + } + if tag == android.PrebuiltDepTag { + return false + } + if _, ok := tag.(hiddenAPIStubsDependencyTag); ok { + return false + } + panic(fmt.Errorf("boot_image module should not have a dependency tag %s", android.PrettyPrintTag(tag))) } -func (b *BootclasspathFragmentModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { - return nil +func (m *BootclasspathFragmentModule) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } // ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a @@ -456,24 +495,24 @@ func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorCon } } - if !dexpreopt.IsDex2oatNeeded(ctx) { - return + if dexpreopt.IsDex2oatNeeded(ctx) { + // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The + // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). + dexpreopt.RegisterToolDeps(ctx) } - // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The - // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). - dexpreopt.RegisterToolDeps(ctx) - // Add a dependency to `all_apex_contributions` to determine if prebuilts are active. // If prebuilts are active, `contents` validation on the source bootclasspath fragment should be disabled. if _, isPrebuiltModule := ctx.Module().(*PrebuiltBootclasspathFragmentModule); !isPrebuiltModule { ctx.AddDependency(b, android.AcDepTag, "all_apex_contributions") } -} -func (b *BootclasspathFragmentModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { // Add dependencies on all the fragments. b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx) + + for _, name := range b.properties.Contents.GetOrDefault(ctx, nil) { + ctx.AddDependency(ctx.Module(), moduleInFragmentDepTag, name) + } } func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -496,7 +535,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo } }) - fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) + fragments, _ := gatherFragments(ctx) // Perform hidden API processing. hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) @@ -529,19 +568,18 @@ func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseMod } // Bootclasspath fragment modules that are for the platform do not produce boot related files. - apexInfos, _ := android.ModuleProvider(ctx, android.AllApexInfoProvider) - if apexInfos == nil { + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + if apexInfo.IsForPlatform() { return "" } - for _, apexInfo := range apexInfos.ApexInfos { - for _, apex := range apexInfo.InApexVariants { - if isProfileProviderApex(ctx, apex) { - return apex + for _, config := range genBootImageConfigs(ctx) { + if config.profileProviderModule == b.BaseModuleName() { + if len(config.profileImports) > 0 { + return config.profileImports[0] } } } - return "" } @@ -605,7 +643,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) if android.IsModulePrebuilt(ctx.Module()) { // prebuilt bcpf. the validation of this will be done at the top-level apex providerClasspathFragmentValidationInfoProvider(ctx, unknown) - } else if !disableSourceApexVariant(ctx) { + } else if !disableSourceApexVariant(ctx) && android.IsModulePreferred(ctx.Module()) { // source bcpf, and prebuilt apex are not selected. ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) } @@ -1141,6 +1179,13 @@ func prebuiltBootclasspathFragmentFactory() android.Module { android.InitPrebuiltModule(m, &[]string{"placeholder"}) android.InitApexModule(m) android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(m) + + m.SetDefaultableHook(func(mctx android.DefaultableHookContext) { + if mctx.Config().AlwaysUsePrebuiltSdks() { + m.prebuilt.ForcePrefer() + } + }) return m } diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 3aa1258a3..87b853c56 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -31,6 +31,7 @@ var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( ) func TestBootclasspathFragment_UnknownImageName(t *testing.T) { + t.Parallel() prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qimage_name: unknown image name "unknown", expected "art"\E`)). @@ -50,6 +51,7 @@ func TestBootclasspathFragment_UnknownImageName(t *testing.T) { } func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) { + t.Parallel() prepareForTestWithBootclasspathFragment. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\Qimage_name: unknown image name "unknown", expected "art"\E`)). @@ -68,6 +70,7 @@ func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) { } func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"), @@ -99,6 +102,7 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T } func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"), @@ -131,6 +135,7 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin } func TestBootclasspathFragment_Coverage(t *testing.T) { + t.Parallel() prepareWithBp := android.FixtureWithRootAndroidBp(` bootclasspath_fragment { name: "myfragment", @@ -204,11 +209,13 @@ func TestBootclasspathFragment_Coverage(t *testing.T) { ) t.Run("without coverage", func(t *testing.T) { + t.Parallel() result := preparer.RunTest(t) checkContents(t, result, "mybootlib") }) t.Run("with coverage", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithFrameworkJacocoInstrumentation, preparer, @@ -364,7 +371,7 @@ func TestFromTextWidestApiScope(t *testing.T) { } `) - fragment := result.ModuleForTests("myfragment", "android_common") + fragment := result.ModuleForTests(t, "myfragment", "android_common") dependencyStubDexFlag := "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.test_module_lib/android_common/dex/android-non-updatable.stubs.test_module_lib.jar" stubFlagsCommand := fragment.Output("modular-hiddenapi/stub-flags.csv").RuleParams.Command android.AssertStringDoesContain(t, @@ -472,7 +479,7 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { // Make sure that the signature-patterns.csv is passed all the appropriate package properties // from the bootclasspath_fragment and its contents. - fragment := result.ModuleForTests("mybootclasspathfragment", "android_common") + fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common") rule := fragment.Output("modular-hiddenapi/signature-patterns.csv") expectedCommand := strings.Join([]string{ "--split-package newlibrary", diff --git a/java/builder.go b/java/builder.go index 895ddb6f9..ade978450 100644 --- a/java/builder.go +++ b/java/builder.go @@ -46,6 +46,7 @@ var ( `mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + `(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` + + `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` + `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` + `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` + `$processorpath $processor $javacFlags $bootClasspath $classpath ` + @@ -55,8 +56,10 @@ var ( `$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` + `if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` + `if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` + + `if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` + `rm -rf "$srcJarDir" "$outDir"`, CommandDeps: []string{ + "${config.FindInputDeltaCmd}", "${config.JavacCmd}", "${config.SoongZipCmd}", "${config.ZipSyncCmd}", @@ -165,7 +168,7 @@ var ( "${config.JavaCmd}", }, Rspfile: "$out.rsp", - RspfileContent: "$in", + RspfileContent: "$in_newline", Restat: true, }, &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"}, @@ -223,6 +226,12 @@ var ( }, "jarArgs") + extractR8Rules = pctx.AndroidStaticRule("extractR8Rules", + blueprint.RuleParams{ + Command: `${config.ExtractR8RulesCmd} --rules-output $out --include-origin-comments $in`, + CommandDeps: []string{"${config.ExtractR8RulesCmd}"}, + }) + jarjar = pctx.AndroidStaticRule("jarjar", blueprint.RuleParams{ Command: "" + @@ -235,12 +244,12 @@ var ( // for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes // avoids adding new hiddenapis after jarjar'ing. " -DremoveAndroidCompatAnnotations=true" + - " -jar ${config.JarjarCmd} process $rulesFile $in $out && " + + " -jar ${config.JarjarCmd} process $rulesFile $in $out $total_shards $shard_index && " + // Turn a missing output file into a ninja error `[ -e ${out} ] || (echo "Missing output file"; exit 1)`, CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"}, }, - "rulesFile") + "rulesFile", "total_shards", "shard_index") packageCheck = pctx.AndroidStaticRule("packageCheck", blueprint.RuleParams{ @@ -314,6 +323,13 @@ var ( Command: `${keep-flagged-apis} ${in} > ${out}`, CommandDeps: []string{"${keep-flagged-apis}"}, }) + + generateApiXMLRule = pctx.AndroidStaticRule("generateApiXMLRule", + blueprint.RuleParams{ + Command: `${config.JavaCmd} ${config.JavaVmFlags} -Xmx4g -jar ${config.MetalavaJar} jar-to-jdiff ${in} ${out}`, + CommandDeps: []string{"${config.JavaCmd}", "${config.MetalavaJar}"}, + Description: "Converting API file to XML", + }) ) func init() { @@ -456,9 +472,10 @@ func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string, const srcJarArgsLimit = 32 * 1024 if len(srcJarArgs) > srcJarArgsLimit { srcJarRspFile := android.PathForModuleOut(ctx, "turbine", "srcjars.rsp") - android.WriteFileRule(ctx, srcJarRspFile, srcJarArgs) + android.WriteFileRule(ctx, srcJarRspFile, strings.Join(srcJars.Strings(), "\n")) srcJarArgs = "@" + srcJarRspFile.String() implicits = append(implicits, srcJarRspFile) + rspFiles = append(rspFiles, srcJarRspFile) rbeInputs = append(rbeInputs, srcJarRspFile) } else { rbeInputs = append(rbeInputs, srcJars...) @@ -488,7 +505,7 @@ func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string, const classpathLimit = 32 * 1024 if len(classpathFlags) > classpathLimit { classpathRspFile := android.PathForModuleOut(ctx, dir, "classpath.rsp") - android.WriteFileRule(ctx, classpathRspFile, classpathFlags) + android.WriteFileRule(ctx, classpathRspFile, strings.Join(classpath.Strings(), "\n")) classpathFlags = "@" + classpathRspFile.String() implicits = append(implicits, classpathRspFile) rspFiles = append(rspFiles, classpathRspFile) @@ -736,6 +753,16 @@ func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePa }) } +func TransformJarToR8Rules(ctx android.ModuleContext, outputFile android.WritablePath, + jar android.Path) { + + ctx.Build(pctx, android.BuildParams{ + Rule: extractR8Rules, + Output: outputFile, + Input: jar, + }) +} + func convertImplementationJarToHeaderJar(ctx android.ModuleContext, implementationJarFile android.Path, headerJarFile android.WritablePath) { ctx.Build(pctx, android.BuildParams{ @@ -747,16 +774,58 @@ func convertImplementationJarToHeaderJar(ctx android.ModuleContext, implementati func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, classesJar android.Path, rulesFile android.Path) { + TransformJarJarWithShards(ctx, outputFile, classesJar, rulesFile, 1) +} + +func TransformJarJarWithShards(ctx android.ModuleContext, outputFile android.WritablePath, + classesJar android.Path, rulesFile android.Path, totalShards int) { + + // If the total number of shards is 1, just run jarjar as-is, with `total_shards` = 1 + // and `shard_index` == 0, which effectively disables sharding + if totalShards == 1 { + ctx.Build(pctx, android.BuildParams{ + Rule: jarjar, + Description: "jarjar", + Output: outputFile, + Input: classesJar, + Implicit: rulesFile, + Args: map[string]string{ + "rulesFile": rulesFile.String(), + "total_shards": "1", + "shard_index": "0", + }, + }) + return + } + + // Otherwise, run multiple jarjar instances and use merge_zips to combine the output. + tempJars := make([]android.Path, 0) + totalStr := strconv.Itoa(totalShards) + for i := 0; i < totalShards; i++ { + iStr := strconv.Itoa(i) + tempOut := outputFile.ReplaceExtension(ctx, "-"+iStr+".jar") + ctx.Build(pctx, android.BuildParams{ + Rule: jarjar, + Description: "jarjar (" + iStr + "/" + totalStr + ")", + Output: tempOut, + Input: classesJar, + Implicit: rulesFile, + Args: map[string]string{ + "rulesFile": rulesFile.String(), + "total_shards": totalStr, + "shard_index": iStr, + }, + }) + tempJars = append(tempJars, tempOut) + } + ctx.Build(pctx, android.BuildParams{ - Rule: jarjar, - Description: "jarjar", + Rule: combineJar, + Description: "merge jarjar shards", Output: outputFile, - Input: classesJar, - Implicit: rulesFile, - Args: map[string]string{ - "rulesFile": rulesFile.String(), - }, + Inputs: tempJars, }) + } func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath, diff --git a/java/classpath_element.go b/java/classpath_element.go index abbcae7a3..4af277012 100644 --- a/java/classpath_element.go +++ b/java/classpath_element.go @@ -108,33 +108,18 @@ type ClasspathElementContext interface { // // e.g. Given the following input: // -// libraries: com.android.art:core-oj, com.android.art:core-libart, framework, ext -// fragments: com.android.art:art-bootclasspath-fragment +// libraries: core-oj, core-libart, framework, ext +// fragments: art-bootclasspath-fragment +// libraryToApex: core-oj: com.android.art, core-libart: com.android.art +// apexNameToFragment: com.android.art: art-bootclasspath-fragment // // Then this will return: // // ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]), // ClasspathLibraryElement(framework), // ClasspathLibraryElement(ext), -func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module) ClasspathElements { - // Create a map from apex name to the fragment module. This makes it easy to find the fragment - // associated with a particular apex. - apexToFragment := map[string]android.Module{} - for _, fragment := range fragments { - apexInfo, ok := android.OtherModuleProvider(ctx, fragment, android.ApexInfoProvider) - if !ok { - ctx.ModuleErrorf("fragment %s is not part of an apex", fragment) - continue - } - - for _, apex := range apexInfo.InApexVariants { - if existing, ok := apexToFragment[apex]; ok { - ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", apex, fragment, existing) - continue - } - apexToFragment[apex] = fragment - } - } +func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module, + libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) ClasspathElements { fragmentToElement := map[android.Module]*ClasspathFragmentElement{} elements := []ClasspathElement{} @@ -144,31 +129,28 @@ skipLibrary: // Iterate over the libraries to construct the ClasspathElements list. for _, library := range libraries { var element ClasspathElement - if apexInfo, ok := android.OtherModuleProvider(ctx, library, android.ApexInfoProvider); ok { - + if libraryApex, ok := libraryToApex[library]; ok { var fragment android.Module // Make sure that the library is in only one fragment of the classpath. - for _, apex := range apexInfo.InApexVariants { - if f, ok := apexToFragment[apex]; ok { - if fragment == nil { - // This is the first fragment so just save it away. - fragment = f - } else if f != fragment { - // This apex variant of the library is in a different fragment. - ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f) - // Skip over this library entirely as otherwise the resulting classpath elements would - // be invalid. - continue skipLibrary - } - } else { - // There is no fragment associated with the library's apex. + if f, ok := apexNameToFragment[libraryApex]; ok { + if fragment == nil { + // This is the first fragment so just save it away. + fragment = f + } else if f != fragment { + // This apex variant of the library is in a different fragment. + ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f) + // Skip over this library entirely as otherwise the resulting classpath elements would + // be invalid. + continue skipLibrary } + } else { + // There is no fragment associated with the library's apex. } if fragment == nil { ctx.ModuleErrorf("library %s is from apexes %s which have no corresponding fragment in %s", - library, apexInfo.InApexVariants, fragments) + library, []string{libraryApex}, fragments) // Skip over this library entirely as otherwise the resulting classpath elements would // be invalid. continue skipLibrary diff --git a/java/config/config.go b/java/config/config.go index 87703d821..71025de6a 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -159,6 +159,7 @@ func init() { pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar") pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file") + pctx.HostBinToolVariable("FindInputDeltaCmd", "find_input_delta") pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh") pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh") @@ -170,6 +171,7 @@ func init() { pctx.HostBinToolVariable("ApiCheckCmd", "apicheck") pctx.HostBinToolVariable("D8Cmd", "d8") pctx.HostBinToolVariable("R8Cmd", "r8") + pctx.HostBinToolVariable("ExtractR8RulesCmd", "extract-r8-rules") pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") diff --git a/java/config/kotlin.go b/java/config/kotlin.go index 302d021db..ffb025d9c 100644 --- a/java/config/kotlin.go +++ b/java/config/kotlin.go @@ -21,6 +21,7 @@ var ( KotlincIllegalFlags = []string{ "-no-jdk", "-no-stdlib", + "-language-version", } ) @@ -56,5 +57,5 @@ func init() { // platform that are not fully compatible with the kotlinc used in g3 kythe indexers. // e.g. uninitialized variables are a warning in 1.*, but an error in 2.* // https://github.com/JetBrains/kotlin/blob/master/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt#L748 - pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " ")) + pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{}, " ")) } diff --git a/java/container_test.go b/java/container_test.go index 25cfa4c7e..35a3020ec 100644 --- a/java/container_test.go +++ b/java/container_test.go @@ -26,6 +26,7 @@ var checkContainerMatch = func(t *testing.T, name string, container string, expe } func TestJavaContainersModuleProperties(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, ).RunTestWithBp(t, ` @@ -154,7 +155,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { } for _, c := range testcases { - m := result.ModuleForTests(c.moduleName, "android_common") + m := result.ModuleForTests(t, c.moduleName, "android_common") containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider) belongingContainers := containers.BelongingContainers() checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers)) diff --git a/java/core-libraries/jarjar-strip-annotations-rules.txt b/java/core-libraries/jarjar-strip-annotations-rules.txt index a1c261b9a..c74eaca49 100644 --- a/java/core-libraries/jarjar-strip-annotations-rules.txt +++ b/java/core-libraries/jarjar-strip-annotations-rules.txt @@ -2,3 +2,4 @@ strip-annotation android.annotation.NotNull strip-annotation android.annotation.Nullable strip-annotation androidx.annotation.RecentlyNonNull strip-annotation androidx.annotation.RecentlyNullable +strip-annotation android.annotation.FlaggedApi diff --git a/java/device_host_converter.go b/java/device_host_converter.go index bfacea6da..04def3e28 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -140,7 +140,7 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont d.combinedHeaderJar = d.headerJars[0] } - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + javaInfo := &JavaInfo{ HeaderJars: d.headerJars, LocalHeaderJars: d.headerJars, TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, nil, transitiveHeaderJars), @@ -154,7 +154,9 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont StubsLinkType: Implementation, // TODO: Not sure if aconfig flags that have been moved between device and host variants // make sense. - }) + } + setExtraJavaInfo(ctx, d, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) } diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go index 6ccc5c1b1..197bb9f95 100644 --- a/java/device_host_converter_test.go +++ b/java/device_host_converter_test.go @@ -22,6 +22,7 @@ import ( ) func TestDeviceForHost(t *testing.T) { + t.Parallel() bp := ` java_library { name: "device_module", @@ -52,15 +53,15 @@ func TestDeviceForHost(t *testing.T) { ctx, config := testJava(t, bp) - deviceModule := ctx.ModuleForTests("device_module", "android_common") + deviceModule := ctx.ModuleForTests(t, "device_module", "android_common") deviceTurbineCombined := deviceModule.Output("turbine-combined/device_module.jar") deviceJavac := deviceModule.Output("javac/device_module.jar") deviceRes := deviceModule.Output("res/device_module.jar") - deviceImportModule := ctx.ModuleForTests("device_import_module", "android_common") + deviceImportModule := ctx.ModuleForTests(t, "device_import_module", "android_common") deviceImportCombined := deviceImportModule.Output("combined/device_import_module.jar") - hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String()) + hostModule := ctx.ModuleForTests(t, "host_module", config.BuildOSCommonTarget.String()) hostJavac := hostModule.Output("javac/host_module.jar") hostRes := hostModule.Output("res/host_module.jar") combined := hostModule.Output("combined/host_module.jar") @@ -102,6 +103,7 @@ func TestDeviceForHost(t *testing.T) { } func TestHostForDevice(t *testing.T) { + t.Parallel() bp := ` java_library_host { name: "host_module", @@ -133,15 +135,15 @@ func TestHostForDevice(t *testing.T) { ctx, config := testJava(t, bp) - hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String()) + hostModule := ctx.ModuleForTests(t, "host_module", config.BuildOSCommonTarget.String()) hostJavac := hostModule.Output("javac/host_module.jar") hostJavacHeader := hostModule.Output("javac-header/host_module.jar") hostRes := hostModule.Output("res/host_module.jar") - hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOSCommonTarget.String()) + hostImportModule := ctx.ModuleForTests(t, "host_import_module", config.BuildOSCommonTarget.String()) hostImportCombined := hostImportModule.Output("combined/host_import_module.jar") - deviceModule := ctx.ModuleForTests("device_module", "android_common") + deviceModule := ctx.ModuleForTests(t, "device_module", "android_common") deviceJavac := deviceModule.Output("javac/device_module.jar") deviceRes := deviceModule.Output("res/device_module.jar") combined := deviceModule.Output("combined/device_module.jar") diff --git a/java/dex.go b/java/dex.go index 2b3c9319a..3df03a889 100644 --- a/java/dex.go +++ b/java/dex.go @@ -42,13 +42,35 @@ type DexProperties struct { // True if the module containing this has it set by default. EnabledByDefault bool `blueprint:"mutated"` + // Whether to allow that library classes inherit from program classes. + // Defaults to false. + Ignore_library_extends_program *bool + // Whether to continue building even if warnings are emitted. Defaults to true. Ignore_warnings *bool + // Whether runtime invisible annotations should be kept by R8. Defaults to false. + // This is equivalent to: + // -keepattributes RuntimeInvisibleAnnotations, + // RuntimeInvisibleParameterAnnotations, + // RuntimeInvisibleTypeAnnotations + // This is only applicable when RELEASE_R8_ONLY_RUNTIME_VISIBLE_ANNOTATIONS is + // enabled and will be used to migrate away from keeping runtime invisible + // annotations (b/387958004). + Keep_runtime_invisible_annotations *bool + // If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode. - // Defaults to false for apps, true for libraries and tests. + // Defaults to false for apps and tests, true for libraries. Proguard_compatibility *bool + // If true, R8 will not add public or protected members (fields or methods) to + // the API surface of the compilation unit, i.e., classes that are kept or + // have kept subclasses will not expose any members added by R8 for internal + // use. That includes renamed members if obfuscation is enabled. + // This should only be used for building targets that go on the bootclasspath. + // Defaults to false. + Protect_api_surface *bool + // If true, optimize for size by removing unused code. Defaults to true for apps, // false for libraries and tests. Shrink *bool @@ -220,21 +242,29 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext, deps = append(deps, f) } - var requestReleaseMode bool + var requestReleaseMode, requestDebugMode bool requestReleaseMode, flags = android.RemoveFromList("--release", flags) + requestDebugMode, flags = android.RemoveFromList("--debug", flags) if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" || ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" { - flags = append(flags, "--debug") + requestDebugMode = true requestReleaseMode = false } // Don't strip out debug information for eng builds, unless the target // explicitly provided the `--release` build flag. This allows certain // test targets to remain optimized as part of eng test_suites builds. - if requestReleaseMode { + if requestDebugMode { + flags = append(flags, "--debug") + } else if requestReleaseMode { flags = append(flags, "--release") } else if ctx.Config().Eng() { flags = append(flags, "--debug") + } else if !d.effectiveOptimizeEnabled() && d.dexProperties.Optimize.EnabledByDefault { + // D8 uses --debug by default, whereas R8 uses --release by default. + // For targets that default to R8 usage (e.g., apps), but override this default, we still + // want D8 to run in release mode, preserving semantics as much as possible between the two. + flags = append(flags, "--release") } // Supplying the platform build flag disables various features like API modeling and desugaring. @@ -306,7 +336,7 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, // TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references. if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer { var proguardRaiseDeps classpath - ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) { + ctx.VisitDirectDepsProxyWithTag(proguardRaiseTag, func(m android.ModuleProxy) { if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...) } @@ -356,10 +386,22 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, r8Flags = append(r8Flags, opt.Proguard_flags...) - if BoolDefault(opt.Proguard_compatibility, true) { + if BoolDefault(opt.Ignore_library_extends_program, false) { + r8Flags = append(r8Flags, "--ignore-library-extends-program") + } + + if BoolDefault(opt.Keep_runtime_invisible_annotations, false) { + r8Flags = append(r8Flags, "--keep-runtime-invisible-annotations") + } + + if BoolDefault(opt.Proguard_compatibility, !ctx.Config().UseR8FullModeByDefault()) { r8Flags = append(r8Flags, "--force-proguard-compatibility") } + if BoolDefault(opt.Protect_api_surface, false) { + r8Flags = append(r8Flags, "--protect-api-surface") + } + // Avoid unnecessary stack frame noise by only injecting source map ids for non-debug // optimized or obfuscated targets. if (Bool(opt.Optimize) || Bool(opt.Obfuscate)) && !debugMode { @@ -412,6 +454,10 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, artProfileOutput = profileOutput } + if ctx.Config().UseR8StoreStoreFenceConstructorInlining() { + r8Flags = append(r8Flags, "--store-store-fence-constructor-inlining") + } + return r8Flags, r8Deps, artProfileOutput } diff --git a/java/dex_test.go b/java/dex_test.go index 8bc28e678..2126e42e8 100644 --- a/java/dex_test.go +++ b/java/dex_test.go @@ -16,6 +16,7 @@ package java import ( "fmt" + "strconv" "testing" "android/soong/android" @@ -24,6 +25,7 @@ import ( ) func TestR8(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` android_app { name: "app", @@ -58,11 +60,11 @@ func TestR8(t *testing.T) { } `) - app := result.ModuleForTests("app", "android_common") - stableApp := result.ModuleForTests("stable_app", "android_common") - corePlatformApp := result.ModuleForTests("core_platform_app", "android_common") - lib := result.ModuleForTests("lib", "android_common") - staticLib := result.ModuleForTests("static_lib", "android_common") + app := result.ModuleForTests(t, "app", "android_common") + stableApp := result.ModuleForTests(t, "stable_app", "android_common") + corePlatformApp := result.ModuleForTests(t, "core_platform_app", "android_common") + lib := result.ModuleForTests(t, "lib", "android_common") + staticLib := result.ModuleForTests(t, "static_lib", "android_common") appJavac := app.Rule("javac") appR8 := app.Rule("r8") @@ -91,6 +93,7 @@ func TestR8(t *testing.T) { } func TestR8TransitiveDeps(t *testing.T) { + t.Parallel() bp := ` override_android_app { name: "override_app", @@ -192,6 +195,7 @@ func TestR8TransitiveDeps(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() fixturePreparer := PrepareForTestWithJavaDefaultModules if tc.unbundled { fixturePreparer = android.GroupFixturePreparers( @@ -206,14 +210,14 @@ func TestR8TransitiveDeps(t *testing.T) { result := fixturePreparer.RunTestWithBp(t, bp) getHeaderJar := func(name string) android.Path { - mod := result.ModuleForTests(name, "android_common") + mod := result.ModuleForTests(t, name, "android_common") return mod.Output("turbine-combined/" + name + ".jar").Output } - appR8 := result.ModuleForTests("app", "android_common").Rule("r8") - overrideAppR8 := result.ModuleForTests("app", "android_common_override_app").Rule("r8") + appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8") + overrideAppR8 := result.ModuleForTests(t, "app", "android_common_override_app").Rule("r8") appHeader := getHeaderJar("app") - overrideAppHeader := result.ModuleForTests("app", "android_common_override_app").Output("turbine-combined/app.jar").Output + overrideAppHeader := result.ModuleForTests(t, "app", "android_common_override_app").Output("turbine-combined/app.jar").Output libHeader := getHeaderJar("lib") transitiveLibHeader := getHeaderJar("transitive_lib") transitiveLib2Header := getHeaderJar("transitive_lib_2") @@ -222,7 +226,7 @@ func TestR8TransitiveDeps(t *testing.T) { repeatedDepHeader := getHeaderJar("repeated_dep") usesLibHeader := getHeaderJar("uses_lib") optionalUsesLibHeader := getHeaderJar("optional_uses_lib") - prebuiltLibHeader := result.ModuleForTests("prebuilt_lib", "android_common").Output("combined/lib.jar").Output + prebuiltLibHeader := result.ModuleForTests(t, "prebuilt_lib", "android_common").Output("combined/lib.jar").Output for _, rule := range []android.TestingBuildParams{appR8, overrideAppR8} { android.AssertStringDoesNotContain(t, "expected no app header jar in app r8 classpath", @@ -259,6 +263,7 @@ func TestR8TransitiveDeps(t *testing.T) { } func TestR8Flags(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` android_app { name: "app", @@ -273,7 +278,7 @@ func TestR8Flags(t *testing.T) { } `) - app := result.ModuleForTests("app", "android_common") + app := result.ModuleForTests(t, "app", "android_common") appR8 := app.Rule("r8") android.AssertStringDoesContain(t, "expected -dontshrink in app r8 flags", appR8.Args["r8Flags"], "-dontshrink") @@ -288,6 +293,7 @@ func TestR8Flags(t *testing.T) { } func TestD8(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` java_library { name: "foo", @@ -306,14 +312,25 @@ func TestD8(t *testing.T) { name: "static_lib", srcs: ["foo.java"], } + + android_app { + name: "app", + srcs: ["foo.java"], + platform_apis: true, + optimize: { + enabled: false, + }, + } `) - foo := result.ModuleForTests("foo", "android_common") - lib := result.ModuleForTests("lib", "android_common") - staticLib := result.ModuleForTests("static_lib", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") + lib := result.ModuleForTests(t, "lib", "android_common") + app := result.ModuleForTests(t, "app", "android_common") + staticLib := result.ModuleForTests(t, "static_lib", "android_common") fooJavac := foo.Rule("javac") fooD8 := foo.Rule("d8") + appD8 := app.Rule("d8") libHeader := lib.Output("turbine-combined/lib.jar").Output staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output @@ -326,9 +343,20 @@ func TestD8(t *testing.T) { fooD8.Args["d8Flags"], libHeader.String()) android.AssertStringDoesNotContain(t, "expected no static_lib header jar in foo javac classpath", fooD8.Args["d8Flags"], staticLibHeader.String()) + + // A --release flag is added only for targets that opt out of default R8 behavior (e.g., apps). + // For library targets that don't use R8 by default, no --debug or --release flag should be + // added, instead relying on default D8 behavior (--debug). + android.AssertStringDoesContain(t, "expected --release in app d8 flags", + appD8.Args["d8Flags"], "--release") + android.AssertStringDoesNotContain(t, "expected no --release flag in lib d8 flags", + fooD8.Args["d8Flags"], "--release") + android.AssertStringDoesNotContain(t, "expected no --debug flag in lib d8 flags", + fooD8.Args["d8Flags"], "--debug") } func TestProguardFlagsInheritanceStatic(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` android_app { name: "app", @@ -370,7 +398,7 @@ func TestProguardFlagsInheritanceStatic(t *testing.T) { } `) - app := result.ModuleForTests("app", "android_common") + app := result.ModuleForTests(t, "app", "android_common") appR8 := app.Rule("r8") android.AssertStringDoesContain(t, "expected primary_lib's proguard flags from direct dep", appR8.Args["r8Flags"], "primary.flags") @@ -383,6 +411,7 @@ func TestProguardFlagsInheritanceStatic(t *testing.T) { } func TestProguardFlagsInheritance(t *testing.T) { + t.Parallel() directDepFlagsFileName := "direct_dep.flags" transitiveDepFlagsFileName := "transitive_dep.flags" @@ -601,6 +630,7 @@ func TestProguardFlagsInheritance(t *testing.T) { for _, topLevelModuleDef := range topLevelModules { for _, tc := range testcases { t.Run(topLevelModuleDef.name+"-"+tc.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureMergeMockFs(android.MockFS{ @@ -617,7 +647,7 @@ func TestProguardFlagsInheritance(t *testing.T) { tc.transitiveDepExportsFlagsFiles, ), ) - appR8 := result.ModuleForTests("app", "android_common").Rule("r8") + appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8") shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles) if shouldHaveDepFlags { @@ -642,6 +672,7 @@ func TestProguardFlagsInheritance(t *testing.T) { } func TestProguardFlagsInheritanceAppImport(t *testing.T) { + t.Parallel() bp := ` android_app { name: "app", @@ -658,12 +689,13 @@ func TestProguardFlagsInheritanceAppImport(t *testing.T) { PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, bp) - appR8 := result.ModuleForTests("app", "android_common").Rule("r8") + appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8") android.AssertStringDoesContain(t, "expected aarimports's proguard flags", appR8.Args["r8Flags"], "proguard.txt") } func TestR8FlagsArtProfile(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, ` android_app { name: "app", @@ -677,7 +709,7 @@ func TestR8FlagsArtProfile(t *testing.T) { } `) - app := result.ModuleForTests("app", "android_common") + app := result.ModuleForTests(t, "app", "android_common") appR8 := app.Rule("r8") android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags", appR8.Args["r8Flags"], "--art-profile") @@ -696,6 +728,7 @@ func TestR8FlagsArtProfile(t *testing.T) { // // The rewritten profile should be used since the dex signatures in the checked-in profile will not match the optimized binary. func TestEnableProfileRewritingIsRequiredForOptimizedApps(t *testing.T) { + t.Parallel() testJavaError(t, "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on", ` @@ -715,11 +748,15 @@ android_app { } func TestDebugReleaseFlags(t *testing.T) { + t.Parallel() bp := ` android_app { name: "app", srcs: ["foo.java"], platform_apis: true, + optimize: { + enabled: %s, + }, dxflags: ["%s"] } ` @@ -728,6 +765,7 @@ func TestDebugReleaseFlags(t *testing.T) { name string envVar string isEng bool + useD8 bool dxFlags string expectedFlags string }{ @@ -767,10 +805,24 @@ func TestDebugReleaseFlags(t *testing.T) { // Eng mode does *not* override explicit dxflags. expectedFlags: "--release", }, + { + name: "app_d8", + useD8: true, + // D8 usage w/ apps should explicitly enable --release mode. + expectedFlags: "--release", + }, + { + name: "app_d8_debug", + useD8: true, + dxFlags: "--debug", + // D8 usage w/ apps respects overriding dxFlags. + expectedFlags: "--debug", + }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() fixturePreparer := PrepareForTestWithJavaDefaultModules fixturePreparer = android.GroupFixturePreparers( fixturePreparer, @@ -788,11 +840,16 @@ func TestDebugReleaseFlags(t *testing.T) { }), ) } - result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, tc.dxFlags)) + result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, strconv.FormatBool(!tc.useD8), tc.dxFlags)) - appR8 := result.ModuleForTests("app", "android_common").Rule("r8") - android.AssertStringDoesContain(t, "expected flag in R8 flags", - appR8.Args["r8Flags"], tc.expectedFlags) + dexRuleKey := "r8" + if tc.useD8 { + dexRuleKey = "d8" + } + dexFlagsKey := dexRuleKey + "Flags" + appDex := result.ModuleForTests(t, "app", "android_common").Rule(dexRuleKey) + android.AssertStringDoesContain(t, "expected flag in dex flags", + appDex.Args[dexFlagsKey], tc.expectedFlags) var unexpectedFlags string if tc.expectedFlags == "--debug" { @@ -801,8 +858,8 @@ func TestDebugReleaseFlags(t *testing.T) { unexpectedFlags = "--debug" } if unexpectedFlags != "" { - android.AssertStringDoesNotContain(t, "unexpected flag in R8 flags", - appR8.Args["r8Flags"], unexpectedFlags) + android.AssertStringDoesNotContain(t, "unexpected flag in dex flags", + appDex.Args[dexFlagsKey], unexpectedFlags) } }) } diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 5928446e3..5755dec23 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -36,61 +36,24 @@ type DexpreopterInterface interface { // If the java module is to be installed into an APEX, this list contains information about the // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed // outside of the APEX. - DexpreoptBuiltInstalledForApex() []dexpreopterInstall + ApexSystemServerDexpreoptInstalls() []DexpreopterInstall - // The Make entries to install the dexpreopt outputs. Derived from - // `DexpreoptBuiltInstalledForApex`. - AndroidMkEntriesForApex() []android.AndroidMkEntries + // ApexSystemServerDexJars returns the list of dex jars if this is an apex system server jar. + ApexSystemServerDexJars() android.Paths // See `dexpreopter.outputProfilePathOnHost`. OutputProfilePathOnHost() android.Path } -type dexpreopterInstall struct { - // A unique name to distinguish an output from others for the same java library module. Usually in - // the form of `<arch>-<encoded-path>.odex/vdex/art`. - name string - - // The name of the input java module. - moduleName string - +type DexpreopterInstall struct { // The path to the dexpreopt output on host. - outputPathOnHost android.Path + OutputPathOnHost android.Path // The directory on the device for the output to install to. - installDirOnDevice android.InstallPath + InstallDirOnDevice android.InstallPath // The basename (the last segment of the path) for the output to install as. - installFileOnDevice string -} - -// The full module name of the output in the makefile. -func (install *dexpreopterInstall) FullModuleName() string { - return install.moduleName + install.SubModuleName() -} - -// The sub-module name of the output in the makefile (the name excluding the java module name). -func (install *dexpreopterInstall) SubModuleName() string { - return "-dexpreopt-" + install.name -} - -// Returns Make entries for installing the file. -// -// This function uses a value receiver rather than a pointer receiver to ensure that the object is -// safe to use in `android.AndroidMkExtraEntriesFunc`. -func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { - return android.AndroidMkEntries{ - Class: "ETC", - OutputFile: android.OptionalPathForPath(install.outputPathOnHost), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_MODULE", install.FullModuleName()) - entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String()) - entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice) - entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false") - }, - }, - } + InstallFileOnDevice string } type Dexpreopter struct { @@ -120,8 +83,9 @@ type dexpreopter struct { classLoaderContexts dexpreopt.ClassLoaderContextMap // See the `dexpreopt` function for details. - builtInstalled string - builtInstalledForApex []dexpreopterInstall + builtInstalled string + apexSystemServerDexpreoptInstalls []DexpreopterInstall + apexSystemServerDexJars android.Paths // The config is used for two purposes: // - Passing dexpreopt information about libraries from Soong to Make. This is needed when @@ -204,27 +168,23 @@ func disableSourceApexVariant(ctx android.BaseModuleContext) bool { } apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) psi := android.PrebuiltSelectionInfoMap{} - ctx.VisitDirectDeps(func(am android.Module) { + ctx.VisitDirectDepsProxy(func(am android.ModuleProxy) { if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok { psi = prebuiltSelectionInfo } }) // Find the apex variant for this module - apexVariantsWithoutTestApexes := []string{} + apexVariants := []string{} if apexInfo.BaseApexName != "" { - // This is a transitive dependency of an override_apex - apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.BaseApexName) - } else { - _, variants, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes) - apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, variants...) + apexVariants = append(apexVariants, apexInfo.BaseApexName) } if apexInfo.ApexAvailableName != "" { - apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.ApexAvailableName) + apexVariants = append(apexVariants, apexInfo.ApexAvailableName) } disableSource := false // find the selected apexes - for _, apexVariant := range apexVariantsWithoutTestApexes { + for _, apexVariant := range apexVariants { if len(psi.GetSelectedModulesForApiDomain(apexVariant)) > 0 { // If the apex_contribution for this api domain is non-empty, disable the source variant disableSource = true @@ -279,20 +239,6 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName s if !isApexSystemServerJar { return true } - ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) - allApexInfos := []android.ApexInfo{} - if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok { - allApexInfos = allApexInfosProvider.ApexInfos - } - if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) { - // Apex system server jars are dexpreopted and installed on to the system image. - // Since we can have BigAndroid and Go variants of system server jar providing apexes, - // and these two variants can have different min_sdk_versions, hide one of the apex variants - // from make to prevent collisions. - // - // Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries. - ctx.Module().MakeUninstallable() - } } else { // Don't preopt the platform variant of an APEX system server jar to avoid conflicts. if isApexSystemServerJar { @@ -347,7 +293,11 @@ func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleCo d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/")) // generate the rules for creating the .odex and .vdex files for this system server jar dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName)) - + if dexJarFile == nil { + ctx.ModuleErrorf( + `Could not find library %s in prebuilt apex %s. +Please make sure that the value of PRODUCT_APEX_(SYSTEM_SERVER|STANDALONE_SYSTEM_SERVER)_JARS is correct`, libraryName, ctx.ModuleName()) + } d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) { // Set the profile path to guide optimization @@ -539,12 +489,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa Output(appProductPackages) productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages") - // Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars - // The javalib from the deapexed prebuilt will be copied to this location. - // TODO (b/331665856): Implement a principled solution for this. - copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake() dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( - ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex) + ctx, globalSoong, global, dexpreoptConfig, appProductPackages) if err != nil { ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) return @@ -577,7 +523,6 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa partition = "" } installBase := filepath.Base(install.To) - arch := filepath.Base(installDir) installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir) isProfile := strings.HasSuffix(installBase, ".prof") @@ -593,16 +538,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa // libraries, only those in the system server classpath are handled here. // Preopting of boot classpath jars in the ART APEX are handled in // java/dexpreopt_bootjars.go, and other APEX jars are not preopted. - // The installs will be handled by Make as sub-modules of the java library. - di := dexpreopterInstall{ - name: arch + "-" + installBase, - moduleName: libName, - outputPathOnHost: install.From, - installDirOnDevice: installPath, - installFileOnDevice: installBase, + // The installs will be handled the apex module that includes this library. + di := DexpreopterInstall{ + OutputPathOnHost: install.From, + InstallDirOnDevice: installPath, + InstallFileOnDevice: installBase, } - ctx.InstallFile(di.installDirOnDevice, di.installFileOnDevice, di.outputPathOnHost) - d.builtInstalledForApex = append(d.builtInstalledForApex, di) + d.apexSystemServerDexpreoptInstalls = append(d.apexSystemServerDexpreoptInstalls, di) } } else if !d.preventInstall { @@ -611,6 +553,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa } } + if isApexSystemServerJar { + // Store the dex jar location for system server jars in apexes, the apex will copy the file into + // a known location for dex2oat. + d.apexSystemServerDexJars = append(d.apexSystemServerDexJars, dexJarFile) + } else if isSystemServerJar && !d.preventInstall { + // Copy the dex jar into a known location for dex2oat for non-apex system server jars. + android.CopyFileRule(ctx, dexJarFile, android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJarFile.Base())) + } + if !isApexSystemServerJar { d.builtInstalled = dexpreoptRule.Installs().String() } @@ -645,16 +596,12 @@ func installFile(ctx android.ModuleContext, install android.RuleBuilderInstall) } } -func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall { - return d.builtInstalledForApex +func (d *dexpreopter) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall { + return d.apexSystemServerDexpreoptInstalls } -func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { - var entries []android.AndroidMkEntries - for _, install := range d.builtInstalledForApex { - entries = append(entries, install.ToMakeEntries()) - } - return entries +func (d *dexpreopter) ApexSystemServerDexJars() android.Paths { + return d.apexSystemServerDexJars } func (d *dexpreopter) OutputProfilePathOnHost() android.Path { diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 8c60d2399..313d8c7a4 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -15,6 +15,7 @@ package java import ( + "fmt" "path/filepath" "strings" @@ -225,7 +226,6 @@ var artApexNames = []string{ } var ( - dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"} dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments") apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"} ) @@ -293,6 +293,9 @@ type bootImageConfig struct { // Profiles imported from APEXes, in addition to the profile at the default path. Each entry must // be the name of an APEX module. profileImports []string + + // The name of the module that provides boot image profiles, if any. + profileProviderModule string } // Target-dependent description of a boot image. @@ -464,9 +467,6 @@ func dexpreoptBootJarsFactory() android.SingletonModule { func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) { ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory) ctx.RegisterModuleType("art_boot_images", artBootImagesFactory) - ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator) - }) } func SkipDexpreoptBootJars(ctx android.PathContext) bool { @@ -502,12 +502,6 @@ type dexpreoptBootJars struct { func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) { // Create a dependency on all_apex_contributions to determine the selected mainline module ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions") -} - -func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) { - if _, ok := ctx.Module().(*dexpreoptBootJars); !ok { - return - } if dexpreopt.IsDex2oatNeeded(ctx) { // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The @@ -521,7 +515,7 @@ func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) { continue } // For accessing the boot jars. - addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag) + addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJar) // Create a dependency on the apex selected using RELEASE_APEX_CONTRIBUTIONS_* // TODO: b/308174306 - Remove the direct depedendency edge to the java_library (source/prebuilt) once all mainline modules // have been flagged using RELEASE_APEX_CONTRIBUTIONS_* @@ -534,11 +528,11 @@ func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) { if ctx.OtherModuleExists("platform-bootclasspath") { // For accessing all bootclasspath fragments. - addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag) + addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platform) } else if ctx.OtherModuleExists("art-bootclasspath-fragment") { // For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where // platform-bootclasspath doesn't exist. - addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag) + addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", fragment) } } @@ -556,13 +550,13 @@ func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorConte // We need to add a dep on only the apex listed in `contents` of the selected apex_contributions module // This is not available in a structured format in `apex_contributions`, so this hack adds a dep on all `contents` // (some modules like art.module.public.api do not have an apex variation since it is a pure stub module that does not get installed) - apexVariationOfSelected := append(ctx.Target().Variations(), blueprint.Variation{Mutator: "apex", Variation: apex}) - if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, selected) { - ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected) - } else if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, android.RemoveOptionalPrebuiltPrefix(selected)) { - // The prebuilt might have been renamed by prebuilt_rename mutator if the source module does not exist. - // Remove the prebuilt_ prefix. - ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, android.RemoveOptionalPrebuiltPrefix(selected)) + tag := bootclasspathDependencyTag{ + typ: dexpreoptBootJar, + } + + dep := android.RemoveOptionalPrebuiltPrefix(selected) + if ctx.OtherModuleDependencyVariantExists(ctx.Target().Variations(), dep) { + ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, dep) } } } @@ -571,23 +565,55 @@ func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorConte func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module { return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} { fragments := make(map[string]android.Module) + + type moduleInApexPair struct { + module string + apex string + } + + var modulesInApexes []moduleInApexPair + + // Find the list of modules in apexes. ctx.WalkDeps(func(child, parent android.Module) bool { if !isActiveModule(ctx, child) { return false } tag := ctx.OtherModuleDependencyTag(child) - if tag == platformBootclasspathDepTag { - return true - } - if tag == bootclasspathFragmentDepTag { - apexInfo, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider) - for _, apex := range apexInfo.InApexVariants { - fragments[apex] = child + if bcpTag, ok := tag.(bootclasspathDependencyTag); ok { + if bcpTag.typ == platform { + return true + } + if bcpTag.typ == fragment { + if bcpTag.moduleInApex == "" { + panic(fmt.Errorf("expected fragment to be in apex")) + } + modulesInApexes = append(modulesInApexes, moduleInApexPair{bcpTag.moduleInApex, ctx.OtherModuleName(child)}) + return true } - return false } return false }) + + for _, moduleInApex := range modulesInApexes { + // Find a desired module in an apex. + ctx.WalkDeps(func(child, parent android.Module) bool { + t := ctx.OtherModuleDependencyTag(child) + if bcpTag, ok := t.(bootclasspathDependencyTag); ok { + if bcpTag.typ == platform { + return true + } + if bcpTag.typ == fragment && ctx.OtherModuleName(child) == moduleInApex.apex { + // This is the dependency from this module to the apex, recurse into it. + return true + } + } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module { + // This is the desired module inside the apex. + fragments[android.RemoveOptionalPrebuiltPrefix(moduleInApex.apex)] = child + } + return false + }) + } + return fragments }).(map[string]android.Module) } @@ -711,7 +737,8 @@ func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) modules := make([]apexJarModulePair, 0, imageConfig.modules.Len()) for i := 0; i < imageConfig.modules.Len(); i++ { found := false - for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) { + dexpreoptBootJarModules, _ := gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJar) + for _, module := range dexpreoptBootJarModules { name := android.RemoveOptionalPrebuiltPrefix(module.Name()) if name == imageConfig.modules.Jar(i) { modules = append(modules, apexJarModulePair{ @@ -794,11 +821,16 @@ func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNam "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars", pair.jarModule.Name(), pair.apex) + return nil } bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider) jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule) if err != nil { - ctx.ModuleErrorf("%s", err) + if ctx.Config().AllowMissingDependencies() { + ctx.AddMissingDependencies([]string{pair.jarModule.String()}) + } else { + ctx.ModuleErrorf("%s", err) + } } return jar } @@ -957,9 +989,16 @@ func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameT func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap { apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{} - ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) { - if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists { - apexNameToApexExportsInfoMap[info.ApexName] = info + + ctx.VisitDirectDeps(func(am android.Module) { + tag := ctx.OtherModuleDependencyTag(am) + if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar { + if bcpTag.moduleInApex == "" { + info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider) + if exists { + apexNameToApexExportsInfoMap[info.ApexName] = info + } + } } }) return apexNameToApexExportsInfoMap @@ -1442,24 +1481,33 @@ func artBootImagesFactory() android.Module { func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) { // Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image. - ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), dexpreoptBootJarDepTag, "dex_bootjars") + tag := bootclasspathDependencyTag{ + typ: dexpreoptBootJar, + } + ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), tag, "dex_bootjars") } func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) { - ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(m android.Module) { - hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider) - if !ok { - ctx.ModuleErrorf("Could not find information about the host variant of ART boot image") - } - installs := d.installFile(ctx, hostInstallsInfo.installs) - if len(installs) > 0 { - d.outputFile = android.OptionalPathForPath(installs[0]) - // Create a phony target that can ART run-tests can depend on. - ctx.Phony(d.Name(), installs...) - } else { - // this might be true e.g. when building with `WITH_DEXPREOPT=false` - // create an empty file so that the `art_boot_images` is known to the packaging system. - d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images")) + ctx.VisitDirectDeps(func(m android.Module) { + tag := ctx.OtherModuleDependencyTag(m) + if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar { + if bcpTag.moduleInApex != "" { + panic("unhandled moduleInApex") + } + hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider) + if !ok { + ctx.ModuleErrorf("Could not find information about the host variant of ART boot image") + } + installs := d.installFile(ctx, hostInstallsInfo.installs) + if len(installs) > 0 { + d.outputFile = android.OptionalPathForPath(installs[0]) + // Create a phony target that can ART run-tests can depend on. + ctx.Phony(d.Name(), installs...) + } else { + // this might be true e.g. when building with `WITH_DEXPREOPT=false` + // create an empty file so that the `art_boot_images` is known to the packaging system. + d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images")) + } } }) } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index dc0973cdf..fb5c325d3 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -67,15 +67,16 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig // ART boot image for testing only. Do not rely on it to make any build-time decision. artCfg := bootImageConfig{ - name: artBootImageName, - enabledIfExists: "art-bootclasspath-fragment", - stem: bootImageStem, - installDir: "apex/art_boot_images/javalib", - modules: global.TestOnlyArtBootImageJars, - preloadedClassesFile: "art/build/boot/preloaded-classes", - compilerFilter: "speed-profile", - singleImage: false, - profileImports: profileImports, + name: artBootImageName, + enabledIfExists: "art-bootclasspath-fragment", + stem: bootImageStem, + installDir: "apex/art_boot_images/javalib", + modules: global.TestOnlyArtBootImageJars, + preloadedClassesFile: "art/build/boot/preloaded-classes", + compilerFilter: "speed-profile", + singleImage: false, + profileImports: profileImports, + profileProviderModule: "art-bootclasspath-fragment", } // Framework config for the boot image extension. diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go index 44d2127fd..99b1f231f 100644 --- a/java/dexpreopt_config_test.go +++ b/java/dexpreopt_config_test.go @@ -23,6 +23,7 @@ import ( ) func TestBootImageConfig(t *testing.T) { + t.Parallel() if runtime.GOOS != "linux" { t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS) } diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go index 33c682bfa..241941eb8 100644 --- a/java/dexpreopt_config_testing.go +++ b/java/dexpreopt_config_testing.go @@ -1217,6 +1217,7 @@ func checkBootImageConfig(t *testing.T, result *android.TestResult, imageConfig } t.Run(imageConfig.name, func(t *testing.T) { + t.Parallel() nestedCheckBootImageConfig(t, result, imageConfig, mutated, expected) }) } @@ -1236,7 +1237,7 @@ func nestedCheckBootImageConfig(t *testing.T, result *android.TestResult, imageC android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip) if !mutated { - dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common") + dexBootJarModule := result.ModuleForTests(t, "dex_bootjars", "android_common") profileInstallInfo, _ := android.OtherModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider) assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls) android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String()) @@ -1246,6 +1247,7 @@ func nestedCheckBootImageConfig(t *testing.T, result *android.TestResult, imageC for i, variant := range imageConfig.variants { expectedVariant := expected.variants[i] t.Run(variant.target.Arch.ArchType.String(), func(t *testing.T) { + t.Parallel() android.AssertDeepEquals(t, "archType", expectedVariant.archType, variant.target.Arch.ArchType) android.AssertDeepEquals(t, "dexLocations", expectedVariant.dexLocations, variant.dexLocations) android.AssertDeepEquals(t, "dexLocationsDeps", expectedVariant.dexLocationsDeps, variant.dexLocationsDeps) @@ -1279,7 +1281,7 @@ func CheckMutatedFrameworkBootImageConfig(t *testing.T, result *android.TestResu // checkDexpreoptMakeVars checks the DEXPREOPT_ prefixed make vars produced by dexpreoptBootJars // singleton. func checkDexpreoptMakeVars(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) { - vars := result.MakeVarsForTesting(func(variable android.MakeVarVariable) bool { + vars := result.MakeVarsForTesting(t, func(variable android.MakeVarVariable) bool { return strings.HasPrefix(variable.Name(), "DEXPREOPT_") }) diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go index 07d0595e6..f437da02c 100644 --- a/java/dexpreopt_test.go +++ b/java/dexpreopt_test.go @@ -17,7 +17,6 @@ package java import ( "fmt" "runtime" - "strings" "testing" "android/soong/android" @@ -30,6 +29,7 @@ func init() { } func TestDexpreoptEnabled(t *testing.T) { + t.Parallel() tests := []struct { name string bp string @@ -219,6 +219,7 @@ func TestDexpreoptEnabled(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + t.Parallel() preparers := android.GroupFixturePreparers( PrepareForTestWithDexpreopt, PrepareForTestWithFakeApexMutator, @@ -238,7 +239,7 @@ func TestDexpreoptEnabled(t *testing.T) { variant += "_apex1000" } - dexpreopt := ctx.ModuleForTests(moduleName, variant).MaybeRule("dexpreopt") + dexpreopt := ctx.ModuleForTests(t, moduleName, variant).MaybeRule("dexpreopt") enabled := dexpreopt.Rule != nil if enabled != test.enabled { @@ -258,6 +259,7 @@ func enabledString(enabled bool) string { } func TestDex2oatToolDeps(t *testing.T) { + t.Parallel() if runtime.GOOS != "linux" { // The host binary paths checked below are build OS dependent. t.Skipf("Unsupported build OS %s", runtime.GOOS) @@ -273,6 +275,7 @@ func TestDex2oatToolDeps(t *testing.T) { name := fmt.Sprintf("sourceEnabled:%t,prebuiltEnabled:%t,prebuiltPreferred:%t", sourceEnabled, prebuiltEnabled, prebuiltPreferred) t.Run(name, func(t *testing.T) { + t.Parallel() result := preparers.RunTestWithBp(t, fmt.Sprintf(` cc_binary { name: "dex2oatd", @@ -296,7 +299,7 @@ func TestDex2oatToolDeps(t *testing.T) { }) } - sourceDex2oatPath := "host/linux-x86/bin/dex2oatd" + sourceDex2oatPath := "../host/linux-x86/bin/dex2oatd" prebuiltDex2oatPath := ".intermediates/prebuilt_dex2oatd/linux_glibc_x86_64/dex2oatd" testDex2oatToolDep(true, false, false, sourceDex2oatPath) @@ -305,7 +308,7 @@ func TestDex2oatToolDeps(t *testing.T) { testDex2oatToolDep(false, true, false, prebuiltDex2oatPath) } -func TestDexpreoptBuiltInstalledForApex(t *testing.T) { +func TestApexSystemServerDexpreoptInstalls(t *testing.T) { preparers := android.GroupFixturePreparers( PrepareForTestWithDexpreopt, PrepareForTestWithFakeApexMutator, @@ -322,117 +325,38 @@ func TestDexpreoptBuiltInstalledForApex(t *testing.T) { sdk_version: "current", }`) ctx := result.TestContext - module := ctx.ModuleForTests("service-foo", "android_common_apex1000") + module := ctx.ModuleForTests(t, "service-foo", "android_common_apex1000") library := module.Module().(*Library) - installs := library.dexpreopter.DexpreoptBuiltInstalledForApex() + installs := library.dexpreopter.ApexSystemServerDexpreoptInstalls() + dexJars := library.dexpreopter.ApexSystemServerDexJars() android.AssertIntEquals(t, "install count", 2, len(installs)) + android.AssertIntEquals(t, "dexjar count", 1, len(dexJars)) - android.AssertStringEquals(t, "installs[0] FullModuleName", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - installs[0].FullModuleName()) + android.AssertPathRelativeToTopEquals(t, "installs[0] OutputPathOnHost", + "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.odex", + installs[0].OutputPathOnHost) - android.AssertStringEquals(t, "installs[0] SubModuleName", - "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - installs[0].SubModuleName()) + android.AssertPathRelativeToTopEquals(t, "installs[0] InstallDirOnDevice", + "out/target/product/test_device/system/framework/oat/arm64", + installs[0].InstallDirOnDevice) - android.AssertStringEquals(t, "installs[1] FullModuleName", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - installs[1].FullModuleName()) - - android.AssertStringEquals(t, "installs[1] SubModuleName", - "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - installs[1].SubModuleName()) - - // Not an APEX system server jar. - result = preparers.RunTestWithBp(t, ` - java_library { - name: "foo", - installable: true, - srcs: ["a.java"], - sdk_version: "current", - }`) - ctx = result.TestContext - module = ctx.ModuleForTests("foo", "android_common") - library = module.Module().(*Library) - - installs = library.dexpreopter.DexpreoptBuiltInstalledForApex() - - android.AssertIntEquals(t, "install count", 0, len(installs)) -} - -func filterDexpreoptEntriesList(entriesList []android.AndroidMkEntries) []android.AndroidMkEntries { - var results []android.AndroidMkEntries - for _, entries := range entriesList { - if strings.Contains(entries.EntryMap["LOCAL_MODULE"][0], "-dexpreopt-") { - results = append(results, entries) - } - } - return results -} - -func verifyEntries(t *testing.T, message string, expectedModule string, - expectedPrebuiltModuleFile string, expectedModulePath string, expectedInstalledModuleStem string, - entries android.AndroidMkEntries) { - android.AssertStringEquals(t, message+" LOCAL_MODULE", expectedModule, - entries.EntryMap["LOCAL_MODULE"][0]) - - android.AssertStringEquals(t, message+" LOCAL_MODULE_CLASS", "ETC", - entries.EntryMap["LOCAL_MODULE_CLASS"][0]) - - android.AssertStringDoesContain(t, message+" LOCAL_PREBUILT_MODULE_FILE", - entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"][0], expectedPrebuiltModuleFile) - - android.AssertStringDoesContain(t, message+" LOCAL_MODULE_PATH", - entries.EntryMap["LOCAL_MODULE_PATH"][0], expectedModulePath) - - android.AssertStringEquals(t, message+" LOCAL_INSTALLED_MODULE_STEM", - expectedInstalledModuleStem, entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0]) - - android.AssertStringEquals(t, message+" LOCAL_NOT_AVAILABLE_FOR_PLATFORM", - "false", entries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"][0]) -} - -func TestAndroidMkEntriesForApex(t *testing.T) { - preparers := android.GroupFixturePreparers( - PrepareForTestWithDexpreopt, - PrepareForTestWithFakeApexMutator, - dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"), - ) - - // An APEX system server jar. - result := preparers.RunTestWithBp(t, ` - java_library { - name: "service-foo", - installable: true, - srcs: ["a.java"], - apex_available: ["com.android.apex1"], - sdk_version: "current", - }`) - ctx := result.TestContext - module := ctx.ModuleForTests("service-foo", "android_common_apex1000") - - entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module()) - entriesList = filterDexpreoptEntriesList(entriesList) + android.AssertStringEquals(t, "installs[0] InstallFileOnDevice", + "apex@com.android.apex1@javalib@service-foo.jar@classes.odex", + installs[0].InstallFileOnDevice) - android.AssertIntEquals(t, "entries count", 2, len(entriesList)) + android.AssertPathRelativeToTopEquals(t, "installs[1] OutputPathOnHost", + "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.vdex", + installs[1].OutputPathOnHost) - verifyEntries(t, - "entriesList[0]", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - "/dexpreopt/service-foo/oat/arm64/javalib.odex", - "/system/framework/oat/arm64", - "apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - entriesList[0]) + android.AssertPathRelativeToTopEquals(t, "installs[1] InstallDirOnDevice", + "out/target/product/test_device/system/framework/oat/arm64", + installs[1].InstallDirOnDevice) - verifyEntries(t, - "entriesList[1]", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - "/dexpreopt/service-foo/oat/arm64/javalib.vdex", - "/system/framework/oat/arm64", + android.AssertStringEquals(t, "installs[1] InstallFileOnDevice", "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - entriesList[1]) + installs[1].InstallFileOnDevice) // Not an APEX system server jar. result = preparers.RunTestWithBp(t, ` @@ -443,12 +367,14 @@ func TestAndroidMkEntriesForApex(t *testing.T) { sdk_version: "current", }`) ctx = result.TestContext - module = ctx.ModuleForTests("foo", "android_common") + module = ctx.ModuleForTests(t, "foo", "android_common") + library = module.Module().(*Library) - entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module()) - entriesList = filterDexpreoptEntriesList(entriesList) + installs = library.dexpreopter.ApexSystemServerDexpreoptInstalls() + dexJars = library.dexpreopter.ApexSystemServerDexJars() - android.AssertIntEquals(t, "entries count", 0, len(entriesList)) + android.AssertIntEquals(t, "install count", 0, len(installs)) + android.AssertIntEquals(t, "dexjar count", 0, len(dexJars)) } func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) { @@ -470,7 +396,7 @@ func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) { }`) ctx := result.TestContext - dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt") + dexpreopt := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("dexpreopt") expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/foo/profile.prof"} diff --git a/java/droiddoc.go b/java/droiddoc.go index 2dda72b0e..225f201a9 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -19,6 +19,7 @@ import ( "path/filepath" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" @@ -357,7 +358,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { deps.aidlPreprocess = sdkDep.aidl } - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -381,9 +382,9 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { deps.classpath = append(deps.classpath, dep.HeaderJars...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...) deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...) - } else if dep, ok := module.(android.SourceFileProducer); ok { - checkProducesJars(ctx, dep) - deps.classpath = append(deps.classpath, dep.Srcs()...) + } else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok { + checkProducesJars(ctx, dep, module) + deps.classpath = append(deps.classpath, dep.Srcs...) } else { ctx.ModuleErrorf("depends on non-java module %q", otherName) } @@ -874,6 +875,13 @@ type ExportedDroiddocDirProperties struct { Path *string } +type ExportedDroiddocDirInfo struct { + Deps android.Paths + Dir android.Path +} + +var ExportedDroiddocDirInfoProvider = blueprint.NewProvider[ExportedDroiddocDirInfo]() + type ExportedDroiddocDir struct { android.ModuleBase @@ -897,6 +905,11 @@ func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleCont path := String(d.properties.Path) d.dir = android.PathForModuleSrc(ctx, path) d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")}) + + android.SetProvider(ctx, ExportedDroiddocDirInfoProvider, ExportedDroiddocDirInfo{ + Dir: d.dir, + Deps: d.deps, + }) } // Defaults diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go index 9e1ebbed0..0c977bceb 100644 --- a/java/droiddoc_test.go +++ b/java/droiddoc_test.go @@ -23,6 +23,7 @@ import ( ) func TestDroiddoc(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` droiddoc_exported_dir { name: "droiddoc-templates-sdk", @@ -69,13 +70,13 @@ func TestDroiddoc(t *testing.T) { "bar-doc/a.java": nil, "bar-doc/b.java": nil, }) - barStubsOutputs := ctx.ModuleForTests("bar-stubs", "android_common").OutputFiles(ctx, t, "") + barStubsOutputs := ctx.ModuleForTests(t, "bar-stubs", "android_common").OutputFiles(ctx, t, "") if len(barStubsOutputs) != 1 { t.Errorf("Expected one output from \"bar-stubs\" got %s", barStubsOutputs) } barStubsOutput := barStubsOutputs[0] - barDoc := ctx.ModuleForTests("bar-doc", "android_common") + barDoc := ctx.ModuleForTests(t, "bar-doc", "android_common") javaDoc := barDoc.Rule("javadoc") if g, w := android.PathsRelativeToTop(javaDoc.Implicits), android.PathRelativeToTop(barStubsOutput); !inList(w, g) { t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g) @@ -97,6 +98,7 @@ func TestDroiddoc(t *testing.T) { } func TestDroiddocArgsAndFlagsCausesError(t *testing.T) { + t.Parallel() testJavaError(t, "flags is set. Cannot set args", ` droiddoc_exported_dir { name: "droiddoc-templates-sdk", diff --git a/java/droidstubs.go b/java/droidstubs.go index e955949af..caad6883e 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -20,6 +20,7 @@ import ( "regexp" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" @@ -27,6 +28,28 @@ import ( "android/soong/remoteexec" ) +type StubsInfo struct { + ApiVersionsXml android.Path + AnnotationsZip android.Path + ApiFile android.Path + RemovedApiFile android.Path +} + +type DroidStubsInfo struct { + CurrentApiTimestamp android.Path + EverythingStubsInfo StubsInfo + ExportableStubsInfo StubsInfo +} + +var DroidStubsInfoProvider = blueprint.NewProvider[DroidStubsInfo]() + +type StubsSrcInfo struct { + EverythingStubsSrcJar android.Path + ExportableStubsSrcJar android.Path +} + +var StubsSrcInfoProvider = blueprint.NewProvider[StubsSrcInfo]() + // The values allowed for Droidstubs' Api_levels_sdk_type var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"} @@ -498,9 +521,9 @@ func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.Ru } func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { - ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) { - if t, ok := m.(*ExportedDroiddocDir); ok { - cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps) + ctx.VisitDirectDepsProxyWithTag(metalavaMergeAnnotationsDirTag, func(m android.ModuleProxy) { + if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok { + cmd.FlagWithArg("--merge-qualifier-annotations ", t.Dir.String()).Implicits(t.Deps) } else { ctx.PropertyErrorf("merge_annotations_dirs", "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) @@ -509,9 +532,9 @@ func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.R } func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { - ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) { - if t, ok := m.(*ExportedDroiddocDir); ok { - cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps) + ctx.VisitDirectDepsProxyWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.ModuleProxy) { + if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok { + cmd.FlagWithArg("--merge-inclusion-annotations ", t.Dir.String()).Implicits(t.Deps) } else { ctx.PropertyErrorf("merge_inclusion_annotations_dirs", "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) @@ -525,12 +548,12 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml) apiVersions = apiVersionsXml } else { - ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) { - if s, ok := m.(*Droidstubs); ok { + ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsModuleTag, func(m android.ModuleProxy) { + if s, ok := android.OtherModuleProvider(ctx, m, DroidStubsInfoProvider); ok { if stubsType == Everything { - apiVersions = s.everythingArtifacts.apiVersionsXml + apiVersions = s.EverythingStubsInfo.ApiVersionsXml } else if stubsType == Exportable { - apiVersions = s.exportableArtifacts.apiVersionsXml + apiVersions = s.ExportableStubsInfo.ApiVersionsXml } else { ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String()) } @@ -603,18 +626,18 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an var dirs []string var extensions_dir string - ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) { - if t, ok := m.(*ExportedDroiddocDir); ok { - extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern) + ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.ModuleProxy) { + if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok { + extRegex := regexp.MustCompile(t.Dir.String() + extensionsPattern) // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps; // ideally this should be read from prebuiltApis.properties.Extensions_* - for _, dep := range t.deps { + for _, dep := range t.Deps { // Check to see if it matches an extension first. depBase := dep.Base() if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil { if extensions_dir == "" { - extensions_dir = t.dir.String() + "/extensions" + extensions_dir = t.Dir.String() + "/extensions" } cmd.Implicit(dep) } else if depBase == filename { @@ -622,23 +645,17 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an cmd.Implicit(dep) } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil { // The output api-versions.xml has been requested to include information on SDK - // extensions. That means it also needs to include - // so - // The module-lib and system-server directories should use `android-plus-updatable.jar` - // instead of `android.jar`. See AndroidPlusUpdatableJar for more information. - cmd.Implicit(dep) - } else if filename != "android.jar" && depBase == "android.jar" { - // Metalava implicitly searches these patterns: - // prebuilts/tools/common/api-versions/android-%/android.jar - // prebuilts/sdk/%/public/android.jar - // Add android.jar files from the api_levels_annotations_dirs directories to try - // to satisfy these patterns. If Metalava can't find a match for an API level - // between 1 and 28 in at least one pattern it will fail. + // extensions, i.e. updatable Apis. That means it also needs to include the history of + // those updatable APIs. Usually, they would be included in the `android.jar` file but + // unfortunately, the `module-lib` and `system-server` cannot as it would lead to build + // cycles. So, the module-lib and system-server directories contain an + // `android-plus-updatable.jar` that should be used instead of `android.jar`. See + // AndroidPlusUpdatableJar for more information. cmd.Implicit(dep) } } - dirs = append(dirs, t.dir.String()) + dirs = append(dirs, t.Dir.String()) } else { ctx.PropertyErrorf("api_levels_annotations_dirs", "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m)) @@ -646,11 +663,11 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an }) // Generate the list of --android-jar-pattern options. The order matters so the first one which - // matches will be the one that is used for a specific api level.. + // matches will be the one that is used for a specific api level. for _, sdkDir := range sdkDirs { for _, dir := range dirs { addPattern := func(jarFilename string) { - cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename)) + cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:major.minor?}/%s/%s", dir, sdkDir, jarFilename)) } if sdkDir == "module-lib" || sdkDir == "system-server" { @@ -665,6 +682,10 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an addPattern(filename) } + + if extensions_dir != "" { + cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:extension}/%s/{module}.jar", extensions_dir, sdkDir)) + } } if d.properties.Extensions_info_file != nil { @@ -673,7 +694,6 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an } info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file) cmd.Implicit(info_file) - cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir) cmd.FlagWithArg("--sdk-extensions-info ", info_file.String()) } } @@ -700,7 +720,8 @@ func metalavaUseRbe(ctx android.ModuleContext) bool { } func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths, - srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, configFiles android.Paths) *android.RuleBuilderCommand { + srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, + configFiles android.Paths, apiSurface *string) *android.RuleBuilderCommand { rule.Command().Text("rm -rf").Flag(homeDir.String()) rule.Command().Text("mkdir -p").Flag(homeDir.String()) @@ -746,6 +767,8 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs andr addMetalavaConfigFilesToCmd(cmd, configFiles) + addOptionalApiSurfaceToCmd(cmd, apiSurface) + return cmd } @@ -764,6 +787,14 @@ func addMetalavaConfigFilesToCmd(cmd *android.RuleBuilderCommand, configFiles an cmd.FlagForEachInput("--config-file ", configFiles) } +// addOptionalApiSurfaceToCmd adds --api-surface option is apiSurface is not `nil`. +func addOptionalApiSurfaceToCmd(cmd *android.RuleBuilderCommand, apiSurface *string) { + if apiSurface != nil { + cmd.Flag("--api-surface") + cmd.Flag(*apiSurface) + } +} + // Pass flagged apis related flags to metalava. When aconfig_declarations property is not // defined for a module, simply revert all flagged apis annotations. If aconfig_declarations // property is defined, apply transformations and only revert the flagged apis that are not @@ -838,7 +869,8 @@ func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *andr configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles) - cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, configFiles) + cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, + configFiles, d.properties.Api_surface) cmd.Implicits(d.Javadoc.implicits) d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi) @@ -1177,6 +1209,34 @@ func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsComm rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged") } +func (d *Droidstubs) setPhonyRules(ctx android.ModuleContext) { + if d.apiFile != nil { + ctx.Phony(d.Name(), d.apiFile) + ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.apiFile) + } + if d.removedApiFile != nil { + ctx.Phony(d.Name(), d.removedApiFile) + ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.removedApiFile) + } + if d.checkCurrentApiTimestamp != nil { + ctx.Phony(fmt.Sprintf("%s-check-current-api", d.Name()), d.checkCurrentApiTimestamp) + ctx.Phony("checkapi", d.checkCurrentApiTimestamp) + } + if d.updateCurrentApiTimestamp != nil { + ctx.Phony(fmt.Sprintf("%s-update-current-api", d.Name()), d.updateCurrentApiTimestamp) + ctx.Phony("update-api", d.updateCurrentApiTimestamp) + } + if d.checkLastReleasedApiTimestamp != nil { + ctx.Phony(fmt.Sprintf("%s-check-last-released-api", d.Name()), d.checkLastReleasedApiTimestamp) + } + if d.apiLintTimestamp != nil { + ctx.Phony(fmt.Sprintf("%s-api-lint", d.Name()), d.apiLintTimestamp) + } + if d.checkNullabilityWarningsTimestamp != nil { + ctx.Phony(fmt.Sprintf("%s-check-nullability-warnings", d.Name()), d.checkNullabilityWarningsTimestamp) + } +} + func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { deps := d.Javadoc.collectDeps(ctx) @@ -1220,6 +1280,41 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { stubCmdParams.stubsType = Exportable d.exportableStubCmd(ctx, stubCmdParams) + if String(d.properties.Check_nullability_warnings) != "" { + if d.everythingArtifacts.nullabilityWarningsFile == nil { + ctx.PropertyErrorf("check_nullability_warnings", + "Cannot specify check_nullability_warnings unless validating nullability") + } + + checkNullabilityWarningsPath := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings)) + + d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp") + + msg := fmt.Sprintf(`\n******************************\n`+ + `The warnings encountered during nullability annotation validation did\n`+ + `not match the checked in file of expected warnings. The diffs are shown\n`+ + `above. You have two options:\n`+ + ` 1. Resolve the differences by editing the nullability annotations.\n`+ + ` 2. Update the file of expected warnings by running:\n`+ + ` cp %s %s\n`+ + ` and submitting the updated file as part of your change.`, + d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarningsPath) + + rule := android.NewRuleBuilder(pctx, ctx) + + rule.Command(). + Text("("). + Text("diff").Input(checkNullabilityWarningsPath).Input(d.everythingArtifacts.nullabilityWarningsFile). + Text("&&"). + Text("touch").Output(d.checkNullabilityWarningsTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build("nullabilityWarningsCheck", "nullability warnings check") + } + if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") { if len(d.Javadoc.properties.Out) > 0 { @@ -1269,13 +1364,25 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+ `******************************\n`, ctx.ModuleName()) - rule.Command(). + cmd := rule.Command(). Text("touch").Output(d.checkCurrentApiTimestamp). Text(") || ("). Text("echo").Flag("-e").Flag(`"` + msg + `"`). Text("; exit 38"). Text(")") + if d.apiLintTimestamp != nil { + cmd.Validation(d.apiLintTimestamp) + } + + if d.checkLastReleasedApiTimestamp != nil { + cmd.Validation(d.checkLastReleasedApiTimestamp) + } + + if d.checkNullabilityWarningsTimestamp != nil { + cmd.Validation(d.checkNullabilityWarningsTimestamp) + } + rule.Build("metalavaCurrentApiCheck", "check current API") d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp") @@ -1305,42 +1412,49 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("metalavaCurrentApiUpdate", "update current API") } - if String(d.properties.Check_nullability_warnings) != "" { - if d.everythingArtifacts.nullabilityWarningsFile == nil { - ctx.PropertyErrorf("check_nullability_warnings", - "Cannot specify check_nullability_warnings unless validating nullability") - } - - checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings)) - - d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp") + droidInfo := DroidStubsInfo{ + CurrentApiTimestamp: d.CurrentApiTimestamp(), + EverythingStubsInfo: StubsInfo{}, + ExportableStubsInfo: StubsInfo{}, + } + setDroidInfo(ctx, d, &droidInfo.EverythingStubsInfo, Everything) + setDroidInfo(ctx, d, &droidInfo.ExportableStubsInfo, Exportable) + android.SetProvider(ctx, DroidStubsInfoProvider, droidInfo) - msg := fmt.Sprintf(`\n******************************\n`+ - `The warnings encountered during nullability annotation validation did\n`+ - `not match the checked in file of expected warnings. The diffs are shown\n`+ - `above. You have two options:\n`+ - ` 1. Resolve the differences by editing the nullability annotations.\n`+ - ` 2. Update the file of expected warnings by running:\n`+ - ` cp %s %s\n`+ - ` and submitting the updated file as part of your change.`, - d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings) + android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{ + EverythingStubsSrcJar: d.stubsSrcJar, + ExportableStubsSrcJar: d.exportableStubsSrcJar, + }) - rule := android.NewRuleBuilder(pctx, ctx) + d.setOutputFiles(ctx) - rule.Command(). - Text("("). - Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile). - Text("&&"). - Text("touch").Output(d.checkNullabilityWarningsTimestamp). - Text(") || ("). - Text("echo").Flag("-e").Flag(`"` + msg + `"`). - Text("; exit 38"). - Text(")") + d.setPhonyRules(ctx) - rule.Build("nullabilityWarningsCheck", "nullability warnings check") + if d.apiLintTimestamp != nil { + if d.apiLintReport != nil { + ctx.DistForGoalsWithFilename( + []string{fmt.Sprintf("%s-api-lint", d.Name()), "droidcore"}, + d.apiLintReport, + fmt.Sprintf("apilint/%s-lint-report.txt", d.Name()), + ) + } } +} - d.setOutputFiles(ctx) +func setDroidInfo(ctx android.ModuleContext, d *Droidstubs, info *StubsInfo, typ StubsType) { + if typ == Everything { + info.ApiFile = d.apiFile + info.RemovedApiFile = d.removedApiFile + info.AnnotationsZip = d.everythingArtifacts.annotationsZip + info.ApiVersionsXml = d.everythingArtifacts.apiVersionsXml + } else if typ == Exportable { + info.ApiFile = d.exportableApiFile + info.RemovedApiFile = d.exportableRemovedApiFile + info.AnnotationsZip = d.exportableArtifacts.annotationsZip + info.ApiVersionsXml = d.exportableArtifacts.apiVersionsXml + } else { + ctx.ModuleErrorf("failed to set ApiVersionsXml, stubs type not supported: %d", typ) + } } // This method sets the outputFiles property, which is used to set the @@ -1508,6 +1622,11 @@ func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleCon p.stubsSrcJar = outPath } + android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{ + EverythingStubsSrcJar: p.stubsSrcJar, + ExportableStubsSrcJar: p.stubsSrcJar, + }) + ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "") // prebuilt droidstubs does not output "exportable" stubs. // Output the "everything" stubs srcjar file if the tag is ".exportable". diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index 1e8362cf2..dfdf87703 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -27,6 +27,7 @@ import ( ) func TestDroidstubs(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` droiddoc_exported_dir { name: "droiddoc-templates-sdk", @@ -82,13 +83,13 @@ func TestDroidstubs(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, c.moduleName, "android_common") manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest) cmdline := String(sboxProto.Commands[0].Command) android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml) if c.expectedJarFilename != "" { - expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename + expected := "--android-jar-pattern ./{version:major.minor?}/public/" + c.expectedJarFilename if !strings.Contains(cmdline, expected) { t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline) } @@ -131,7 +132,7 @@ func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string { "foo-doc/a.java": nil, }) - m := ctx.ModuleForTests("foo-stubs", "android_common") + m := ctx.ModuleForTests(t, "foo-stubs", "android_common") manifest := m.Output("metalava.sbox.textproto") cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command) r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`) @@ -139,35 +140,38 @@ func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string { } func TestPublicDroidstubs(t *testing.T) { + t.Parallel() patterns := getAndroidJarPatternsForDroidstubs(t, "public") android.AssertArrayString(t, "order of patterns", []string{ - "--android-jar-pattern somedir/%/public/android.jar", - "--android-jar-pattern someotherdir/%/public/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar", }, patterns) } func TestSystemDroidstubs(t *testing.T) { + t.Parallel() patterns := getAndroidJarPatternsForDroidstubs(t, "system") android.AssertArrayString(t, "order of patterns", []string{ - "--android-jar-pattern somedir/%/system/android.jar", - "--android-jar-pattern someotherdir/%/system/android.jar", - "--android-jar-pattern somedir/%/public/android.jar", - "--android-jar-pattern someotherdir/%/public/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar", }, patterns) } func TestModuleLibDroidstubs(t *testing.T) { + t.Parallel() patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib") android.AssertArrayString(t, "order of patterns", []string{ - "--android-jar-pattern somedir/%/module-lib/android.jar", - "--android-jar-pattern someotherdir/%/module-lib/android.jar", - "--android-jar-pattern somedir/%/system/android.jar", - "--android-jar-pattern someotherdir/%/system/android.jar", - "--android-jar-pattern somedir/%/public/android.jar", - "--android-jar-pattern someotherdir/%/public/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar", }, patterns) } @@ -175,14 +179,14 @@ func TestSystemServerDroidstubs(t *testing.T) { patterns := getAndroidJarPatternsForDroidstubs(t, "system-server") android.AssertArrayString(t, "order of patterns", []string{ - "--android-jar-pattern somedir/%/system-server/android.jar", - "--android-jar-pattern someotherdir/%/system-server/android.jar", - "--android-jar-pattern somedir/%/module-lib/android.jar", - "--android-jar-pattern someotherdir/%/module-lib/android.jar", - "--android-jar-pattern somedir/%/system/android.jar", - "--android-jar-pattern someotherdir/%/system/android.jar", - "--android-jar-pattern somedir/%/public/android.jar", - "--android-jar-pattern someotherdir/%/public/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/system-server/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/system-server/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar", + "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar", + "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar", }, patterns) } @@ -206,7 +210,7 @@ func TestDroidstubsSandbox(t *testing.T) { "bar-doc/a.java": nil, }) - m := ctx.ModuleForTests("bar-stubs", "android_common") + m := ctx.ModuleForTests(t, "bar-stubs", "android_common") metalava := m.Rule("metalava") if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) { t.Errorf("Expected inputs %q, got %q", w, g) @@ -267,7 +271,7 @@ func TestDroidstubsWithSystemModules(t *testing.T) { } func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) { - metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava") + metalavaRule := ctx.ModuleForTests(t, moduleName, "android_common").Rule("metalava") var systemJars []string for _, i := range metalavaRule.Implicits { systemJars = append(systemJars, i.Base()) @@ -300,10 +304,10 @@ func TestDroidstubsWithSdkExtensions(t *testing.T) { "sdk/extensions/1/public/some-mainline-module-stubs.jar": nil, "sdk/extensions/info.txt": nil, }) - m := ctx.ModuleForTests("baz-stubs", "android_common") + m := ctx.ModuleForTests(t, "baz-stubs", "android_common") manifest := m.Output("metalava.sbox.textproto") cmdline := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command) - android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions") + android.AssertStringDoesContain(t, "android-jar-pattern present", cmdline, "--android-jar-pattern sdk/extensions/{version:extension}/public/{module}.jar") android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt") } @@ -328,7 +332,7 @@ func TestDroidStubsApiContributionGeneration(t *testing.T) { }, ) - ctx.ModuleForTests("foo.api.contribution", "") + ctx.ModuleForTests(t, "foo.api.contribution", "") } func TestGeneratedApiContributionVisibilityTest(t *testing.T) { @@ -362,7 +366,7 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) { }, ) - ctx.ModuleForTests("bar", "android_common") + ctx.ModuleForTests(t, "bar", "android_common") } func TestAconfigDeclarations(t *testing.T) { @@ -404,7 +408,7 @@ func TestAconfigDeclarations(t *testing.T) { android.AssertBoolEquals(t, "foo expected to depend on bar", CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true) - m := result.ModuleForTests("foo", "android_common") + m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") @@ -454,7 +458,7 @@ func TestReleaseExportRuntimeApis(t *testing.T) { } `) - m := result.ModuleForTests("foo", "android_common") + m := result.ModuleForTests(t, "foo", "android_common") rule := m.Output("released-flagged-apis-exportable.txt") exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'" diff --git a/java/fuzz.go b/java/fuzz.go index 90f09a899..5973957a2 100644 --- a/java/fuzz.go +++ b/java/fuzz.go @@ -63,7 +63,7 @@ func JavaFuzzFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) module.Module.sourceProperties.Top_level_test_target = true @@ -107,23 +107,7 @@ func (j *JavaFuzzTest) DepsMutator(ctx android.BottomUpMutatorContext) { } func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { - if j.fuzzPackagedModule.FuzzProperties.Corpus != nil { - j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus) - } - if j.fuzzPackagedModule.FuzzProperties.Device_common_corpus != nil { - j.fuzzPackagedModule.Corpus = append(j.fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Device_common_corpus)...) - } - if j.fuzzPackagedModule.FuzzProperties.Data != nil { - j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data) - } - if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil { - j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary) - } - if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil { - configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json") - android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String()) - j.fuzzPackagedModule.Config = configPath - } + j.fuzzPackagedModule = cc.PackageFuzzModule(ctx, j.fuzzPackagedModule) _, sharedDeps := cc.CollectAllSharedDependencies(ctx) for _, dep := range sharedDeps { diff --git a/java/fuzz_test.go b/java/fuzz_test.go index f29c91327..8cbe873ad 100644 --- a/java/fuzz_test.go +++ b/java/fuzz_test.go @@ -30,6 +30,7 @@ var prepForJavaFuzzTest = android.GroupFixturePreparers( ) func TestJavaFuzz(t *testing.T) { + t.Parallel() result := prepForJavaFuzzTest.RunTestWithBp(t, ` java_fuzz { name: "foo", @@ -63,14 +64,14 @@ func TestJavaFuzz(t *testing.T) { osCommonTarget := result.Config.BuildOSCommonTarget.String() - javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac") - combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac") + javac := result.ModuleForTests(t, "foo", osCommonTarget).Rule("javac") + combineJar := result.ModuleForTests(t, "foo", osCommonTarget).Description("for javac") if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) } - baz := result.ModuleForTests("baz", osCommonTarget).Rule("javac").Output.String() + baz := result.ModuleForTests(t, "baz", osCommonTarget).Rule("javac").Output.String() barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac-header", "bar.jar") bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac-header", "baz.jar") @@ -82,7 +83,7 @@ func TestJavaFuzz(t *testing.T) { } ctx := result.TestContext - foo := ctx.ModuleForTests("foo", osCommonTarget).Module().(*JavaFuzzTest) + foo := ctx.ModuleForTests(t, "foo", osCommonTarget).Module().(*JavaFuzzTest) expected := "lib64/libjni.so" if runtime.GOOS == "darwin" { diff --git a/java/gen.go b/java/gen.go index 1b4f4c7dc..aab841851 100644 --- a/java/gen.go +++ b/java/gen.go @@ -26,15 +26,14 @@ import ( ) func init() { - pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py") - pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py") + pctx.HostBinToolVariable("logtagsCmd", "java-event-log-tags") } var ( logtags = pctx.AndroidStaticRule("logtags", blueprint.RuleParams{ Command: "$logtagsCmd -o $out $in", - CommandDeps: []string{"$logtagsCmd", "$logtagsLib"}, + CommandDeps: []string{"$logtagsCmd"}, }) ) diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go index a5c4be111..e5ee5861e 100644 --- a/java/generated_java_library_test.go +++ b/java/generated_java_library_test.go @@ -52,6 +52,7 @@ func testGenLib(t *testing.T, errorHandler android.FixtureErrorHandler, bp strin } func TestGenLib(t *testing.T) { + t.Parallel() bp := ` test_java_gen_lib { name: "javagenlibtest", @@ -60,6 +61,6 @@ func TestGenLib(t *testing.T) { ` result := testGenLib(t, android.FixtureExpectsNoErrors, bp) - javagenlibtest := result.ModuleForTests("javagenlibtest", "android_common").Module().(*GeneratedJavaLibraryModule) + javagenlibtest := result.ModuleForTests(t, "javagenlibtest", "android_common").Module().(*GeneratedJavaLibraryModule) android.AssertPathsEndWith(t, "Generated_srcjars", []string{"/blah.srcjar"}, javagenlibtest.Library.properties.Generated_srcjars) } diff --git a/java/genrule_combiner.go b/java/genrule_combiner.go new file mode 100644 index 000000000..357dc2c76 --- /dev/null +++ b/java/genrule_combiner.go @@ -0,0 +1,252 @@ +// Copyright 2019 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 ( + "fmt" + "io" + + "android/soong/android" + "android/soong/dexpreopt" + + "github.com/google/blueprint/depset" + "github.com/google/blueprint/proptools" +) + +type GenruleCombiner struct { + android.ModuleBase + android.DefaultableModuleBase + + genruleCombinerProperties GenruleCombinerProperties + + headerJars android.Paths + implementationJars android.Paths + implementationAndResourceJars android.Paths + resourceJars android.Paths + aconfigProtoFiles android.Paths + + srcJarArgs []string + srcJarDeps android.Paths + + headerDirs android.Paths + + combinedHeaderJar android.Path + combinedImplementationJar android.Path +} + +type GenruleCombinerProperties struct { + // List of modules whose implementation (and resources) jars will be visible to modules + // that depend on this module. + Static_libs proptools.Configurable[[]string] `android:"arch_variant"` + + // List of modules whose header jars will be visible to modules that depend on this module. + Headers proptools.Configurable[[]string] `android:"arch_variant"` +} + +// java_genrule_combiner provides the implementation and resource jars from `static_libs`, with +// the header jars from `headers`. +// +// This is useful when a java_genrule is used to change the implementation of a java library +// without requiring a change in the header jars. +func GenruleCombinerFactory() android.Module { + module := &GenruleCombiner{} + + module.AddProperties(&module.genruleCombinerProperties) + InitJavaModule(module, android.HostAndDeviceSupported) + return module +} + +var genruleCombinerHeaderDepTag = dependencyTag{name: "genrule_combiner_header"} + +func (j *GenruleCombiner) DepsMutator(ctx android.BottomUpMutatorContext) { + ctx.AddVariationDependencies(nil, staticLibTag, + j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...) + ctx.AddVariationDependencies(nil, genruleCombinerHeaderDepTag, + j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...) +} + +func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if len(j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)) < 1 { + ctx.PropertyErrorf("static_libs", "at least one dependency is required") + } + + if len(j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)) < 1 { + ctx.PropertyErrorf("headers", "at least one dependency is required") + } + + var transitiveHeaderJars []depset.DepSet[android.Path] + var transitiveImplementationJars []depset.DepSet[android.Path] + var transitiveResourceJars []depset.DepSet[android.Path] + var sdkVersion android.SdkSpec + var stubsLinkType StubsLinkType + moduleWithSdkDepInfo := &ModuleWithSdkDepInfo{} + + // Collect the headers first, so that aconfig flag values for the libraries will override + // values from the headers (if they are different). + ctx.VisitDirectDepsWithTag(genruleCombinerHeaderDepTag, func(m android.Module) { + if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { + j.headerJars = append(j.headerJars, dep.HeaderJars...) + + j.srcJarArgs = append(j.srcJarArgs, dep.SrcJarArgs...) + j.srcJarDeps = append(j.srcJarDeps, dep.SrcJarDeps...) + j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...) + sdkVersion = dep.SdkVersion + stubsLinkType = dep.StubsLinkType + *moduleWithSdkDepInfo = *dep.ModuleWithSdkDepInfo + + transitiveHeaderJars = append(transitiveHeaderJars, dep.TransitiveStaticLibsHeaderJars) + } else if dep, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok { + j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...) + } else { + ctx.PropertyErrorf("headers", "module %q cannot be used as a dependency", ctx.OtherModuleName(m)) + } + }) + ctx.VisitDirectDepsWithTag(staticLibTag, func(m android.Module) { + if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { + j.implementationJars = append(j.implementationJars, dep.ImplementationJars...) + j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.ImplementationAndResourcesJars...) + j.resourceJars = append(j.resourceJars, dep.ResourceJars...) + + transitiveImplementationJars = append(transitiveImplementationJars, dep.TransitiveStaticLibsImplementationJars) + transitiveResourceJars = append(transitiveResourceJars, dep.TransitiveStaticLibsResourceJars) + j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...) + } else if dep, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok { + // This is provided by `java_genrule` modules. + j.implementationJars = append(j.implementationJars, dep.DefaultOutputFiles...) + j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.DefaultOutputFiles...) + stubsLinkType = Implementation + } else { + ctx.PropertyErrorf("static_libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m)) + } + }) + + jarName := ctx.ModuleName() + ".jar" + + if len(j.implementationAndResourceJars) > 1 { + outputFile := android.PathForModuleOut(ctx, "combined", jarName) + TransformJarsToJar(ctx, outputFile, "combine", j.implementationAndResourceJars, + android.OptionalPath{}, false, nil, nil) + j.combinedImplementationJar = outputFile + } else if len(j.implementationAndResourceJars) == 1 { + j.combinedImplementationJar = j.implementationAndResourceJars[0] + } + + if len(j.headerJars) > 1 { + outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName) + TransformJarsToJar(ctx, outputFile, "turbine combine", j.headerJars, + android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"}) + j.combinedHeaderJar = outputFile + j.headerDirs = append(j.headerDirs, android.PathForModuleOut(ctx, "turbine-combined")) + } else if len(j.headerJars) == 1 { + j.combinedHeaderJar = j.headerJars[0] + } + + javaInfo := &JavaInfo{ + HeaderJars: android.Paths{j.combinedHeaderJar}, + LocalHeaderJars: android.Paths{j.combinedHeaderJar}, + TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, android.Paths{j.combinedHeaderJar}, transitiveHeaderJars), + TransitiveStaticLibsImplementationJars: depset.New(depset.PREORDER, android.Paths{j.combinedImplementationJar}, transitiveImplementationJars), + TransitiveStaticLibsResourceJars: depset.New(depset.PREORDER, nil, transitiveResourceJars), + GeneratedSrcjars: android.Paths{j.combinedImplementationJar}, + ImplementationAndResourcesJars: android.Paths{j.combinedImplementationJar}, + ImplementationJars: android.Paths{j.combinedImplementationJar}, + ModuleWithSdkDepInfo: moduleWithSdkDepInfo, + ResourceJars: j.resourceJars, + OutputFile: j.combinedImplementationJar, + SdkVersion: sdkVersion, + SrcJarArgs: j.srcJarArgs, + SrcJarDeps: j.srcJarDeps, + StubsLinkType: stubsLinkType, + AconfigIntermediateCacheOutputPaths: j.aconfigProtoFiles, + } + setExtraJavaInfo(ctx, j, javaInfo) + ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, "") + ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, android.DefaultDistTag) + ctx.SetOutputFiles(javaInfo.ImplementationAndResourcesJars, ".jar") + ctx.SetOutputFiles(javaInfo.HeaderJars, ".hjar") + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + +} + +func (j *GenruleCombiner) GeneratedSourceFiles() android.Paths { + return append(android.Paths{}, j.combinedImplementationJar) +} + +func (j *GenruleCombiner) GeneratedHeaderDirs() android.Paths { + return append(android.Paths{}, j.headerDirs...) +} + +func (j *GenruleCombiner) GeneratedDeps() android.Paths { + return append(android.Paths{}, j.combinedImplementationJar) +} + +func (j *GenruleCombiner) Srcs() android.Paths { + return append(android.Paths{}, j.implementationAndResourceJars...) +} + +func (j *GenruleCombiner) HeaderJars() android.Paths { + return j.headerJars +} + +func (j *GenruleCombiner) ImplementationAndResourcesJars() android.Paths { + return j.implementationAndResourceJars +} + +func (j *GenruleCombiner) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path { + return nil +} + +func (j *GenruleCombiner) DexJarInstallPath() android.Path { + return nil +} + +func (j *GenruleCombiner) AidlIncludeDirs() android.Paths { + return nil +} + +func (j *GenruleCombiner) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { + return nil +} + +func (j *GenruleCombiner) JacocoReportClassesFile() android.Path { + return nil +} + +func (j *GenruleCombiner) AndroidMk() android.AndroidMkData { + return android.AndroidMkData{ + Class: "JAVA_LIBRARIES", + OutputFile: android.OptionalPathForPath(j.combinedImplementationJar), + // Make does not support Windows Java modules + Disabled: j.Os() == android.Windows, + Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", + Extra: []android.AndroidMkExtraFunc{ + func(w io.Writer, outputFile android.Path) { + fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") + fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", j.combinedHeaderJar.String()) + fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", j.combinedImplementationJar.String()) + }, + }, + } +} + +// implement the following interface for IDE completion. +var _ android.IDEInfo = (*GenruleCombiner)(nil) + +func (j *GenruleCombiner) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) { + ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...) + ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...) + ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...) + ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...) +} diff --git a/java/genrule_combiner_test.go b/java/genrule_combiner_test.go new file mode 100644 index 000000000..7d024cfec --- /dev/null +++ b/java/genrule_combiner_test.go @@ -0,0 +1,237 @@ +// Copyright 2018 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "reflect" + "testing" + + "android/soong/android" +) + +func TestJarGenruleCombinerSingle(t *testing.T) { + t.Parallel() + t.Helper() + ctx := prepareForJavaTest.RunTestWithBp(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + } + + java_genrule { + name: "gen", + tool_files: ["b.java"], + cmd: "$(location b.java) $(in) $(out)", + out: ["gen.jar"], + srcs: [":foo"], + } + + java_genrule_combiner { + name: "jarcomb", + static_libs: ["gen"], + headers: ["foo"], + } + + java_library { + name: "bar", + static_libs: ["jarcomb"], + srcs: ["c.java"], + } + + java_library { + name: "baz", + libs: ["jarcomb"], + srcs: ["c.java"], + } + `).TestContext + + fooMod := ctx.ModuleForTests(t, "foo", "android_common") + fooCombined := fooMod.Output("turbine-combined/foo.jar") + fooOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), fooMod.Module(), android.OutputFilesProvider) + fooHeaderJars := fooOutputFiles.TaggedOutputFiles[".hjar"] + + genMod := ctx.ModuleForTests(t, "gen", "android_common") + gen := genMod.Output("gen.jar") + + jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common") + jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider) + jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider) + + // Confirm that jarcomb simply forwards the jarcomb implementation and the foo headers. + if len(jarcombOutputFiles.DefaultOutputFiles) != 1 || + android.PathRelativeToTop(jarcombOutputFiles.DefaultOutputFiles[0]) != android.PathRelativeToTop(gen.Output) { + t.Errorf("jarcomb Implementation %v is not [%q]", + android.PathsRelativeToTop(jarcombOutputFiles.DefaultOutputFiles), android.PathRelativeToTop(gen.Output)) + } + jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"] + if !reflect.DeepEqual(jarcombHeaderJars, fooHeaderJars) { + t.Errorf("jarcomb Header jar %v is not %q", + jarcombHeaderJars, fooHeaderJars) + } + + // Confirm that JavaInfoProvider agrees. + if len(jarcombInfo.ImplementationJars) != 1 || + android.PathRelativeToTop(jarcombInfo.ImplementationJars[0]) != android.PathRelativeToTop(gen.Output) { + t.Errorf("jarcomb ImplementationJars %v is not [%q]", + android.PathsRelativeToTop(jarcombInfo.ImplementationJars), android.PathRelativeToTop(gen.Output)) + } + if len(jarcombInfo.HeaderJars) != 1 || + android.PathRelativeToTop(jarcombInfo.HeaderJars[0]) != android.PathRelativeToTop(fooCombined.Output) { + t.Errorf("jarcomb HeaderJars %v is not [%q]", + android.PathsRelativeToTop(jarcombInfo.HeaderJars), android.PathRelativeToTop(fooCombined.Output)) + } + + barMod := ctx.ModuleForTests(t, "bar", "android_common") + bar := barMod.Output("javac/bar.jar") + barCombined := barMod.Output("combined/bar.jar") + + // Confirm that bar uses the Implementation from gen and headerJars from foo. + if len(barCombined.Inputs) != 2 || + barCombined.Inputs[0].String() != bar.Output.String() || + barCombined.Inputs[1].String() != gen.Output.String() { + t.Errorf("bar combined jar inputs %v is not [%q, %q]", + barCombined.Inputs.Strings(), bar.Output.String(), gen.Output.String()) + } + + bazMod := ctx.ModuleForTests(t, "baz", "android_common") + baz := bazMod.Output("javac/baz.jar") + + string_in_list := func(s string, l []string) bool { + for _, v := range l { + if s == v { + return true + } + } + return false + } + + // Confirm that baz uses the headerJars from foo. + bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits) + for _, v := range android.PathsRelativeToTop(fooHeaderJars) { + if !string_in_list(v, bazImplicitsRel) { + t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v) + } + } +} + +func TestJarGenruleCombinerMulti(t *testing.T) { + t.Parallel() + t.Helper() + ctx := prepareForJavaTest.RunTestWithBp(t, ` + java_library { + name: "foo1", + srcs: ["foo1_a.java"], + } + + java_library { + name: "foo2", + srcs: ["foo2_a.java"], + } + + java_genrule { + name: "gen1", + tool_files: ["b.java"], + cmd: "$(location b.java) $(in) $(out)", + out: ["gen1.jar"], + srcs: [":foo1"], + } + + java_genrule { + name: "gen2", + tool_files: ["b.java"], + cmd: "$(location b.java) $(in) $(out)", + out: ["gen2.jar"], + srcs: [":foo2"], + } + + // Combine multiple java_genrule modules. + java_genrule_combiner { + name: "jarcomb", + static_libs: ["gen1", "gen2"], + headers: ["foo1", "foo2"], + } + + java_library { + name: "bar", + static_libs: ["jarcomb"], + srcs: ["c.java"], + } + + java_library { + name: "baz", + libs: ["jarcomb"], + srcs: ["c.java"], + } + `).TestContext + + gen1Mod := ctx.ModuleForTests(t, "gen1", "android_common") + gen1 := gen1Mod.Output("gen1.jar") + gen2Mod := ctx.ModuleForTests(t, "gen2", "android_common") + gen2 := gen2Mod.Output("gen2.jar") + + jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common") + jarcomb := jarcombMod.Output("combined/jarcomb.jar") + jarcombTurbine := jarcombMod.Output("turbine-combined/jarcomb.jar") + _ = jarcombTurbine + jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider) + _ = jarcombInfo + jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider) + jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"] + + if len(jarcomb.Inputs) != 2 || + jarcomb.Inputs[0].String() != gen1.Output.String() || + jarcomb.Inputs[1].String() != gen2.Output.String() { + t.Errorf("jarcomb inputs %v are not [%q, %q]", + jarcomb.Inputs.Strings(), gen1.Output.String(), gen2.Output.String()) + } + + if len(jarcombHeaderJars) != 1 || + android.PathRelativeToTop(jarcombHeaderJars[0]) != android.PathRelativeToTop(jarcombTurbine.Output) { + t.Errorf("jarcomb Header jars %v is not [%q]", + android.PathsRelativeToTop(jarcombHeaderJars), android.PathRelativeToTop(jarcombTurbine.Output)) + } + + barMod := ctx.ModuleForTests(t, "bar", "android_common") + bar := barMod.Output("javac/bar.jar") + barCombined := barMod.Output("combined/bar.jar") + + // Confirm that bar uses the Implementation and Headers from jarcomb. + if len(barCombined.Inputs) != 2 || + barCombined.Inputs[0].String() != bar.Output.String() || + barCombined.Inputs[1].String() != jarcomb.Output.String() { + t.Errorf("bar combined jar inputs %v is not [%q, %q]", + barCombined.Inputs.Strings(), bar.Output.String(), jarcomb.Output.String()) + } + + bazMod := ctx.ModuleForTests(t, "baz", "android_common") + baz := bazMod.Output("javac/baz.jar") + + string_in_list := func(s string, l []string) bool { + for _, v := range l { + if s == v { + return true + } + } + return false + } + + // Confirm that baz uses the headerJars from foo. + bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits) + for _, v := range android.PathsRelativeToTop(jarcombHeaderJars) { + if !string_in_list(v, bazImplicitsRel) { + t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v) + } + } +} diff --git a/java/genrule_test.go b/java/genrule_test.go index 1c294b286..c112e4503 100644 --- a/java/genrule_test.go +++ b/java/genrule_test.go @@ -31,6 +31,7 @@ func testGenruleContext(config android.Config) *android.TestContext { } func TestGenruleCmd(t *testing.T) { + t.Parallel() fs := map[string][]byte{ "tool": nil, "foo": nil, @@ -56,7 +57,7 @@ func TestGenruleCmd(t *testing.T) { t.Fatal(errs) } - gen := ctx.ModuleForTests("gen", "android_common").Output("out") + gen := ctx.ModuleForTests(t, "gen", "android_common").Output("out") expected := []string{"foo"} if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) { t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings()) @@ -64,6 +65,7 @@ func TestGenruleCmd(t *testing.T) { } func TestJarGenrules(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -91,11 +93,11 @@ func TestJarGenrules(t *testing.T) { } `) - foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar") - jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar") - bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar") - baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar") - barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar") + foo := ctx.ModuleForTests(t, "foo", "android_common").Output("javac/foo.jar") + jargen := ctx.ModuleForTests(t, "jargen", "android_common").Output("jargen.jar") + bar := ctx.ModuleForTests(t, "bar", "android_common").Output("javac/bar.jar") + baz := ctx.ModuleForTests(t, "baz", "android_common").Output("javac/baz.jar") + barCombined := ctx.ModuleForTests(t, "bar", "android_common").Output("combined/bar.jar") if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) { t.Errorf("expected jargen inputs [%q], got %q", w, g) diff --git a/java/hiddenapi.go b/java/hiddenapi.go index b1a9debe1..c9a1f2bbe 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -97,7 +97,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ // Save the classes jars even if this is not active as they may be used by modular hidden API // processing. classesJars := android.Paths{classesJar} - ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(hiddenApiAnnotationsTag, func(dep android.ModuleProxy) { if javaInfo, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { classesJars = append(classesJars, javaInfo.ImplementationJars...) } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 7d21b7a61..2c8694237 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -171,11 +171,11 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu // Now match the apex part of the boot image configuration. requiredApex := configuredBootJars.Apex(index) if android.IsConfiguredJarForPlatform(requiredApex) { - if len(apexInfo.InApexVariants) != 0 { + if apexInfo.ApexVariationName != "" { // A platform variant is required but this is for an apex so ignore it. return false } - } else if !apexInfo.InApexVariant(requiredApex) { + } else if apexInfo.BaseApexName != requiredApex { // An apex variant for a specific apex is required but this is the wrong apex. return false } diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index afe8b4c8e..147f326c7 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -44,6 +44,7 @@ var hiddenApiFixtureFactory = android.GroupFixturePreparers( ) func TestHiddenAPISingleton(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), @@ -56,13 +57,14 @@ func TestHiddenAPISingleton(t *testing.T) { } `) - hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenAPI := result.ModuleForTests(t, "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) } func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) { + t.Parallel() expectedErrorMessage := "module prebuilt_foo{os:android,arch:common} does not provide a dex jar" android.GroupFixturePreparers( @@ -86,6 +88,7 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) } func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), @@ -98,13 +101,14 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { } `) - hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenAPI := result.ModuleForTests(t, "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) } func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), @@ -124,7 +128,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { } `) - hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenAPI := result.ModuleForTests(t, "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) @@ -134,6 +138,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { } func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), @@ -153,7 +158,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { } `) - hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenAPI := result.ModuleForTests(t, "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) @@ -163,6 +168,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { } func TestHiddenAPISingletonSdks(t *testing.T) { + t.Parallel() testCases := []struct { name string unbundledBuild bool @@ -213,7 +219,7 @@ func TestHiddenAPISingletonSdks(t *testing.T) { } `) - hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenAPI := result.ModuleForTests(t, "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) @@ -246,6 +252,7 @@ func generateSdkDexPath(module string, unbundled bool) string { } func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) { + t.Parallel() // The idea behind this test is to ensure that when the build is // confugured with a PrebuiltHiddenApiDir that the rules for the @@ -272,9 +279,9 @@ func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) { expectedCpOutput := "out/soong/hiddenapi/hiddenapi-flags.csv" expectedFlagsCsv := "out/soong/hiddenapi/hiddenapi-flags.csv" - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") - hiddenAPI := result.SingletonForTests("hiddenapi") + hiddenAPI := result.SingletonForTests(t, "hiddenapi") cpRule := hiddenAPI.Rule("Cp") actualCpInput := cpRule.BuildParams.Input actualCpOutput := cpRule.BuildParams.Output @@ -289,6 +296,7 @@ func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) { } func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, @@ -310,7 +318,7 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) { `) checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) { - moduleForTests := result.ModuleForTests(name+".impl", "android_common") + moduleForTests := result.ModuleForTests(t, name+".impl", "android_common") encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex") actualUnencodedDexJar := encodeDexRule.Input @@ -324,10 +332,7 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) { android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar) } - // The java_library embedded with the java_sdk_library must be dex encoded. - t.Run("foo", func(t *testing.T) { - expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar" - expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar" - checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar) - }) + expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar" + expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar" + checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar) } diff --git a/java/jacoco_test.go b/java/jacoco_test.go index 1882908ca..58a091e4c 100644 --- a/java/jacoco_test.go +++ b/java/jacoco_test.go @@ -17,6 +17,7 @@ package java import "testing" func TestJacocoFilterToSpecs(t *testing.T) { + t.Parallel() testCases := []struct { name, in, out string }{ @@ -54,6 +55,7 @@ func TestJacocoFilterToSpecs(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() got, err := jacocoFilterToSpec(testCase.in) if err != nil { t.Error(err) @@ -66,6 +68,7 @@ func TestJacocoFilterToSpecs(t *testing.T) { } func TestJacocoFiltersToZipCommand(t *testing.T) { + t.Parallel() testCases := []struct { name string includes, excludes []string @@ -96,6 +99,7 @@ func TestJacocoFiltersToZipCommand(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() got := jacocoFiltersToZipCommand(testCase.includes, testCase.excludes) if got != testCase.out { t.Errorf("expected %q got %q", testCase.out, got) diff --git a/java/jarjar_test.go b/java/jarjar_test.go index 82bfa2b86..b68976155 100644 --- a/java/jarjar_test.go +++ b/java/jarjar_test.go @@ -22,7 +22,7 @@ import ( ) func AssertJarJarRename(t *testing.T, result *android.TestResult, libName, original, expectedRename string) { - module := result.ModuleForTests(libName, "android_common") + module := result.ModuleForTests(t, libName, "android_common") provider, found := android.OtherModuleProvider(result.OtherModuleProviderAdaptor(), module.Module(), JarJarProvider) android.AssertBoolEquals(t, fmt.Sprintf("found provider (%s)", libName), true, found) diff --git a/java/java.go b/java/java.go index ee112c1da..af2b86e2a 100644 --- a/java/java.go +++ b/java/java.go @@ -64,6 +64,7 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_api_library", ApiLibraryFactory) ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory) ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory) + ctx.RegisterModuleType("java_genrule_combiner", GenruleCombinerFactory) // This mutator registers dependencies on dex2oat for modules that should be // dexpreopted. This is done late when the final variants have been @@ -250,6 +251,37 @@ type ProguardSpecInfo struct { var ProguardSpecInfoProvider = blueprint.NewProvider[ProguardSpecInfo]() +type AndroidLibraryDependencyInfo struct { + ExportPackage android.Path + ResourcesNodeDepSet depset.DepSet[*resourcesNode] + RRODirsDepSet depset.DepSet[rroDir] + ManifestsDepSet depset.DepSet[android.Path] +} + +type UsesLibraryDependencyInfo struct { + DexJarBuildPath OptionalDexJarPath + DexJarInstallPath android.Path + ClassLoaderContexts dexpreopt.ClassLoaderContextMap +} + +type SdkLibraryComponentDependencyInfo struct { + // The name of the implementation library for the optional SDK library or nil, if there isn't one. + OptionalSdkLibraryImplementation *string +} + +type ProvidesUsesLibInfo struct { + ProvidesUsesLib *string +} + +type ModuleWithUsesLibraryInfo struct { + UsesLibrary *usesLibrary +} + +type ModuleWithSdkDepInfo struct { + SdkLinkType sdkLinkType + Stubs bool +} + // JavaInfo contains information about a java module for use by modules that depend on it. type JavaInfo struct { // HeaderJars is a list of jars that can be passed as the javac classpath in order to link @@ -328,10 +360,92 @@ type JavaInfo struct { AconfigIntermediateCacheOutputPaths android.Paths SdkVersion android.SdkSpec + + // output file of the module, which may be a classes jar or a dex jar + OutputFile android.Path + + ExtraOutputFiles android.Paths + + AndroidLibraryDependencyInfo *AndroidLibraryDependencyInfo + + UsesLibraryDependencyInfo *UsesLibraryDependencyInfo + + SdkLibraryComponentDependencyInfo *SdkLibraryComponentDependencyInfo + + ProvidesUsesLibInfo *ProvidesUsesLibInfo + + MissingOptionalUsesLibs []string + + ModuleWithSdkDepInfo *ModuleWithSdkDepInfo + + // output file containing classes.dex and resources + DexJarFile OptionalDexJarPath + + // installed file for binary dependency + InstallFile android.Path + + // The path to the dex jar that is in the boot class path. If this is unset then the associated + // module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional + // annotations for the <x> boot dex jar but which do not actually provide a boot dex jar + // themselves. + // + // This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on + // this file so using the encoded dex jar here would result in a cycle in the ninja rules. + BootDexJarPath OptionalDexJarPath + + // The compressed state of the dex file being encoded. This is used to ensure that the encoded + // dex file has the same state. + UncompressDexState *bool + + // True if the module containing this structure contributes to the hiddenapi information or has + // that information encoded within it. + Active bool + + BuiltInstalled string + + // ApexSystemServerDexpreoptInstalls stores the list of dexpreopt artifacts if this is a system server + // jar in an apex. + ApexSystemServerDexpreoptInstalls []DexpreopterInstall + + // ApexSystemServerDexJars stores the list of dex jars if this is a system server jar in an apex. + ApexSystemServerDexJars android.Paths + + // 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 + + // The path to the profile on host that dexpreopter generates. This is used as the input for + // dex2oat. + OutputProfilePathOnHost android.Path + + LogtagsSrcs android.Paths + + ProguardDictionary android.OptionalPath + + ProguardUsageZip android.OptionalPath + + LinterReports android.Paths + + // installed file for hostdex copy + HostdexInstallFile android.InstallPath + + // Additional srcJars tacked in by GeneratedJavaLibraryModule + GeneratedSrcjars []android.Path + + // True if profile-guided optimization is actually enabled. + ProfileGuided bool } var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]() +type JavaLibraryInfo struct{} + +var JavaLibraryInfoProvider = blueprint.NewProvider[JavaLibraryInfo]() + // SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to // the sysprop implementation library. type SyspropPublicStubInfo struct { @@ -482,7 +596,7 @@ var ( ) func IsLibDepTag(depTag blueprint.DependencyTag) bool { - return depTag == libTag || depTag == sdkLibTag + return depTag == libTag } func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool { @@ -593,11 +707,11 @@ type deps struct { transitiveStaticLibsResourceJars []depset.DepSet[android.Path] } -func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) { - for _, f := range dep.Srcs() { +func checkProducesJars(ctx android.ModuleContext, dep android.SourceFilesInfo, module android.ModuleProxy) { + for _, f := range dep.Srcs { if f.Ext() != ".jar" { ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency", - ctx.OtherModuleName(dep.(blueprint.Module))) + ctx.OtherModuleName(module)) } } } @@ -715,6 +829,8 @@ type Library struct { combinedExportedProguardFlagsFile android.Path InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths) + + apiXmlFile android.WritablePath } var _ android.ApexModule = (*Library)(nil) @@ -1002,7 +1118,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.disableDexpreopt() } } - j.compile(ctx, nil, nil, nil, nil) + javaInfo := j.compile(ctx, nil, nil, nil, nil) j.setInstallRules(ctx) @@ -1011,7 +1127,88 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { TopLevelTarget: j.sourceProperties.Top_level_test_target, }) + android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{}) + + if javaInfo != nil { + setExtraJavaInfo(ctx, j, javaInfo) + javaInfo.ExtraOutputFiles = j.extraOutputFiles + javaInfo.DexJarFile = j.dexJarFile + javaInfo.InstallFile = j.installFile + javaInfo.BootDexJarPath = j.bootDexJarPath + javaInfo.UncompressDexState = j.uncompressDexState + javaInfo.Active = j.active + javaInfo.ApexSystemServerDexpreoptInstalls = j.apexSystemServerDexpreoptInstalls + javaInfo.ApexSystemServerDexJars = j.apexSystemServerDexJars + javaInfo.BuiltInstalled = j.builtInstalled + javaInfo.ConfigPath = j.configPath + javaInfo.OutputProfilePathOnHost = j.outputProfilePathOnHost + javaInfo.LogtagsSrcs = j.logtagsSrcs + javaInfo.ProguardDictionary = j.proguardDictionary + javaInfo.ProguardUsageZip = j.proguardUsageZip + javaInfo.LinterReports = j.reports + javaInfo.HostdexInstallFile = j.hostdexInstallFile + javaInfo.GeneratedSrcjars = j.properties.Generated_srcjars + javaInfo.ProfileGuided = j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided + + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + } + setOutputFiles(ctx, j.Module) + + j.javaLibraryModuleInfoJSON(ctx) + + buildComplianceMetadata(ctx) + + j.createApiXmlFile(ctx) +} + +func (j *Library) javaLibraryModuleInfoJSON(ctx android.ModuleContext) *android.ModuleInfoJSON { + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"} + if j.implementationAndResourcesJar != nil { + moduleInfoJSON.ClassesJar = []string{j.implementationAndResourcesJar.String()} + } + moduleInfoJSON.SystemSharedLibs = []string{"none"} + + if j.hostDexNeeded() { + hostDexModuleInfoJSON := ctx.ExtraModuleInfoJSON() + hostDexModuleInfoJSON.SubName = "-hostdex" + hostDexModuleInfoJSON.Class = []string{"JAVA_LIBRARIES"} + if j.implementationAndResourcesJar != nil { + hostDexModuleInfoJSON.ClassesJar = []string{j.implementationAndResourcesJar.String()} + } + hostDexModuleInfoJSON.SystemSharedLibs = []string{"none"} + hostDexModuleInfoJSON.SupportedVariantsOverride = []string{"HOST"} + } + + if j.hideApexVariantFromMake { + moduleInfoJSON.Disabled = true + } + return moduleInfoJSON +} + +func buildComplianceMetadata(ctx android.ModuleContext) { + // Dump metadata that can not be done in android/compliance-metadata.go + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + builtFiles := ctx.GetOutputFiles().DefaultOutputFiles.Strings() + for _, paths := range ctx.GetOutputFiles().TaggedOutputFiles { + builtFiles = append(builtFiles, paths.Strings()...) + } + complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.BUILT_FILES, android.SortedUniqueStrings(builtFiles)) + + // Static deps + staticDepNames := make([]string, 0) + staticDepFiles := android.Paths{} + ctx.VisitDirectDepsWithTag(staticLibTag, func(module android.Module) { + if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { + staticDepNames = append(staticDepNames, module.Name()) + staticDepFiles = append(staticDepFiles, dep.ImplementationJars...) + staticDepFiles = append(staticDepFiles, dep.HeaderJars...) + staticDepFiles = append(staticDepFiles, dep.ResourceJars...) + } + }) + complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.SortedUniqueStrings(staticDepNames)) + complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.SortedUniqueStrings(staticDepFiles.Strings())) } func (j *Library) getJarInstallDir(ctx android.ModuleContext) android.InstallPath { @@ -1067,6 +1264,28 @@ func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { } } +var apiXMLGeneratingApiSurfaces = []android.SdkKind{ + android.SdkPublic, + android.SdkSystem, + android.SdkModule, + android.SdkSystemServer, + android.SdkTest, +} + +func (j *Library) createApiXmlFile(ctx android.ModuleContext) { + if kind, ok := android.JavaLibraryNameToSdkKind(ctx.ModuleName()); ok && android.InList(kind, apiXMLGeneratingApiSurfaces) { + scopePrefix := AllApiScopes.matchingScopeFromSdkKind(kind).apiFilePrefix + j.apiXmlFile = android.PathForModuleOut(ctx, fmt.Sprintf("%sapi.xml", scopePrefix)) + ctx.Build(pctx, android.BuildParams{ + Rule: generateApiXMLRule, + // LOCAL_SOONG_CLASSES_JAR + Input: j.implementationAndResourcesJar, + Output: j.apiXmlFile, + }) + ctx.DistForGoal("dist_files", j.apiXmlFile) + } +} + const ( aidlIncludeDir = "aidl" javaDir = "java" @@ -1570,6 +1789,11 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { MkInclude: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", MkAppClass: "JAVA_LIBRARIES", }) + + moduleInfoJSON := ctx.ModuleInfoJSON() + if proptools.Bool(j.testProperties.Test_options.Unit_test) { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests") + } } func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1604,17 +1828,17 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs) - ctx.VisitDirectDepsWithTag(dataNativeBinsTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(dataNativeBinsTag, func(dep android.ModuleProxy) { j.data = append(j.data, android.OutputFileForModule(ctx, dep, "")) }) - ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(dataDeviceBinsTag, func(dep android.ModuleProxy) { j.data = append(j.data, android.OutputFileForModule(ctx, dep, "")) }) var directImplementationDeps android.Paths var transitiveImplementationDeps []depset.DepSet[android.Path] - ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(jniLibTag, func(dep android.ModuleProxy) { sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider) if sharedLibInfo.SharedLibrary != nil { // Copy to an intermediate output directory to append "lib[64]" to the path, @@ -1647,10 +1871,74 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, }) j.Library.GenerateAndroidBuildActions(ctx) + + moduleInfoJSON := ctx.ModuleInfoJSON() + // LOCAL_MODULE_TAGS + moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests") + var allTestConfigs android.Paths + if j.testConfig != nil { + allTestConfigs = append(allTestConfigs, j.testConfig) + } + allTestConfigs = append(allTestConfigs, j.extraTestConfigs...) + if len(allTestConfigs) > 0 { + moduleInfoJSON.TestConfig = allTestConfigs.Strings() + } else { + optionalConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml") + if optionalConfig.Valid() { + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String()) + } + } + if len(j.testProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, j.testProperties.Test_suites...) + } else { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") + } + if _, ok := j.testConfig.(android.WritablePath); ok { + moduleInfoJSON.AutoTestConfig = []string{"true"} + } + if proptools.Bool(j.testProperties.Test_options.Unit_test) { + moduleInfoJSON.IsUnitTest = "true" + if ctx.Host() { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests") + } + } + moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, j.testProperties.Test_mainline_modules...) + + // Install test deps + if !ctx.Config().KatiEnabled() { + pathInTestCases := android.PathForModuleInstall(ctx, "testcases", ctx.ModuleName()) + if j.testConfig != nil { + ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".config", j.testConfig) + } + dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml") + if dynamicConfig.Valid() { + ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path()) + } + testDeps := append(j.data, j.extraTestConfigs...) + for _, data := range android.SortedUniquePaths(testDeps) { + dataPath := android.DataPath{SrcPath: data} + ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath}) + } + if j.outputFile != nil { + ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".jar", j.outputFile) + } + } } func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.Library.GenerateAndroidBuildActions(ctx) + + moduleInfoJSON := ctx.ModuleInfoJSON() + moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests") + if len(j.testHelperLibraryProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, j.testHelperLibraryProperties.Test_suites...) + } else { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") + } + optionalConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml") + if optionalConfig.Valid() { + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String()) + } } func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1740,7 +2028,7 @@ func TestFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) module.Module.sourceProperties.Top_level_test_target = true @@ -1757,7 +2045,7 @@ func TestHelperLibraryFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) InitJavaModule(module, android.HostAndDeviceSupported) @@ -1904,13 +2192,13 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Set the jniLibs of this binary. // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will // install these alongside the java binary. - ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) { + ctx.VisitDirectDepsProxyWithTag(jniInstallTag, func(jni android.ModuleProxy) { // Use the BaseModuleName of the dependency (without any prebuilt_ prefix) - bmn, _ := jni.(interface{ BaseModuleName() string }) - j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness()) + commonInfo, _ := android.OtherModuleProvider(ctx, jni, android.CommonModuleInfoKey) + j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, commonInfo.BaseModuleName+":"+commonInfo.Target.Arch.ArchType.Bitness()) }) // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead. - ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(android.RequiredDepTag, func(dep android.ModuleProxy) { if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo { ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name()) } @@ -2129,7 +2417,7 @@ func (al *ApiLibrary) StubsJar() android.Path { func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths, homeDir android.WritablePath, - classpath android.Paths, configFiles android.Paths) *android.RuleBuilderCommand { + classpath android.Paths, configFiles android.Paths, apiSurface *string) *android.RuleBuilderCommand { rule.Command().Text("rm -rf").Flag(homeDir.String()) rule.Command().Text("mkdir -p").Flag(homeDir.String()) @@ -2170,6 +2458,8 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, addMetalavaConfigFilesToCmd(cmd, configFiles) + addOptionalApiSurfaceToCmd(cmd, apiSurface) + if len(classpath) == 0 { // The main purpose of the `--api-class-resolution api` option is to force metalava to ignore // classes on the classpath when an API file contains missing classes. However, as this command @@ -2253,6 +2543,17 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { var scopeOrderMap = AllApiScopes.MapToIndex( func(s *apiScope) string { return s.name }) +// Add some extra entries into scopeOrderMap for some special api surface names needed by libcore, +// external/conscrypt and external/icu and java/core-libraries. +func init() { + count := len(scopeOrderMap) + scopeOrderMap["core"] = count + 1 + scopeOrderMap["core-platform"] = count + 2 + scopeOrderMap["intra-core"] = count + 3 + scopeOrderMap["core-platform-plus-public"] = count + 4 + scopeOrderMap["core-platform-legacy"] = count + 5 +} + func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo { for _, srcFileInfo := range srcFilesInfo { if srcFileInfo.ApiSurface == "" { @@ -2301,7 +2602,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { var bootclassPaths android.Paths var staticLibs android.Paths var systemModulesPaths android.Paths - ctx.VisitDirectDeps(func(dep android.Module) { + ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(dep) switch tag { case javaApiContributionTag: @@ -2330,8 +2631,8 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { systemModulesPaths = append(systemModulesPaths, sm.HeaderJars...) } case metalavaCurrentApiTimestampTag: - if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok { - al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp()) + if currentApiTimestampProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider); ok { + al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp) } case aconfigDeclarationTag: if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok { @@ -2363,7 +2664,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { combinedPaths := append(([]android.Path)(nil), systemModulesPaths...) combinedPaths = append(combinedPaths, classPaths...) combinedPaths = append(combinedPaths, bootclassPaths...) - cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles) + cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles, al.properties.Api_surface) al.stubsFlags(ctx, cmd, stubsDir) @@ -2427,7 +2728,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.Phony(ctx.ModuleName(), al.stubsJar) - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + javaInfo := &JavaInfo{ HeaderJars: android.PathsIfNonNil(al.stubsJar), LocalHeaderJars: android.PathsIfNonNil(al.stubsJar), TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, android.PathsIfNonNil(al.stubsJar), nil), @@ -2437,7 +2738,9 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { AidlIncludeDirs: android.Paths{}, StubsLinkType: Stubs, // No aconfig libraries on api libraries - }) + } + setExtraJavaInfo(ctx, al, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) } func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { @@ -2705,7 +3008,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { var staticJars android.Paths var staticResourceJars android.Paths var staticHeaderJars android.Paths - ctx.VisitDirectDeps(func(module android.Module) { + ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(module) if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { switch tag { @@ -2827,6 +3130,23 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { outputFile = combinedJar } + proguardFlags := android.PathForModuleOut(ctx, "proguard_flags") + TransformJarToR8Rules(ctx, proguardFlags, outputFile) + + transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx) + android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{ + ProguardFlagsFiles: depset.New[android.Path]( + depset.POSTORDER, + android.Paths{proguardFlags}, + transitiveProguardFlags, + ), + UnconditionallyExportedProguardFlags: depset.New[android.Path]( + depset.POSTORDER, + nil, + transitiveUnconditionalExportedFlags, + ), + }) + // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource. // Also strip the relative path from the header output file so that the reuseImplementationJarAsHeaderJar check // in a module that depends on this module considers them equal. @@ -2895,7 +3215,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } - android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ + javaInfo := &JavaInfo{ HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile), LocalHeaderJars: android.PathsIfNonNil(j.combinedHeaderFile), TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8, @@ -2909,10 +3229,14 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { AidlIncludeDirs: j.exportAidlIncludeDirs, StubsLinkType: j.stubsLinkType, // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts - }) + } + setExtraJavaInfo(ctx, j, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, "") ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, ".jar") + + buildComplianceMetadata(ctx) } func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) { @@ -2959,26 +3283,29 @@ func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { var _ android.ApexModule = (*Import)(nil) // Implements android.ApexModule -func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - return j.depIsInSameApex(ctx, dep) +func (m *Import) GetDepInSameApexChecker() android.DepInSameApexChecker { + return JavaImportDepInSameApexChecker{} +} + +type JavaImportDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m JavaImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + return depIsInSameApex(tag) } // Implements android.ApexModule -func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { +func (j *Import) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { sdkVersionSpec := j.SdkVersion(ctx) minSdkVersion := j.MinSdkVersion(ctx) - if !minSdkVersion.Specified() { - return fmt.Errorf("min_sdk_version is not specified") - } + // If the module is compiling against core (via sdk_version), skip comparison check. if sdkVersionSpec.Kind == android.SdkCore { - return nil + return android.MinApiLevel } - if minSdkVersion.GreaterThan(sdkVersion) { - return fmt.Errorf("newer SDK(%v)", minSdkVersion) - } - return nil + + return minSdkVersion } // requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or @@ -3020,7 +3347,7 @@ var _ android.IDECustomizedModuleName = (*Import)(nil) // Collect information for opening IDE project files in java/jdeps.go. func (j *Import) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { - dpInfo.Jars = append(dpInfo.Jars, j.combinedHeaderFile.String()) + dpInfo.Jars = append(dpInfo.Jars, j.combinedImplementationFile.String()) } func (j *Import) IDECustomizedModuleName() string { @@ -3194,10 +3521,8 @@ func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDex var _ android.ApexModule = (*DexImport)(nil) // Implements android.ApexModule -func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { - // we don't check prebuilt modules for sdk_version - return nil +func (m *DexImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } // dex_import imports a `.jar` file containing classes.dex files. @@ -3219,7 +3544,6 @@ func DexImportFactory() android.Module { type Defaults struct { android.ModuleBase android.DefaultsModuleBase - android.ApexModuleBase } // java_defaults provides a set of properties that can be inherited by other java or android modules. @@ -3283,6 +3607,8 @@ func DefaultsFactory() android.Module { &bootclasspathFragmentProperties{}, &SourceOnlyBootclasspathProperties{}, &ravenwoodTestProperties{}, + &AndroidAppImportProperties{}, + &UsesLibraryProperties{}, ) android.InitDefaultsModule(module) @@ -3320,11 +3646,11 @@ var String = proptools.String var inList = android.InList[string] // Add class loader context (CLC) of a given dependency to the current CLC. -func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, +func addCLCFromDep(ctx android.ModuleContext, depModule android.ModuleProxy, clcMap dexpreopt.ClassLoaderContextMap) { - dep, ok := depModule.(UsesLibraryDependency) - if !ok { + dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider) + if !ok || dep.UsesLibraryDependencyInfo == nil { return } @@ -3334,14 +3660,14 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, if lib, ok := android.OtherModuleProvider(ctx, depModule, SdkLibraryInfoProvider); ok && lib.SharedLibrary { // A shared SDK library. This should be added as a top-level CLC element. sdkLib = &depName - } else if lib, ok := depModule.(SdkLibraryComponentDependency); ok && lib.OptionalSdkLibraryImplementation() != nil { - if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation())+".impl" { - sdkLib = lib.OptionalSdkLibraryImplementation() + } else if lib := dep.SdkLibraryComponentDependencyInfo; lib != nil && lib.OptionalSdkLibraryImplementation != nil { + if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation)+".impl" { + sdkLib = lib.OptionalSdkLibraryImplementation } - } else if ulib, ok := depModule.(ProvidesUsesLib); ok { + } else if ulib := dep.ProvidesUsesLibInfo; ulib != nil { // A non-SDK library disguised as an SDK library by the means of `provides_uses_lib` // property. This should be handled in the same way as a shared SDK library. - sdkLib = ulib.ProvidesUsesLib() + sdkLib = ulib.ProvidesUsesLib } depTag := ctx.OtherModuleDependencyTag(depModule) @@ -3373,21 +3699,22 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, } } clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional, - dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts()) + dep.UsesLibraryDependencyInfo.DexJarBuildPath.PathOrNil(), + dep.UsesLibraryDependencyInfo.DexJarInstallPath, dep.UsesLibraryDependencyInfo.ClassLoaderContexts) } else { - clcMap.AddContextMap(dep.ClassLoaderContexts(), depName) + clcMap.AddContextMap(dep.UsesLibraryDependencyInfo.ClassLoaderContexts, depName) } } -func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module, +func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.ModuleProxy, usesLibrary *usesLibrary) { - dep, ok := depModule.(ModuleWithUsesLibrary) + dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider) if !ok { return } - for _, lib := range dep.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs { + for _, lib := range dep.MissingOptionalUsesLibs { if !android.InList(lib, usesLibrary.usesLibraryProperties.Missing_optional_uses_libs) { usesLibrary.usesLibraryProperties.Missing_optional_uses_libs = append(usesLibrary.usesLibraryProperties.Missing_optional_uses_libs, lib) @@ -3443,3 +3770,46 @@ func (j *JavaApiContributionImport) CreatedByJavaSdkLibraryName() *string { func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { ap.JavaApiContribution.GenerateAndroidBuildActions(ctx) } + +func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo *JavaInfo) { + if alDep, ok := module.(AndroidLibraryDependency); ok { + javaInfo.AndroidLibraryDependencyInfo = &AndroidLibraryDependencyInfo{ + ExportPackage: alDep.ExportPackage(), + ResourcesNodeDepSet: alDep.ResourcesNodeDepSet(), + RRODirsDepSet: alDep.RRODirsDepSet(), + ManifestsDepSet: alDep.ManifestsDepSet(), + } + } + + if ulDep, ok := module.(UsesLibraryDependency); ok { + javaInfo.UsesLibraryDependencyInfo = &UsesLibraryDependencyInfo{ + DexJarBuildPath: ulDep.DexJarBuildPath(ctx), + DexJarInstallPath: ulDep.DexJarInstallPath(), + ClassLoaderContexts: ulDep.ClassLoaderContexts(), + } + } + + if slcDep, ok := module.(SdkLibraryComponentDependency); ok { + javaInfo.SdkLibraryComponentDependencyInfo = &SdkLibraryComponentDependencyInfo{ + OptionalSdkLibraryImplementation: slcDep.OptionalSdkLibraryImplementation(), + } + } + + if pul, ok := module.(ProvidesUsesLib); ok { + javaInfo.ProvidesUsesLibInfo = &ProvidesUsesLibInfo{ + ProvidesUsesLib: pul.ProvidesUsesLib(), + } + } + + if mwul, ok := module.(ModuleWithUsesLibrary); ok { + javaInfo.MissingOptionalUsesLibs = mwul.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs + } + + if mwsd, ok := module.(moduleWithSdkDep); ok { + linkType, stubs := mwsd.getSdkLinkType(ctx, ctx.ModuleName()) + javaInfo.ModuleWithSdkDepInfo = &ModuleWithSdkDepInfo{ + SdkLinkType: linkType, + Stubs: stubs, + } + } +} diff --git a/java/java_test.go b/java/java_test.go index d415679bd..f097762eb 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -117,6 +117,7 @@ func defaultModuleToPath(name string) string { // Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by // running it in a fixture that requires all source files to exist. func TestPrepareForTestWithJavaDefaultModules(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.PrepareForTestDisallowNonExistentPaths, @@ -124,6 +125,7 @@ func TestPrepareForTestWithJavaDefaultModules(t *testing.T) { } func TestJavaLinkType(t *testing.T) { + t.Parallel() testJava(t, ` java_library { name: "foo", @@ -212,6 +214,7 @@ func TestJavaLinkType(t *testing.T) { } func TestSimple(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -341,11 +344,12 @@ func TestSimple(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, tt.preparer, ).RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") fooJavac := foo.Rule("javac") android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs) @@ -360,7 +364,7 @@ func TestSimple(t *testing.T) { fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar") android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs) - bar := result.ModuleForTests("bar", "android_common") + bar := result.ModuleForTests(t, "bar", "android_common") barJavac := bar.Rule("javac") android.AssertPathsRelativeToTopEquals(t, "bar javac inputs", tt.barJavacInputs, barJavac.Inputs) @@ -378,6 +382,7 @@ func TestSimple(t *testing.T) { } func TestExportedPlugins(t *testing.T) { + t.Parallel() type Result struct { library string processors string @@ -456,6 +461,7 @@ func TestExportedPlugins(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_plugin { name: "plugin", @@ -469,11 +475,11 @@ func TestExportedPlugins(t *testing.T) { `+test.extra) for _, want := range test.results { - javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac") + javac := ctx.ModuleForTests(t, want.library, "android_common").Rule("javac") if javac.Args["processor"] != want.processors { t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"]) } - turbine := ctx.ModuleForTests(want.library, "android_common").MaybeRule("turbine") + turbine := ctx.ModuleForTests(t, want.library, "android_common").MaybeRule("turbine") disableTurbine := turbine.BuildParams.Rule == nil if disableTurbine != want.disableTurbine { t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine) @@ -484,6 +490,7 @@ func TestExportedPlugins(t *testing.T) { } func TestSdkVersionByPartition(t *testing.T) { + t.Parallel() testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` java_library { name: "foo", @@ -525,6 +532,7 @@ func TestSdkVersionByPartition(t *testing.T) { } func TestArchSpecific(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -537,13 +545,14 @@ func TestArchSpecific(t *testing.T) { } `) - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" { t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs) } } func TestBinary(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library_host { name: "foo", @@ -567,11 +576,11 @@ func TestBinary(t *testing.T) { buildOS := ctx.Config().BuildOS.String() - bar := ctx.ModuleForTests("bar", buildOS+"_common") + bar := ctx.ModuleForTests(t, "bar", buildOS+"_common") barJar := bar.Output("bar.jar").Output.String() barWrapperDeps := bar.Output("bar").Implicits.Strings() - libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared") + libjni := ctx.ModuleForTests(t, "libjni", buildOS+"_x86_64_shared") libjniSO := libjni.Rule("Cp").Output.String() // Test that the install binary wrapper depends on the installed jar file @@ -586,6 +595,7 @@ func TestBinary(t *testing.T) { } func TestTest(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_test_host { name: "foo", @@ -603,7 +613,7 @@ func TestTest(t *testing.T) { buildOS := ctx.Config().BuildOS.String() - foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) + foo := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost) expected := "lib64/libjni.so" if runtime.GOOS == "darwin" { @@ -618,6 +628,7 @@ func TestTest(t *testing.T) { } func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { + t.Parallel() bp := ` java_library { name: "target_library", @@ -638,7 +649,7 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { ).RunTestWithBp(t, bp) // first, check that the -g flag is added to target modules - targetLibrary := result.ModuleForTests("target_library", "android_common") + targetLibrary := result.ModuleForTests(t, "target_library", "android_common") targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"] if !strings.Contains(targetJavaFlags, "-g:source,lines") { t.Errorf("target library javac flags %v should contain "+ @@ -647,7 +658,7 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { // check that -g is not overridden for host modules buildOS := result.Config.BuildOS.String() - hostBinary := result.ModuleForTests("host_binary", buildOS+"_common") + hostBinary := result.ModuleForTests(t, "host_binary", buildOS+"_common") hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"] if strings.Contains(hostJavaFlags, "-g:source,lines") { t.Errorf("java_binary_host javac flags %v should not have "+ @@ -665,6 +676,7 @@ func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil) func TestPrebuilts(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -710,14 +722,14 @@ func TestPrebuilts(t *testing.T) { } `) - fooModule := ctx.ModuleForTests("foo", "android_common") + fooModule := ctx.ModuleForTests(t, "foo", "android_common") javac := fooModule.Rule("javac") - combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") - barModule := ctx.ModuleForTests("bar", "android_common") + combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac") + barModule := ctx.ModuleForTests(t, "bar", "android_common") barJar := barModule.Output("combined/bar.jar").Output - bazModule := ctx.ModuleForTests("baz", "android_common") + bazModule := ctx.ModuleForTests(t, "baz", "android_common") bazJar := bazModule.Output("combined/baz.jar").Output - sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common"). + sdklibStubsJar := ctx.ModuleForTests(t, "sdklib.stubs", "android_common"). Output("combined/sdklib.stubs.jar").Output fooLibrary := fooModule.Module().(*Library) @@ -750,7 +762,7 @@ func TestPrebuilts(t *testing.T) { expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar" android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar) - ctx.ModuleForTests("qux", "android_common").Rule("Cp") + ctx.ModuleForTests(t, "qux", "android_common").Rule("Cp") entries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0] android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0]) @@ -765,6 +777,7 @@ func assertDeepEquals(t *testing.T, message string, expected interface{}, actual } func TestPrebuiltStubsSources(t *testing.T) { + t.Parallel() test := func(t *testing.T, sourcesPath string, expectedInputs []string) { ctx, _ := testJavaWithFS(t, fmt.Sprintf(` prebuilt_stubs_sources { @@ -775,17 +788,19 @@ prebuilt_stubs_sources { "stubs/sources/pkg/B.java": nil, }) - zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src") + zipSrc := ctx.ModuleForTests(t, "stubs-source", "android_common").Rule("zip_src") if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) { t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual) } } t.Run("empty/missing directory", func(t *testing.T) { + t.Parallel() test(t, "empty-directory", nil) }) t.Run("non-empty set of sources", func(t *testing.T) { + t.Parallel() test(t, "stubs/sources", []string{ "stubs/sources/pkg/A.java", "stubs/sources/pkg/B.java", @@ -794,6 +809,7 @@ prebuilt_stubs_sources { } func TestDefaults(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_defaults { name: "defaults", @@ -835,8 +851,8 @@ func TestDefaults(t *testing.T) { } `) - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") - combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") + combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac") if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" { t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs) @@ -847,28 +863,29 @@ func TestDefaults(t *testing.T) { t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine) } - baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String() + baz := ctx.ModuleForTests(t, "baz", "android_common").Rule("javac").Output.String() if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz { t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz) } - atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8") + atestOptimize := ctx.ModuleForTests(t, "atestOptimize", "android_common").MaybeRule("r8") if atestOptimize.Output == nil { t.Errorf("atestOptimize should optimize APK") } - atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8") + atestNoOptimize := ctx.ModuleForTests(t, "atestNoOptimize", "android_common").MaybeRule("d8") if atestNoOptimize.Output == nil { t.Errorf("atestNoOptimize should not optimize APK") } - atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("d8") + atestDefault := ctx.ModuleForTests(t, "atestDefault", "android_common").MaybeRule("d8") if atestDefault.Output == nil { t.Errorf("atestDefault should not optimize APK") } } func TestResources(t *testing.T) { + t.Parallel() var table = []struct { name string prop string @@ -940,6 +957,7 @@ func TestResources(t *testing.T) { for _, test := range table { t.Run(test.name, func(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -958,8 +976,8 @@ func TestResources(t *testing.T) { }, ) - foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") - fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar") + foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar") + fooRes := ctx.ModuleForTests(t, "foo", "android_common").Output("res/foo.jar") if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { t.Errorf("foo combined jars %v does not contain %q", @@ -975,6 +993,7 @@ func TestResources(t *testing.T) { } func TestIncludeSrcs(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -1003,8 +1022,8 @@ func TestIncludeSrcs(t *testing.T) { }) // Test a library with include_srcs: true - foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar") - fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar") + foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar") + fooSrcJar := ctx.ModuleForTests(t, "foo", "android_common").Output("foo.srcjar") if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) { t.Errorf("foo combined jars %v does not contain %q", w, g) @@ -1015,10 +1034,10 @@ func TestIncludeSrcs(t *testing.T) { } // Test a library with include_srcs: true and resources - bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar") - barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar") - barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar") - barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar") + bar := ctx.ModuleForTests(t, "bar", "android_common").Output("withres/bar.jar") + barResCombined := ctx.ModuleForTests(t, "bar", "android_common").Output("res-combined/bar.jar") + barRes := ctx.ModuleForTests(t, "bar", "android_common").Output("res/bar.jar") + barSrcJar := ctx.ModuleForTests(t, "bar", "android_common").Output("bar.srcjar") if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) { t.Errorf("bar combined resource jars %v does not contain %q", w, g) @@ -1042,6 +1061,7 @@ func TestIncludeSrcs(t *testing.T) { } func TestGeneratedSources(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -1062,8 +1082,8 @@ func TestGeneratedSources(t *testing.T) { "b.java": nil, }) - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") - genrule := ctx.ModuleForTests("gen", "").Rule("generator") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") + genrule := ctx.ModuleForTests(t, "gen", "").Rule("generator") if filepath.Base(genrule.Output.String()) != "gen.java" { t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String()) @@ -1078,6 +1098,7 @@ func TestGeneratedSources(t *testing.T) { } func TestTurbine(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})). RunTestWithBp(t, ` @@ -1102,11 +1123,11 @@ func TestTurbine(t *testing.T) { } `) - fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine") - barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine") - barJavac := result.ModuleForTests("bar", "android_common").Rule("javac") - barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine") - bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac") + fooTurbine := result.ModuleForTests(t, "foo", "android_common").Rule("turbine") + barTurbine := result.ModuleForTests(t, "bar", "android_common").Rule("turbine") + barJavac := result.ModuleForTests(t, "bar", "android_common").Rule("javac") + barTurbineCombined := result.ModuleForTests(t, "bar", "android_common").Description("for turbine") + bazJavac := result.ModuleForTests(t, "baz", "android_common").Rule("javac") android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs) @@ -1119,6 +1140,7 @@ func TestTurbine(t *testing.T) { } func TestSharding(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "bar", @@ -1129,7 +1151,7 @@ func TestSharding(t *testing.T) { barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar") for i := 0; i < 3; i++ { - barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)) + barJavac := ctx.ModuleForTests(t, "bar", "android_common").Description("javac" + strconv.Itoa(i)) if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") { t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar) } @@ -1137,6 +1159,7 @@ func TestSharding(t *testing.T) { } func TestExcludeFileGroupInSrcs(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1155,7 +1178,7 @@ func TestExcludeFileGroupInSrcs(t *testing.T) { } `) - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" { t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs) @@ -1163,6 +1186,7 @@ func TestExcludeFileGroupInSrcs(t *testing.T) { } func TestJavaLibraryOutputFiles(t *testing.T) { + t.Parallel() testJavaWithFS(t, "", map[string][]byte{ "libcore/Android.bp": []byte(` java_library { @@ -1180,6 +1204,7 @@ func TestJavaLibraryOutputFiles(t *testing.T) { } func TestJavaImportOutputFiles(t *testing.T) { + t.Parallel() testJavaWithFS(t, "", map[string][]byte{ "libcore/Android.bp": []byte(` java_import { @@ -1196,6 +1221,7 @@ func TestJavaImportOutputFiles(t *testing.T) { } func TestJavaImport(t *testing.T) { + t.Parallel() bp := ` java_library { name: "source_library", @@ -1223,7 +1249,7 @@ func TestJavaImport(t *testing.T) { PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, bp) - source := ctx.ModuleForTests("source_library", "android_common") + source := ctx.ModuleForTests(t, "source_library", "android_common") sourceJar := source.Output("javac/source_library.jar") sourceHeaderJar := source.Output("turbine-combined/source_library.jar") sourceJavaInfo, _ := android.OtherModuleProvider(ctx, source.Module(), JavaInfoProvider) @@ -1234,7 +1260,7 @@ func TestJavaImport(t *testing.T) { android.AssertPathsRelativeToTopEquals(t, "source library header jar", []string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars) - importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common") + importWithNoDeps := ctx.ModuleForTests(t, "import_with_no_deps", "android_common") importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar") importWithNoDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider) @@ -1246,7 +1272,7 @@ func TestJavaImport(t *testing.T) { android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs", []string{"no_deps.jar"}, importWithNoDepsJar.Inputs) - importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common") + importWithSourceDeps := ctx.ModuleForTests(t, "import_with_source_deps", "android_common") importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar") importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar") importWithSourceDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider) @@ -1261,7 +1287,7 @@ func TestJavaImport(t *testing.T) { android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs", []string{"source_deps.jar", sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs) - importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common") + importWithImportDeps := ctx.ModuleForTests(t, "import_with_import_deps", "android_common") importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar") importWithImportDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider) @@ -1323,6 +1349,7 @@ func (ctx *mockContext) PropertyErrorf(property, format string, args ...interfac } func TestCompilerFlags(t *testing.T) { + t.Parallel() for _, testCase := range compilerFlagsTestCases { ctx := &mockContext{result: true} CheckKotlincFlags(ctx, []string{testCase.in}) @@ -1337,7 +1364,7 @@ func TestCompilerFlags(t *testing.T) { // TODO(jungjw): Consider making this more robust by ignoring path order. func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) { - variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop() + variables := ctx.ModuleForTests(t, moduleName, "android_common").VariablesForTestsRelativeToTop() flags := strings.Split(variables["javacFlags"], " ") got := "" for _, flag := range flags { @@ -1353,7 +1380,9 @@ func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName str } func TestPatchModule(t *testing.T) { + t.Parallel() t.Run("Java language level 8", func(t *testing.T) { + t.Parallel() // Test with legacy javac -source 1.8 -target 1.8 bp := ` java_library { @@ -1386,6 +1415,7 @@ func TestPatchModule(t *testing.T) { }) t.Run("Java language level 9", func(t *testing.T) { + t.Parallel() // Test with default javac -source 9 -target 9 bp := ` java_library { @@ -1426,6 +1456,7 @@ func TestPatchModule(t *testing.T) { } func TestJavaLibraryWithSystemModules(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "lib-with-source-system-modules", @@ -1474,7 +1505,7 @@ func TestJavaLibraryWithSystemModules(t *testing.T) { } func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) { - javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac") + javacRule := ctx.ModuleForTests(t, moduleName, "android_common").Rule("javac") bootClasspath := javacRule.Args["bootClasspath"] if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) { t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath) @@ -1482,6 +1513,7 @@ func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestCon } func TestAidlExportIncludeDirsFromImports(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1498,7 +1530,7 @@ func TestAidlExportIncludeDirsFromImports(t *testing.T) { } `) - aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command expectedAidlFlag := "-Iaidl/bar" if !strings.Contains(aidlCommand, expectedAidlFlag) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) @@ -1506,6 +1538,7 @@ func TestAidlExportIncludeDirsFromImports(t *testing.T) { } func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1514,7 +1547,7 @@ func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) { } `) - aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command expectedAidlFlag := "-Werror" if !strings.Contains(aidlCommand, expectedAidlFlag) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) @@ -1522,6 +1555,7 @@ func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) { } func TestAidlFlagsWithMinSdkVersion(t *testing.T) { + t.Parallel() fixture := android.GroupFixturePreparers( prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})) @@ -1535,6 +1569,7 @@ func TestAidlFlagsWithMinSdkVersion(t *testing.T) { {"system_current", `sdk_version: "system_current"`, "current"}, } { t.Run(tc.name, func(t *testing.T) { + t.Parallel() ctx := fixture.RunTestWithBp(t, ` java_library { name: "foo", @@ -1542,7 +1577,7 @@ func TestAidlFlagsWithMinSdkVersion(t *testing.T) { `+tc.sdkVersion+` } `) - aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command expectedAidlFlag := "--min_sdk_version=" + tc.expected if !strings.Contains(aidlCommand, expectedAidlFlag) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) @@ -1552,6 +1587,7 @@ func TestAidlFlagsWithMinSdkVersion(t *testing.T) { } func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) { + t.Parallel() bpTemplate := ` droidstubs { name: "foo-stubs", @@ -1578,13 +1614,14 @@ func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) { } for _, tc := range testCases { ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp)) - aidlCmd := ctx.ModuleForTests("foo-stubs", "android_common").Rule("aidl").RuleParams.Command + aidlCmd := ctx.ModuleForTests(t, "foo-stubs", "android_common").Rule("aidl").RuleParams.Command expected := "--min_sdk_version=" + tc.minSdkVersionExpected android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected) } } func TestAidlEnforcePermissions(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1593,7 +1630,7 @@ func TestAidlEnforcePermissions(t *testing.T) { } `) - aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command expectedAidlFlag := "-Wmissing-permission-annotation -Werror" if !strings.Contains(aidlCommand, expectedAidlFlag) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) @@ -1601,6 +1638,7 @@ func TestAidlEnforcePermissions(t *testing.T) { } func TestAidlEnforcePermissionsException(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1609,7 +1647,7 @@ func TestAidlEnforcePermissionsException(t *testing.T) { } `) - aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command + aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl" if !strings.Contains(aidlCommand, expectedAidlFlag) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) @@ -1621,6 +1659,7 @@ func TestAidlEnforcePermissionsException(t *testing.T) { } func TestDataNativeBinaries(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( prepareForJavaTest, android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, ` @@ -1638,7 +1677,7 @@ func TestDataNativeBinaries(t *testing.T) { buildOS := ctx.Config().BuildOS.String() - test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) + test := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost) entries := android.AndroidMkEntriesForTest(t, ctx, test)[0] expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"} actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] @@ -1646,6 +1685,7 @@ func TestDataNativeBinaries(t *testing.T) { } func TestDefaultInstallable(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_test_host { name: "foo" @@ -1653,12 +1693,13 @@ func TestDefaultInstallable(t *testing.T) { `) buildOS := ctx.Config().BuildOS.String() - module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) + module := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost) assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true), module.properties.Installable) } func TestErrorproneEnabled(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -1669,7 +1710,7 @@ func TestErrorproneEnabled(t *testing.T) { } `) - javac := ctx.ModuleForTests("foo", "android_common").Description("javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac") // Test that the errorprone plugins are passed to javac expectedSubstring := "-Xplugin:ErrorProne" @@ -1680,13 +1721,14 @@ func TestErrorproneEnabled(t *testing.T) { // Modules with errorprone { enabled: true } will include errorprone checks // in the main javac build rule. Only when RUN_ERROR_PRONE is true will // the explicit errorprone build rule be created. - errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone") + errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone") if errorprone.RuleParams.Description != "" { t.Errorf("expected errorprone build rule to not exist, but it did") } } func TestErrorproneDisabled(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -1703,7 +1745,7 @@ func TestErrorproneDisabled(t *testing.T) { }), ).RunTestWithBp(t, bp) - javac := ctx.ModuleForTests("foo", "android_common").Description("javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac") // Test that the errorprone plugins are not passed to javac, like they would // be if enabled was true. @@ -1714,13 +1756,14 @@ func TestErrorproneDisabled(t *testing.T) { // Check that no errorprone build rule is created, like there would be // if enabled was unset and RUN_ERROR_PRONE was true. - errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone") + errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone") if errorprone.RuleParams.Description != "" { t.Errorf("expected errorprone build rule to not exist, but it did") } } func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -1734,8 +1777,8 @@ func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) { }), ).RunTestWithBp(t, bp) - javac := ctx.ModuleForTests("foo", "android_common").Description("javac") - errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone") + javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac") + errorprone := ctx.ModuleForTests(t, "foo", "android_common").Description("errorprone") // Check that the errorprone plugins are not passed to javac, because they // will instead be passed to the separate errorprone compilation @@ -1751,6 +1794,7 @@ func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) { } func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { + t.Parallel() testCases := []struct { dataDeviceBinType string depCompileMultilib string @@ -1887,6 +1931,7 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib) t.Run(testName, func(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava). ExtendWithErrorHandler(errorHandler). RunTestWithBp(t, bp) @@ -1895,7 +1940,7 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { } buildOS := ctx.Config.BuildOS.String() - fooVariant := ctx.ModuleForTests("foo", buildOS+"_common") + fooVariant := ctx.ModuleForTests(t, "foo", buildOS+"_common") fooMod := fooVariant.Module().(*TestHost) entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0] @@ -1907,7 +1952,7 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { expectedData := []string{} for _, variant := range tc.variants { - barVariant := ctx.ModuleForTests("bar", variant) + barVariant := ctx.ModuleForTests(t, "bar", variant) relocated := barVariant.Output("bar") expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant) android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input) @@ -1916,12 +1961,13 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) { } actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] - android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData) + android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, android.SortedUniqueStrings(expectedData), android.SortedUniqueStrings(actualData)) }) } } func TestDeviceBinaryWrapperGeneration(t *testing.T) { + t.Parallel() // Scenario 1: java_binary has main_class property in its bp ctx, _ := testJava(t, ` java_binary { @@ -1930,7 +1976,7 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) { main_class: "foo.bar.jb", } `) - wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_common").AllOutputs()) + wrapperPath := fmt.Sprint(ctx.ModuleForTests(t, "foo", "android_common").AllOutputs()) if !strings.Contains(wrapperPath, "foo.sh") { t.Errorf("wrapper file foo.sh is not generated") } @@ -1945,6 +1991,7 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) { } func TestJavaApiContributionEmptyApiFile(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, android.FixtureMergeEnv( @@ -1968,6 +2015,7 @@ func TestJavaApiContributionEmptyApiFile(t *testing.T) { } func TestJavaApiLibraryAndProviderLink(t *testing.T) { + t.Parallel() provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2024,7 +2072,7 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, c.moduleName, "android_common") manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) manifestCommand := sboxProto.Commands[0].GetCommand() @@ -2034,6 +2082,7 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { } func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { + t.Parallel() provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2132,7 +2181,7 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, c.moduleName, "android_common") manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) manifestCommand := sboxProto.Commands[0].GetCommand() @@ -2142,6 +2191,7 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { } func TestJavaApiLibraryJarGeneration(t *testing.T) { + t.Parallel() provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2199,7 +2249,7 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, 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) @@ -2208,6 +2258,7 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { } func TestJavaApiLibraryLibsLink(t *testing.T) { + t.Parallel() provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2284,7 +2335,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, c.moduleName, "android_common") javacRules := m.Rule("javac") classPathArgs := javacRules.Args["classpath"] for _, jarName := range c.classPathJarNames { @@ -2296,6 +2347,7 @@ func TestJavaApiLibraryLibsLink(t *testing.T) { } func TestJavaApiLibraryStaticLibsLink(t *testing.T) { + t.Parallel() provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2372,7 +2424,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { }, } for _, c := range testcases { - m := ctx.ModuleForTests(c.moduleName, "android_common") + m := ctx.ModuleForTests(t, c.moduleName, "android_common") mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command for _, jarName := range c.staticLibJarNames { if !strings.Contains(mergeZipsCommand, jarName) { @@ -2383,6 +2435,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { } func TestTransitiveSrcFiles(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "a", @@ -2399,13 +2452,14 @@ func TestTransitiveSrcFiles(t *testing.T) { static_libs: ["b"], } `) - c := ctx.ModuleForTests("c", "android_common").Module() + c := ctx.ModuleForTests(t, "c", "android_common").Module() javaInfo, _ := android.OtherModuleProvider(ctx, c, JavaInfoProvider) transitiveSrcFiles := android.Paths(javaInfo.TransitiveSrcFiles.ToList()) android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings()) } func TestTradefedOptions(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` java_test_host { name: "foo", @@ -2421,7 +2475,7 @@ java_test_host { `) buildOS := result.Config.BuildOS.String() - args := result.ModuleForTests("foo", buildOS+"_common"). + args := result.ModuleForTests(t, "foo", buildOS+"_common"). Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />") if args["extraConfigs"] != expected { @@ -2430,6 +2484,7 @@ java_test_host { } func TestTestRunnerOptions(t *testing.T) { + t.Parallel() result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` java_test_host { name: "foo", @@ -2445,7 +2500,7 @@ java_test_host { `) buildOS := result.Config.BuildOS.String() - args := result.ModuleForTests("foo", buildOS+"_common"). + args := result.ModuleForTests(t, "foo", buildOS+"_common"). Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n ") if args["extraTestRunnerConfigs"] != expected { @@ -2454,6 +2509,7 @@ java_test_host { } func TestJavaLibraryWithResourcesStem(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -2465,7 +2521,7 @@ func TestJavaLibraryWithResourcesStem(t *testing.T) { "test-jar/test/resource.txt": nil, }) - m := ctx.ModuleForTests("foo", "android_common") + m := ctx.ModuleForTests(t, "foo", "android_common") outputs := fmt.Sprint(m.AllOutputs()) if !strings.Contains(outputs, "test.jar") { t.Errorf("Module output does not contain expected jar %s", "test.jar") @@ -2473,6 +2529,7 @@ func TestJavaLibraryWithResourcesStem(t *testing.T) { } func TestHeadersOnly(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -2481,16 +2538,17 @@ func TestHeadersOnly(t *testing.T) { } `) - turbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine") + turbine := ctx.ModuleForTests(t, "foo", "android_common").Rule("turbine") if len(turbine.Inputs) != 1 || turbine.Inputs[0].String() != "a.java" { t.Errorf(`foo inputs %v != ["a.java"]`, turbine.Inputs) } - javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac") + javac := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("javac") android.AssertDeepEquals(t, "javac rule", nil, javac.Rule) } func TestJavaApiContributionImport(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( prepareForJavaTest, android.FixtureMergeEnv( @@ -2510,7 +2568,7 @@ func TestJavaApiContributionImport(t *testing.T) { api_surface: "public", } `) - m := ctx.ModuleForTests("foo", "android_common") + m := ctx.ModuleForTests(t, "foo", "android_common") manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest) manifestCommand := sboxProto.Commands[0].GetCommand() @@ -2519,6 +2577,7 @@ func TestJavaApiContributionImport(t *testing.T) { } func TestJavaApiLibraryApiFilesSorting(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_api_library { name: "foo", @@ -2532,7 +2591,7 @@ func TestJavaApiLibraryApiFilesSorting(t *testing.T) { stubs_type: "everything", } `) - m := ctx.ModuleForTests("foo", "android_common") + m := ctx.ModuleForTests(t, "foo", "android_common") manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest) manifestCommand := sboxProto.Commands[0].GetCommand() @@ -2547,6 +2606,7 @@ func TestJavaApiLibraryApiFilesSorting(t *testing.T) { } func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -2576,6 +2636,7 @@ func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { } func TestApiLibraryDroidstubsDependency(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -2605,9 +2666,9 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) { `) currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp" - foo := result.ModuleForTests("foo", "android_common").Module().(*ApiLibrary) + foo := result.ModuleForTests(t, "foo", "android_common").Module().(*ApiLibrary) fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ") - bar := result.ModuleForTests("bar", "android_common").Module().(*ApiLibrary) + bar := result.ModuleForTests(t, "bar", "android_common").Module().(*ApiLibrary) barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ") android.AssertStringDoesContain(t, "Module expected to have validation", @@ -2622,6 +2683,7 @@ func TestApiLibraryDroidstubsDependency(t *testing.T) { } func TestDisableFromTextStubForCoverageBuild(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -2651,6 +2713,7 @@ func TestDisableFromTextStubForCoverageBuild(t *testing.T) { } func TestMultiplePrebuilts(t *testing.T) { + t.Parallel() bp := ` // an rdep java_library { @@ -2733,8 +2796,8 @@ func TestMultiplePrebuilts(t *testing.T) { ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName)) // check that rdep gets the correct variation of dep - foo := ctx.ModuleForTests("foo", "android_common") - expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") + expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_common") android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module())) // check that output file of dep is always bar.jar @@ -2749,6 +2812,7 @@ func TestMultiplePrebuilts(t *testing.T) { } func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) { + t.Parallel() bp := ` // multiple variations of platform_compat_config // source @@ -2802,13 +2866,14 @@ func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) { android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"), ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName)) - mergedGlobalConfig := ctx.SingletonForTests("platform_compat_config_singleton").Output("compat_config/merged_compat_config.xml") + mergedGlobalConfig := ctx.SingletonForTests(t, "platform_compat_config_singleton").Output("compat_config/merged_compat_config.xml") android.AssertIntEquals(t, "The merged compat config file should only have a single dependency", 1, len(mergedGlobalConfig.Implicits)) android.AssertStringEquals(t, "The merged compat config file is missing the appropriate platform compat config", mergedGlobalConfig.Implicits[0].String(), tc.expectedPlatformCompatConfigXml) } } func TestApiLibraryAconfigDeclarations(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -2850,7 +2915,7 @@ func TestApiLibraryAconfigDeclarations(t *testing.T) { android.AssertBoolEquals(t, "foo expected to depend on bar", CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true) - m := result.ModuleForTests("foo", "android_common") + m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") @@ -2919,6 +2984,7 @@ func TestTestOnly(t *testing.T) { // Don't allow setting test-only on things that are always tests or never tests. func TestInvalidTestOnlyTargets(t *testing.T) { + t.Parallel() testCases := []string{ ` java_test { name: "java-test", test_only: true, srcs: ["foo.java"], } `, ` java_test_host { name: "java-test-host", test_only: true, srcs: ["foo.java"], } `, @@ -2954,6 +3020,7 @@ func expectOneError(expected string, msg string) android.FixtureErrorHandler { } func TestJavaLibHostWithStem(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library_host { name: "foo", @@ -2963,7 +3030,7 @@ func TestJavaLibHostWithStem(t *testing.T) { `) buildOS := ctx.Config().BuildOS.String() - foo := ctx.ModuleForTests("foo", buildOS+"_common") + foo := ctx.ModuleForTests(t, "foo", buildOS+"_common") outputs := fmt.Sprint(foo.AllOutputs()) if !strings.Contains(outputs, "foo-new.jar") { @@ -2972,6 +3039,7 @@ func TestJavaLibHostWithStem(t *testing.T) { } func TestJavaLibWithStem(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -2980,7 +3048,7 @@ func TestJavaLibWithStem(t *testing.T) { } `) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") outputs := fmt.Sprint(foo.AllOutputs()) if !strings.Contains(outputs, "foo-new.jar") { @@ -2989,6 +3057,7 @@ func TestJavaLibWithStem(t *testing.T) { } func TestJavaLibraryOutputFilesRel(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -3010,9 +3079,9 @@ func TestJavaLibraryOutputFilesRel(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") - bar := result.ModuleForTests("bar", "android_common") - baz := result.ModuleForTests("baz", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") + bar := result.ModuleForTests(t, "bar", "android_common") + baz := result.ModuleForTests(t, "baz", "android_common") fooOutputPaths := foo.OutputFiles(result.TestContext, t, "") barOutputPaths := bar.OutputFiles(result.TestContext, t, "") @@ -3034,6 +3103,7 @@ func TestJavaLibraryOutputFilesRel(t *testing.T) { } func TestCoverage(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, prepareForTestWithFrameworkJacocoInstrumentation, @@ -3054,8 +3124,8 @@ func TestCoverage(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") - androidCar := result.ModuleForTests("android.car", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") + androidCar := result.ModuleForTests(t, "android.car", "android_common") fooJacoco := foo.Rule("jacoco") fooCombine := foo.Description("for javac") @@ -3104,6 +3174,7 @@ func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTe // Test that a dependency edge is created to the matching variant of a native library listed in `jni_libs` of java_binary func TestNativeRequiredDepOfJavaBinary(t *testing.T) { + t.Parallel() findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module { var ret []blueprint.Module ctx.VisitDirectDeps(module, func(dep blueprint.Module) { @@ -3125,6 +3196,6 @@ cc_library_shared { } ` res, _ := testJava(t, bp) - deps := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib") + deps := findDepsOfModule(res, res.ModuleForTests(t, "myjavabin", "android_common").Module(), "mynativelib") android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps)) } diff --git a/java/jdeps.go b/java/jdeps.go index c2ce50383..927c1694d 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -37,8 +37,6 @@ type jdepsGeneratorSingleton struct { outputPath android.Path } -var _ android.SingletonMakeVarsProvider = (*jdepsGeneratorSingleton)(nil) - const ( jdepsJsonFileName = "module_bp_java_deps.json" ) @@ -101,13 +99,6 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont Rule: android.Touch, Output: jfpath, }) -} - -func (j *jdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) { - if j.outputPath == nil { - return - } - ctx.DistForGoal("general-tests", j.outputPath) } diff --git a/java/jdeps_test.go b/java/jdeps_test.go index 143500004..00f383997 100644 --- a/java/jdeps_test.go +++ b/java/jdeps_test.go @@ -22,6 +22,7 @@ import ( ) func TestCollectJavaLibraryPropertiesAddLibsDeps(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library {name: "Foo"} @@ -31,7 +32,7 @@ func TestCollectJavaLibraryPropertiesAddLibsDeps(t *testing.T) { libs: ["Foo", "Bar"], } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) for _, expected := range []string{"Foo", "Bar"} { @@ -42,6 +43,7 @@ func TestCollectJavaLibraryPropertiesAddLibsDeps(t *testing.T) { } func TestCollectJavaLibraryPropertiesAddStaticLibsDeps(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library {name: "Foo"} @@ -51,7 +53,7 @@ func TestCollectJavaLibraryPropertiesAddStaticLibsDeps(t *testing.T) { static_libs: ["Foo", "Bar"], } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) for _, expected := range []string{"Foo", "Bar"} { @@ -62,6 +64,7 @@ func TestCollectJavaLibraryPropertiesAddStaticLibsDeps(t *testing.T) { } func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { @@ -69,7 +72,7 @@ func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) { srcs: ["Foo.java", "Bar.java"], } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) expected := []string{"Foo.java", "Bar.java"} @@ -79,6 +82,7 @@ func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) { } func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { @@ -88,7 +92,7 @@ func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) { }, } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) expected := []string{"Foo", "Bar"} @@ -98,6 +102,7 @@ func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) { } func TestCollectJavaLibraryWithJarJarRules(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { @@ -106,7 +111,7 @@ func TestCollectJavaLibraryWithJarJarRules(t *testing.T) { jarjar_rules: "jarjar_rules.txt", } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) android.AssertStringEquals(t, "IdeInfo.Srcs of repackaged library should not be empty", "foo.java", dpInfo.Srcs[0]) @@ -117,6 +122,7 @@ func TestCollectJavaLibraryWithJarJarRules(t *testing.T) { } func TestCollectJavaLibraryLinkingAgainstVersionedSdk(t *testing.T) { + t.Parallel() ctx := android.GroupFixturePreparers( prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{ @@ -129,7 +135,7 @@ func TestCollectJavaLibraryLinkingAgainstVersionedSdk(t *testing.T) { sdk_version: "29", } `) - module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey) android.AssertStringListContains(t, "IdeInfo.Deps should contain versioned sdk module", dpInfo.Deps, "sdk_public_29_android") @@ -165,11 +171,11 @@ func TestDoNotAddNoneSystemModulesToDeps(t *testing.T) { api_surface: "public", } `) - javalib := ctx.ModuleForTests("javalib", "android_common").Module().(*Library) + javalib := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library) dpInfo, _ := android.OtherModuleProvider(ctx, javalib, android.IdeInfoProviderKey) android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none") - javalib_stubs := ctx.ModuleForTests("javalib.stubs", "android_common").Module().(*ApiLibrary) + javalib_stubs := ctx.ModuleForTests(t, "javalib.stubs", "android_common").Module().(*ApiLibrary) dpInfo, _ = android.OtherModuleProvider(ctx, javalib_stubs, android.IdeInfoProviderKey) android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none") } diff --git a/java/kotlin.go b/java/kotlin.go index f42d16304..308bb0305 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -181,6 +181,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` + `mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + + `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` + `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` + ` --srcs "$out.rsp" --srcs "$srcJarDir/list"` + ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` + @@ -197,8 +198,10 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp `$kaptProcessor ` + `-Xbuild-file=$kotlinBuildFile && ` + `${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` + + `if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ + "${config.FindInputDeltaCmd}", "${config.KotlincCmd}", "${config.KotlinCompilerJar}", "${config.KotlinKaptJar}", diff --git a/java/kotlin_test.go b/java/kotlin_test.go index 45eac0134..c7b1ece98 100644 --- a/java/kotlin_test.go +++ b/java/kotlin_test.go @@ -24,6 +24,7 @@ import ( ) func TestKotlin(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -234,11 +235,12 @@ func TestKotlin(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, tt.preparer, ).RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") fooKotlinc := foo.Rule("kotlinc") android.AssertPathsRelativeToTopEquals(t, "foo kotlinc inputs", tt.fooKotlincInputs, fooKotlinc.Inputs) @@ -258,7 +260,7 @@ func TestKotlin(t *testing.T) { fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar") android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs) - bar := result.ModuleForTests("bar", "android_common") + bar := result.ModuleForTests(t, "bar", "android_common") barKotlinc := bar.Rule("kotlinc") android.AssertPathsRelativeToTopEquals(t, "bar kotlinc inputs", tt.barKotlincInputs, barKotlinc.Inputs) @@ -275,6 +277,7 @@ func TestKotlin(t *testing.T) { } func TestKapt(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -303,18 +306,19 @@ func TestKapt(t *testing.T) { } ` t.Run("", func(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, bp) buildOS := ctx.Config().BuildOS.String() - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") kaptStubs := foo.Rule("kapt") turbineApt := foo.Description("turbine apt") kotlinc := foo.Rule("kotlinc") javac := foo.Rule("javac") - bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String() - baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String() + bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String() + baz := ctx.ModuleForTests(t, "baz", buildOS+"_common").Rule("javac").Output.String() // Test that the kotlin and java sources are passed to kapt and kotlinc if len(kaptStubs.Inputs) != 2 || kaptStubs.Inputs[0].String() != "a.java" || kaptStubs.Inputs[1].String() != "b.kt" { @@ -384,6 +388,7 @@ func TestKapt(t *testing.T) { }) t.Run("errorprone", func(t *testing.T) { + t.Parallel() env := map[string]string{ "RUN_ERROR_PRONE": "true", } @@ -395,13 +400,13 @@ func TestKapt(t *testing.T) { buildOS := result.Config.BuildOS.String() - kapt := result.ModuleForTests("foo", "android_common").Rule("kapt") - javac := result.ModuleForTests("foo", "android_common").Description("javac") - errorprone := result.ModuleForTests("foo", "android_common").Description("errorprone") + kapt := result.ModuleForTests(t, "foo", "android_common").Rule("kapt") + javac := result.ModuleForTests(t, "foo", "android_common").Description("javac") + errorprone := result.ModuleForTests(t, "foo", "android_common").Description("errorprone") - bar := result.ModuleForTests("bar", buildOS+"_common").Description("javac").Output.String() - baz := result.ModuleForTests("baz", buildOS+"_common").Description("javac").Output.String() - myCheck := result.ModuleForTests("my_check", buildOS+"_common").Description("javac").Output.String() + bar := result.ModuleForTests(t, "bar", buildOS+"_common").Description("javac").Output.String() + baz := result.ModuleForTests(t, "baz", buildOS+"_common").Description("javac").Output.String() + myCheck := result.ModuleForTests(t, "my_check", buildOS+"_common").Description("javac").Output.String() // Test that the errorprone plugins are not passed to kapt expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar + @@ -434,6 +439,7 @@ func TestKapt(t *testing.T) { } func TestKaptEncodeFlags(t *testing.T) { + t.Parallel() // Compares the kaptEncodeFlags against the results of the example implementation at // https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding tests := []struct { @@ -484,6 +490,7 @@ func TestKaptEncodeFlags(t *testing.T) { for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() got := kaptEncodeFlags(test.in) if got != test.out { t.Errorf("\nwant %q\n got %q", test.out, got) @@ -493,6 +500,7 @@ func TestKaptEncodeFlags(t *testing.T) { } func TestKotlinCompose(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -501,7 +509,7 @@ func TestKotlinCompose(t *testing.T) { } kotlin_plugin { - name: "androidx.compose.compiler_compiler-hosted-plugin", + name: "kotlin-compose-compiler-plugin", } java_library { @@ -523,9 +531,9 @@ func TestKotlinCompose(t *testing.T) { buildOS := result.Config.BuildOS.String() - composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted-plugin", buildOS+"_common").Rule("combineJar").Output - withCompose := result.ModuleForTests("withcompose", "android_common") - noCompose := result.ModuleForTests("nocompose", "android_common") + composeCompiler := result.ModuleForTests(t, "kotlin-compose-compiler-plugin", buildOS+"_common").Rule("combineJar").Output + withCompose := result.ModuleForTests(t, "withcompose", "android_common") + noCompose := result.ModuleForTests(t, "nocompose", "android_common") android.AssertStringListContains(t, "missing compose compiler dependency", withCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String()) @@ -544,6 +552,7 @@ func TestKotlinCompose(t *testing.T) { } func TestKotlinPlugin(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, ).RunTestWithBp(t, ` @@ -570,9 +579,9 @@ func TestKotlinPlugin(t *testing.T) { buildOS := result.Config.BuildOS.String() - kotlinPlugin := result.ModuleForTests("kotlin_plugin", buildOS+"_common").Rule("combineJar").Output - withKotlinPlugin := result.ModuleForTests("with_kotlin_plugin", "android_common") - noKotlinPlugin := result.ModuleForTests("no_kotlin_plugin", "android_common") + kotlinPlugin := result.ModuleForTests(t, "kotlin_plugin", buildOS+"_common").Rule("combineJar").Output + withKotlinPlugin := result.ModuleForTests(t, "with_kotlin_plugin", "android_common") + noKotlinPlugin := result.ModuleForTests(t, "no_kotlin_plugin", "android_common") android.AssertStringListContains(t, "missing plugin compiler dependency", withKotlinPlugin.Rule("kotlinc").Implicits.Strings(), kotlinPlugin.String()) diff --git a/java/lint.go b/java/lint.go index ac90e19ba..66f7f8549 100644 --- a/java/lint.go +++ b/java/lint.go @@ -69,6 +69,11 @@ type LintProperties struct { // If soong gets support for testonly, this flag should be replaced with that. Test *bool + // Same as the regular Test property, but set by internal soong code based on if the module + // type is a test module type. This will act as the default value for the test property, + // but can be overridden by the user. + Test_module_type *bool `blueprint:"mutated"` + // Whether to ignore the exit code of Android lint. This is the --exit_code // option. Defaults to false. Suppress_exit_code *bool @@ -257,7 +262,12 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru if l.library { cmd.Flag("--library") } - if proptools.BoolDefault(l.properties.Lint.Test, false) { + + test := proptools.BoolDefault(l.properties.Lint.Test_module_type, false) + if l.properties.Lint.Test != nil { + test = *l.properties.Lint.Test + } + if test { cmd.Flag("--test") } if l.manifest != nil { @@ -388,7 +398,7 @@ func (l *linter) lint(ctx android.ModuleContext) { } } - extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag) + extraLintCheckModules := ctx.GetDirectDepsProxyWithTag(extraLintCheckTag) for _, extraLintCheckModule := range extraLintCheckModules { if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok { l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...) @@ -413,7 +423,7 @@ func (l *linter) lint(ctx android.ModuleContext) { depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline) - ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) { + ctx.VisitDirectDepsProxyWithTag(staticLibTag, func(dep android.ModuleProxy) { if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok { depSetsBuilder.Transitive(info) } @@ -470,7 +480,7 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd := rule.Command() - cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`). + cmd.Flag(`JAVA_OPTS="-Xmx4096m --add-opens java.base/java.util=ALL-UNNAMED"`). FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()). FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath). FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath) @@ -694,16 +704,12 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { zip(l.referenceBaselineZip, func(l *LintInfo) android.Path { return l.ReferenceBaseline }) ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip) -} -func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) { if !ctx.Config().UnbundledBuild() { ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip) } } -var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) - func init() { android.RegisterParallelSingletonType("lint", func() android.Singleton { return &lintSingleton{} }) diff --git a/java/lint_test.go b/java/lint_test.go index afe3914ff..236fa63ba 100644 --- a/java/lint_test.go +++ b/java/lint_test.go @@ -22,6 +22,7 @@ import ( ) func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -37,7 +38,7 @@ func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) { "lint-baseline.xml": nil, }) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto")) if strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") { @@ -46,6 +47,7 @@ func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) { } func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.PrepareForTestDisallowNonExistentPaths, @@ -65,6 +67,7 @@ func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) { } func TestJavaLintUsesCorrectBpConfig(t *testing.T) { + t.Parallel() ctx, _ := testJavaWithFS(t, ` java_library { name: "foo", @@ -84,7 +87,7 @@ func TestJavaLintUsesCorrectBpConfig(t *testing.T) { "mybaseline.xml": nil, }) - foo := ctx.ModuleForTests("foo", "android_common") + foo := ctx.ModuleForTests(t, "foo", "android_common") sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto")) if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") { @@ -101,6 +104,7 @@ func TestJavaLintUsesCorrectBpConfig(t *testing.T) { } func TestJavaLintBypassUpdatableChecks(t *testing.T) { + t.Parallel() testCases := []struct { name string bp string @@ -144,6 +148,7 @@ func TestJavaLintBypassUpdatableChecks(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { + t.Parallel() errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.error) android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules). ExtendWithErrorHandler(errorHandler). @@ -153,6 +158,7 @@ func TestJavaLintBypassUpdatableChecks(t *testing.T) { } func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { + t.Parallel() bp := ` java_library { name: "foo", @@ -187,7 +193,7 @@ func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()). RunTestWithBp(t, bp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") strictUpdatabilityCheck := foo.Output("lint_strict_updatability_check.stamp") if !strings.Contains(strictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi") { @@ -250,7 +256,7 @@ func TestJavaLintDatabaseSelectionFull(t *testing.T) { })). RunTestWithBp(t, thisBp) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto")) if !strings.Contains(*sboxProto.Commands[0].Command, "/"+testCase.expected_file) { t.Error("did not use full api database for case", testCase) @@ -276,3 +282,50 @@ func TestCantControlCheckSeverityWithFlags(t *testing.T) { ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")). RunTestWithBp(t, bp) } + +// b/358643466 +func TestNotTestViaDefault(t *testing.T) { + bp := ` + java_defaults { + name: "mydefaults", + lint: { + test: false, + }, + } + android_test { + name: "foo", + srcs: [ + "a.java", + ], + min_sdk_version: "29", + sdk_version: "current", + defaults: ["mydefaults"], + } + android_test { + name: "foo2", + srcs: [ + "a.java", + ], + min_sdk_version: "29", + sdk_version: "current", + } + ` + result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp) + ctx := result.TestContext + + foo := ctx.ModuleForTests(t, "foo", "android_common") + sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto")) + command := *sboxProto.Commands[0].Command + + if strings.Contains(command, "--test") { + t.Fatalf("Expected command to not contain --test") + } + + foo2 := ctx.ModuleForTests(t, "foo2", "android_common") + sboxProto2 := android.RuleBuilderSboxProtoForTests(t, ctx, foo2.Output("lint.sbox.textproto")) + command2 := *sboxProto2.Commands[0].Command + + if !strings.Contains(command2, "--test") { + t.Fatalf("Expected command to contain --test") + } +} diff --git a/java/metalava/main-config.xml b/java/metalava/main-config.xml index c61196fc6..c2881acf0 100644 --- a/java/metalava/main-config.xml +++ b/java/metalava/main-config.xml @@ -16,4 +16,20 @@ <config xmlns="http://www.google.com/tools/metalava/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd"/> + xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd"> + <api-surfaces> + <!-- These are hard coded into java_sdk_library. --> + <api-surface name="public"/> + <api-surface name="system" extends="public"/> + <api-surface name="module-lib" extends="system"/> + <api-surface name="test" extends="system"/> + <api-surface name="system-server" extends="public"/> + <!-- This is used in java/core-libraries/Android.bp. --> + <api-surface name="core"/> + <!-- These are used in libcore, external/conscrypt and external/icu. --> + <api-surface name="core-platform" extends="public"/> + <api-surface name="core-platform-legacy" extends="public"/> + <api-surface name="core-platform-plus-public"/> + <api-surface name="intra-core" extends="public"/> + </api-surfaces> +</config> diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index d09a02e50..155afc6c2 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -15,6 +15,11 @@ package java import ( + "maps" + "slices" + + "github.com/google/blueprint" + "android/soong/android" "android/soong/dexpreopt" ) @@ -29,12 +34,15 @@ func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContex // The tags used for the dependencies between the platform bootclasspath and any configured boot // jars. -var ( - platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"} - platformBootclasspathBootJarDepTag = bootclasspathDependencyTag{name: "platform-boot-jar"} - platformBootclasspathApexBootJarDepTag = bootclasspathDependencyTag{name: "apex-boot-jar"} - platformBootclasspathImplLibDepTag = dependencyTag{name: "impl-lib-tag"} -) +type platformBootclasspathImplLibDepTagType struct { + blueprint.BaseDependencyTag +} + +func (p platformBootclasspathImplLibDepTagType) ExcludeFromVisibilityEnforcement() {} + +var platformBootclasspathImplLibDepTag platformBootclasspathImplLibDepTagType + +var _ android.ExcludeFromVisibilityEnforcementTag = platformBootclasspathImplLibDepTag type platformBootclasspathModule struct { android.ModuleBase @@ -48,6 +56,12 @@ type platformBootclasspathModule struct { // The apex:module pairs obtained from the fragments. fragments []android.Module + // The map of apex to the fragments they contain. + apexNameToFragment map[string]android.Module + + // The map of library modules in the bootclasspath to the fragments that contain them. + libraryToApex map[android.Module]string + // Path to the monolithic hiddenapi-flags.csv file. hiddenAPIFlagsCSV android.OutputPath @@ -89,26 +103,12 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon b.hiddenAPIDepsMutator(ctx) - if !dexpreopt.IsDex2oatNeeded(ctx) { - return - } - - // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The - // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). - dexpreopt.RegisterToolDeps(ctx) -} - -func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) { - if ctx.Config().DisableHiddenApiChecks() { - return + if dexpreopt.IsDex2oatNeeded(ctx) { + // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The + // path is retrieved from the dependency by GetGlobalSoongConfig(ctx). + dexpreopt.RegisterToolDeps(ctx) } - // Add dependencies onto the stub lib modules. - apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config()) - hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules) -} - -func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { // Add dependencies on all the ART jars. global := dexpreopt.GetGlobalConfig(ctx) addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art") @@ -116,13 +116,13 @@ func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.Botto var bootImageModuleNames []string // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly - addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag) + addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, artBootJar) bootImageModuleNames = append(bootImageModuleNames, global.ArtApexJars.CopyOfJars()...) // Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable // APEXes. platformJars := b.platformJars(ctx) - addDependenciesOntoBootImageModules(ctx, platformJars, platformBootclasspathBootJarDepTag) + addDependenciesOntoBootImageModules(ctx, platformJars, platformBootJar) bootImageModuleNames = append(bootImageModuleNames, platformJars.CopyOfJars()...) // Add dependencies on all the updatable jars, except the ART jars. @@ -133,7 +133,7 @@ func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.Botto } addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...) // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly - addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag) + addDependenciesOntoBootImageModules(ctx, apexJars, apexBootJar) bootImageModuleNames = append(bootImageModuleNames, apexJars.CopyOfJars()...) // Add dependencies on all the fragments. @@ -147,32 +147,42 @@ func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.Botto } } -func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) { +func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) { + if ctx.Config().DisableHiddenApiChecks() { + return + } + + // Add dependencies onto the stub lib modules. + apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config()) + hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules) +} + +func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tagType bootclasspathDependencyTagType) { for i := 0; i < modules.Len(); i++ { apex := modules.Apex(i) name := modules.Jar(i) - addDependencyOntoApexModulePair(ctx, apex, name, tag) + addDependencyOntoApexModulePair(ctx, apex, name, tagType) } } func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Gather all the dependencies from the art, platform, and apex boot jars. - artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag) - platformModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathBootJarDepTag) - apexModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathApexBootJarDepTag) + artModules, artModulesToApex := gatherApexModulePairDepsWithTag(ctx, artBootJar) + platformModules, platformModulesToApex := gatherApexModulePairDepsWithTag(ctx, platformBootJar) + apexModules, apexModulesToApex := gatherApexModulePairDepsWithTag(ctx, apexBootJar) // Concatenate them all, in order as they would appear on the bootclasspath. - var allModules []android.Module - allModules = append(allModules, artModules...) - allModules = append(allModules, platformModules...) - allModules = append(allModules, apexModules...) + allModules := slices.Concat(artModules, platformModules, apexModules) b.configuredModules = allModules + b.libraryToApex = maps.Clone(artModulesToApex) + maps.Copy(b.libraryToApex, platformModulesToApex) + maps.Copy(b.libraryToApex, apexModulesToApex) // Do not add implLibModule to allModules as the impl lib is only used to collect the // transitive source files var implLibModule []android.Module - ctx.VisitDirectDepsWithTag(implLibraryTag, func(m android.Module) { + ctx.VisitDirectDepsWithTag(platformBootclasspathImplLibDepTag, func(m android.Module) { implLibModule = append(implLibModule, m) }) @@ -188,7 +198,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo TransformResourcesToJar(ctx, srcjar, jarArgs, transitiveSrcFiles) // Gather all the fragments dependencies. - b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) + b.fragments, b.apexNameToFragment = gatherFragments(ctx) // Check the configuration of the boot modules. // ART modules are checked by the art-bootclasspath-fragment. @@ -197,7 +207,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo b.generateClasspathProtoBuildActions(ctx) - bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments) + bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments, b.libraryToApex, b.apexNameToFragment) buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule) ctx.SetOutputFiles(android.Paths{b.hiddenAPIFlagsCSV}, "hiddenapi-flags.csv") @@ -248,7 +258,7 @@ func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleCon fromUpdatableApex := apexInfo.Updatable if fromUpdatableApex { // error: this jar is part of an updatable apex - ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.InApexVariants) + ctx.ModuleErrorf("module %q from updatable apex %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.BaseApexName) } else { // ok: this jar is part of the platform or a non-updatable apex } @@ -272,7 +282,11 @@ func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext // modules is complete. if !ctx.Config().AlwaysUsePrebuiltSdks() { // error: this jar is part of the platform - ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name) + if ctx.Config().AllowMissingDependencies() { + ctx.AddMissingDependencies([]string{"module_" + name + "_from_platform_is_not_allowed_in_the_apex_boot_jars_list"}) + } else { + ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name) + } } } else { // TODO(b/177892522): Treat this as an error. @@ -284,7 +298,8 @@ func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext } // generateHiddenAPIBuildActions generates all the hidden API related build rules. -func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule { +func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, + fragments []android.Module, libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) bootDexJarByModule { createEmptyHiddenApiFiles := func() { paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV} for _, path := range paths { @@ -311,7 +326,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. } // Construct a list of ClasspathElement objects from the modules and fragments. - classpathElements := CreateClasspathElements(ctx, modules, fragments) + classpathElements := CreateClasspathElements(ctx, modules, fragments, libraryToApex, apexNameToFragment) monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements) diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index 7fa6ddb38..727e30670 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -27,21 +27,27 @@ var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers( ) func TestPlatformBootclasspath(t *testing.T) { + t.Parallel() preparer := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, FixtureConfigureBootJars("platform:foo", "system_ext:bar"), + android.FixtureMergeMockFs(android.MockFS{ + "api/current.txt": nil, + "api/removed.txt": nil, + }), android.FixtureWithRootAndroidBp(` platform_bootclasspath { name: "platform-bootclasspath", } - java_library { + java_sdk_library { name: "bar", srcs: ["a.java"], system_modules: "none", sdk_version: "none", compile_dex: true, system_ext_specific: true, + unsafe_ignore_missing_latest_api: true, } `), ) @@ -76,6 +82,7 @@ func TestPlatformBootclasspath(t *testing.T) { `) t.Run("missing", func(t *testing.T) { + t.Parallel() preparer. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"platform-bootclasspath" depends on undefined module "foo"`)). RunTest(t) @@ -86,11 +93,12 @@ func TestPlatformBootclasspath(t *testing.T) { checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) { t.Helper() - srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar") + srcjar := result.ModuleForTests(t, name, "android_common").Output(name + "-transitive.srcjar") android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar") android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings()) } t.Run("source", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, @@ -107,6 +115,7 @@ func TestPlatformBootclasspath(t *testing.T) { }) t.Run("prebuilt", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( preparer, addPrebuiltBootclassPathModule, @@ -123,6 +132,7 @@ func TestPlatformBootclasspath(t *testing.T) { }) t.Run("source+prebuilt - source preferred", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, @@ -140,6 +150,7 @@ func TestPlatformBootclasspath(t *testing.T) { }) t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( preparer, addSourceBootclassPathModule, @@ -157,6 +168,7 @@ func TestPlatformBootclasspath(t *testing.T) { }) t.Run("dex import", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( preparer, android.FixtureAddTextFile("deximport/Android.bp", ` @@ -179,6 +191,7 @@ func TestPlatformBootclasspath(t *testing.T) { } func TestPlatformBootclasspathVariant(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` @@ -193,6 +206,7 @@ func TestPlatformBootclasspathVariant(t *testing.T) { } func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` @@ -204,10 +218,11 @@ func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) { p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) android.AssertStringEquals(t, "output filepath", "bootclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base()) - android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install filepath", "out/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) } func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { + t.Parallel() preparer := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, android.FixtureWithRootAndroidBp(` @@ -218,6 +233,7 @@ func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { ) t.Run("AndroidMkEntries", func(t *testing.T) { + t.Parallel() result := preparer.RunTest(t) p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) @@ -227,6 +243,7 @@ func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { }) t.Run("hiddenapi-flags-entry", func(t *testing.T) { + t.Parallel() result := preparer.RunTest(t) p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) @@ -238,6 +255,7 @@ func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { }) t.Run("classpath-fragment-entry", func(t *testing.T) { + t.Parallel() result := preparer.RunTest(t) want := map[string][]string{ @@ -262,6 +280,7 @@ func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) { } func TestPlatformBootclasspath_Dist(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, FixtureConfigureBootJars("platform:foo", "platform:bar"), @@ -305,6 +324,7 @@ func TestPlatformBootclasspath_Dist(t *testing.T) { } func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( hiddenApiFixtureFactory, PrepareForTestWithJavaSdkLibraryFiles, @@ -347,7 +367,7 @@ func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) { // Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that // creates the index.csv file. - platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common") + platformBootclasspath := result.ModuleForTests(t, "myplatform-bootclasspath", "android_common") var rule android.TestingBuildParams diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 5b145c658..d4d2fb5bb 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -51,6 +51,10 @@ func platformCompatConfigPath(ctx android.PathContext) android.OutputPath { type platformCompatConfigProperties struct { Src *string `android:"path"` + + // If true, we include it in the "merged" XML (merged_compat_config.xml). + // Default is true. + Include_in_merged_xml *bool } type platformCompatConfig struct { @@ -60,6 +64,7 @@ type platformCompatConfig struct { installDirPath android.InstallPath configFile android.OutputPath metadataFile android.OutputPath + doMerge bool installConfigFile android.InstallPath } @@ -68,6 +73,10 @@ func (p *platformCompatConfig) compatConfigMetadata() android.Path { return p.metadataFile } +func (p *platformCompatConfig) includeInMergedXml() bool { + return p.doMerge +} + func (p *platformCompatConfig) CompatConfig() android.OutputPath { return p.configFile } @@ -78,6 +87,9 @@ func (p *platformCompatConfig) SubDir() string { type platformCompatConfigMetadataProvider interface { compatConfigMetadata() android.Path + + // Whether to include it in the "merged" XML (merged_compat_config.xml) or not. + includeInMergedXml() bool } type PlatformCompatConfigIntf interface { @@ -98,6 +110,7 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon metadataFileName := p.Name() + "_meta.xml" p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath + p.doMerge = proptools.BoolDefault(p.properties.Include_in_merged_xml, true) path := android.PathForModuleSrc(ctx, String(p.properties.Src)) rule.Command(). @@ -201,6 +214,10 @@ func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path { return module.metadataFile } +func (module *prebuiltCompatConfigModule) includeInMergedXml() bool { + return true // Always include in merged.xml +} + func (module *prebuiltCompatConfigModule) BaseModuleName() string { return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name()) } @@ -237,6 +254,9 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet if !android.IsModulePreferred(module) { return } + if !c.includeInMergedXml() { + return + } metadata := c.compatConfigMetadata() compatConfigMetadata = append(compatConfigMetadata, metadata) } @@ -258,12 +278,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet rule.Build("merged-compat-config", "Merge compat config") p.metadata = outputPath -} - -func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) { - if p.metadata != nil { - ctx.DistForGoal("droidcore", p.metadata) - } + ctx.DistForGoal("droidcore", p.metadata) } func platformCompatConfigSingletonFactory() android.Singleton { diff --git a/java/platform_compat_config_test.go b/java/platform_compat_config_test.go index 80d991c49..72f81e060 100644 --- a/java/platform_compat_config_test.go +++ b/java/platform_compat_config_test.go @@ -21,11 +21,13 @@ import ( ) func TestPlatformCompatConfig(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithPlatformCompatConfig, android.FixtureWithRootAndroidBp(` platform_compat_config { name: "myconfig2", + include_in_merged_xml: false, } platform_compat_config { name: "myconfig1", @@ -38,7 +40,6 @@ func TestPlatformCompatConfig(t *testing.T) { CheckMergedCompatConfigInputs(t, result, "myconfig", "out/soong/.intermediates/myconfig1/myconfig1_meta.xml", - "out/soong/.intermediates/myconfig2/myconfig2_meta.xml", "out/soong/.intermediates/myconfig3/myconfig3_meta.xml", ) } diff --git a/java/plugin.go b/java/plugin.go index 610c9fd11..3534c7b13 100644 --- a/java/plugin.go +++ b/java/plugin.go @@ -16,8 +16,21 @@ package java import ( "android/soong/android" + "github.com/google/blueprint" ) +type JavaPluginInfo struct { + ProcessorClass *string + GeneratesApi bool +} + +var JavaPluginInfoProvider = blueprint.NewProvider[JavaPluginInfo]() + +type KotlinPluginInfo struct { +} + +var KotlinPluginInfoProvider = blueprint.NewProvider[KotlinPluginInfo]() + func init() { registerJavaPluginBuildComponents(android.InitRegistrationContext) } @@ -65,7 +78,22 @@ type PluginProperties struct { Generates_api *bool } +func (p *Plugin) GenerateAndroidBuildActions(ctx android.ModuleContext) { + p.Library.GenerateAndroidBuildActions(ctx) + + android.SetProvider(ctx, JavaPluginInfoProvider, JavaPluginInfo{ + ProcessorClass: p.pluginProperties.Processor_class, + GeneratesApi: Bool(p.pluginProperties.Generates_api), + }) +} + // Plugin describes a kotlin_plugin module, a host java/kotlin library that will be used by kotlinc as a compiler plugin. type KotlinPlugin struct { Library } + +func (p *KotlinPlugin) GenerateAndroidBuildActions(ctx android.ModuleContext) { + p.Library.GenerateAndroidBuildActions(ctx) + + android.SetProvider(ctx, KotlinPluginInfoProvider, KotlinPluginInfo{}) +} diff --git a/java/plugin_test.go b/java/plugin_test.go index dc29b1c3e..007b74a9e 100644 --- a/java/plugin_test.go +++ b/java/plugin_test.go @@ -19,6 +19,7 @@ import ( ) func TestNoPlugin(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -26,8 +27,8 @@ func TestNoPlugin(t *testing.T) { } `) - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") - turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") + turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine") if turbine.Rule == nil { t.Errorf("expected turbine to be enabled") @@ -43,6 +44,7 @@ func TestNoPlugin(t *testing.T) { } func TestPlugin(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -59,14 +61,14 @@ func TestPlugin(t *testing.T) { buildOS := ctx.Config().BuildOS.String() - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") - turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") + turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine") if turbine.Rule == nil { t.Errorf("expected turbine to be enabled") } - bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String() + bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String() if !inList(bar, javac.Implicits.Strings()) { t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar) @@ -82,6 +84,7 @@ func TestPlugin(t *testing.T) { } func TestPluginGeneratesApi(t *testing.T) { + t.Parallel() ctx, _ := testJava(t, ` java_library { name: "foo", @@ -99,14 +102,14 @@ func TestPluginGeneratesApi(t *testing.T) { buildOS := ctx.Config().BuildOS.String() - javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") - turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine") + javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac") + turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine") if turbine.Rule != nil { t.Errorf("expected turbine to be disabled") } - bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String() + bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String() if !inList(bar, javac.Implicits.Strings()) { t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar) diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go index b6fb2c6bf..1f095e49b 100644 --- a/java/prebuilt_apis_test.go +++ b/java/prebuilt_apis_test.go @@ -29,6 +29,7 @@ func intPtr(v int) *int { } func TestPrebuiltApis_SystemModulesCreation(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{ @@ -61,6 +62,7 @@ func TestPrebuiltApis_SystemModulesCreation(t *testing.T) { } func TestPrebuiltApis_WithExtensions(t *testing.T) { + t.Parallel() runTestWithBaseExtensionLevel := func(v int) (foo_input, bar_input, baz_input string) { result := android.GroupFixturePreparers( prepareForJavaTest, @@ -76,9 +78,9 @@ func TestPrebuiltApis_WithExtensions(t *testing.T) { "2": {"foo", "bar"}, }), ).RunTest(t) - foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String() - bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String() - baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String() + foo_input = result.ModuleForTests(t, "foo.api.public.latest", "").Rule("generator").Implicits[0].String() + bar_input = result.ModuleForTests(t, "bar.api.public.latest", "").Rule("generator").Implicits[0].String() + baz_input = result.ModuleForTests(t, "baz.api.public.latest", "").Rule("generator").Implicits[0].String() return } // Extension 2 is the latest for both foo and bar, finalized after the base extension version. @@ -101,6 +103,7 @@ func TestPrebuiltApis_WithExtensions(t *testing.T) { } func TestPrebuiltApis_WithIncrementalApi(t *testing.T) { + t.Parallel() runTestWithIncrementalApi := func() (foo_input, bar_input, baz_input string) { result := android.GroupFixturePreparers( prepareForJavaTest, @@ -111,9 +114,9 @@ func TestPrebuiltApis_WithIncrementalApi(t *testing.T) { "current": {"foo", "bar"}, }), ).RunTest(t) - foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String() - bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String() - baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String() + foo_input = result.ModuleForTests(t, "foo.api.public.latest", "").Rule("generator").Implicits[0].String() + bar_input = result.ModuleForTests(t, "bar.api.public.latest", "").Rule("generator").Implicits[0].String() + baz_input = result.ModuleForTests(t, "baz.api.public.latest", "").Rule("generator").Implicits[0].String() return } // 33.1 is the latest for baz, 33.2 is the latest for both foo & bar diff --git a/java/proto_test.go b/java/proto_test.go index d1cb71448..3fbe3e602 100644 --- a/java/proto_test.go +++ b/java/proto_test.go @@ -28,6 +28,7 @@ java_library_static { ` func TestProtoStream(t *testing.T) { + t.Parallel() bp := ` java_library { name: "java-stream-protos", @@ -45,7 +46,7 @@ func TestProtoStream(t *testing.T) { PrepareForIntegrationTestWithJava, ).RunTestWithBp(t, protoModules+bp) - proto0 := ctx.ModuleForTests("java-stream-protos", "android_common").Output("proto/proto0.srcjar") + proto0 := ctx.ModuleForTests(t, "java-stream-protos", "android_common").Output("proto/proto0.srcjar") if cmd := proto0.RuleParams.Command; !strings.Contains(cmd, "--javastream_out=") { t.Errorf("expected '--javastream_out' in %q", cmd) diff --git a/java/ravenwood.go b/java/ravenwood.go index 4c43a9ffb..3b6c80bc6 100644 --- a/java/ravenwood.go +++ b/java/ravenwood.go @@ -110,7 +110,7 @@ func ravenwoodTestFactory() android.Module { module.AddProperties(&module.testProperties, &module.ravenwoodTestProperties) module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.testProperties.Test_suites = []string{ "general-tests", @@ -185,26 +185,24 @@ func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { // All JNI libraries included in the runtime var runtimeJniModuleNames map[string]bool - if utils := ctx.GetDirectDepsWithTag(ravenwoodUtilsTag)[0]; utils != nil { - for _, installFile := range android.OtherModuleProviderOrDefault( - ctx, utils, android.InstallFilesProvider).InstallFiles { - installDeps = append(installDeps, installFile) - } - jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider) - if ok { - runtimeJniModuleNames = jniDeps.names - } + utils := ctx.GetDirectDepsProxyWithTag(ravenwoodUtilsTag)[0] + for _, installFile := range android.OtherModuleProviderOrDefault( + ctx, utils, android.InstallFilesProvider).InstallFiles { + installDeps = append(installDeps, installFile) + } + jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider) + if ok { + runtimeJniModuleNames = jniDeps.names } - if runtime := ctx.GetDirectDepsWithTag(ravenwoodRuntimeTag)[0]; runtime != nil { - for _, installFile := range android.OtherModuleProviderOrDefault( - ctx, runtime, android.InstallFilesProvider).InstallFiles { - installDeps = append(installDeps, installFile) - } - jniDeps, ok := android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider) - if ok { - runtimeJniModuleNames = jniDeps.names - } + runtime := ctx.GetDirectDepsProxyWithTag(ravenwoodRuntimeTag)[0] + for _, installFile := range android.OtherModuleProviderOrDefault( + ctx, runtime, android.InstallFilesProvider).InstallFiles { + installDeps = append(installDeps, installFile) + } + jniDeps, ok = android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider) + if ok { + runtimeJniModuleNames = jniDeps.names } // Also remember what JNI libs are in the runtime. @@ -228,7 +226,7 @@ func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks") copyResApk := func(tag blueprint.DependencyTag, toFileName string) { - if resApk := ctx.GetDirectDepsWithTag(tag); len(resApk) > 0 { + if resApk := ctx.GetDirectDepsProxyWithTag(tag); len(resApk) > 0 { installFile := android.OutputFileForModule(ctx, resApk[0], "") installResApk := ctx.InstallFile(resApkInstallPath, toFileName, installFile) installDeps = append(installDeps, installResApk) @@ -260,6 +258,15 @@ func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Install our JAR with all dependencies ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...) + + moduleInfoJSON := ctx.ModuleInfoJSON() + if _, ok := r.testConfig.(android.WritablePath); ok { + moduleInfoJSON.AutoTestConfig = []string{"true"} + } + if r.testConfig != nil { + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String()) + } + moduleInfoJSON.CompatibilitySuites = []string{"general-tests", "ravenwood-tests"} } func (r *ravenwoodTest) AndroidMkEntries() []android.AndroidMkEntries { @@ -345,7 +352,7 @@ func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContex // Install our runtime into expected location for packaging installPath := android.PathForModuleInstall(ctx, r.BaseModuleName()) for _, lib := range r.ravenwoodLibgroupProperties.Libs { - libModule := ctx.GetDirectDepWithTag(lib, ravenwoodLibContentTag) + libModule := ctx.GetDirectDepProxyWithTag(lib, ravenwoodLibContentTag) if libModule == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{lib}) diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go index 6394a9ac9..24a02bbdc 100644 --- a/java/ravenwood_test.go +++ b/java/ravenwood_test.go @@ -100,9 +100,10 @@ var prepareRavenwoodRuntime = android.GroupFixturePreparers( `), ) -var installPathPrefix = "out/soong/host/linux-x86/testcases" +var installPathPrefix = "out/host/linux-x86/testcases" func TestRavenwoodRuntime(t *testing.T) { + t.Parallel() if runtime.GOOS != "linux" { t.Skip("requires linux") } @@ -120,7 +121,7 @@ func TestRavenwoodRuntime(t *testing.T) { CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-utils", "android_common", "framework-rules.ravenwood") // Verify that we've emitted artifacts in expected location - runtime := ctx.ModuleForTests("ravenwood-runtime", "android_common") + runtime := ctx.ModuleForTests(t, "ravenwood-runtime", "android_common") runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-minus-apex.ravenwood.jar") runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-services.ravenwood.jar") runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni1.so") @@ -128,11 +129,12 @@ func TestRavenwoodRuntime(t *testing.T) { runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so") runtime.Output(installPathPrefix + "/ravenwood-runtime/ravenwood-data/app1.apk") runtime.Output(installPathPrefix + "/ravenwood-runtime/fonts/Font.ttf") - utils := ctx.ModuleForTests("ravenwood-utils", "android_common") + utils := ctx.ModuleForTests(t, "ravenwood-utils", "android_common") utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar") } func TestRavenwoodTest(t *testing.T) { + t.Parallel() if runtime.GOOS != "linux" { t.Skip("requires linux") } @@ -191,7 +193,7 @@ func TestRavenwoodTest(t *testing.T) { CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-utils") CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "jni-lib") - module := ctx.ModuleForTests("ravenwood-test", "android_common") + module := ctx.ModuleForTests(t, "ravenwood-test", "android_common") classpath := module.Rule("javac").Args["classpath"] // Verify that we're linking against test_current @@ -212,7 +214,7 @@ func TestRavenwoodTest(t *testing.T) { module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk") module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-inst-res.apk") - module = ctx.ModuleForTests("ravenwood-test-empty", "android_common") + module = ctx.ModuleForTests(t, "ravenwood-test-empty", "android_common") module.Output(installPathPrefix + "/ravenwood-test-empty/ravenwood.properties") // ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted. diff --git a/java/robolectric.go b/java/robolectric.go index 5f46267f9..43e17f9ea 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -21,6 +21,7 @@ import ( "android/soong/java/config" "android/soong/tradefed" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -28,6 +29,23 @@ func init() { RegisterRobolectricBuildComponents(android.InitRegistrationContext) } +type RobolectricRuntimesInfo struct { + Runtimes []android.InstallPath +} + +var RobolectricRuntimesInfoProvider = blueprint.NewProvider[RobolectricRuntimesInfo]() + +type roboRuntimeOnlyDependencyTag struct { + blueprint.BaseDependencyTag +} + +var roboRuntimeOnlyDepTag roboRuntimeOnlyDependencyTag + +// Mark this tag so dependencies that use it are excluded from visibility enforcement. +func (t roboRuntimeOnlyDependencyTag) ExcludeFromVisibilityEnforcement() {} + +var _ android.ExcludeFromVisibilityEnforcementTag = roboRuntimeOnlyDepTag + func RegisterRobolectricBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_robolectric_test", RobolectricTestFactory) ctx.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory) @@ -41,12 +59,12 @@ var robolectricDefaultLibs = []string{ } const robolectricCurrentLib = "Robolectric_all-target" +const clearcutJunitLib = "ClearcutJunitListenerAar" const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt" var ( roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"} roboRuntimesTag = dependencyTag{name: "roboRuntimes"} - roboRuntimeOnlyTag = dependencyTag{name: "roboRuntimeOnlyTag"} ) type robolectricProperties struct { @@ -64,10 +82,6 @@ type robolectricProperties struct { Shards *int64 } - // The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric - // instead of the one built from source in external/robolectric-shadows. - Robolectric_prebuilt_version *string - // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric // to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows Upstream *bool @@ -106,21 +120,12 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module") } - if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" { - ctx.AddVariationDependencies(nil, staticLibTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v)) - } else if !proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) { - if proptools.Bool(r.robolectricProperties.Upstream) { - ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib+"_upstream") - } else { - ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib) - } - } + ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, clearcutJunitLib) if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) { - ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream") + ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, robolectricCurrentLib) } else { - // opting out from strict mode, robolectric_non_strict_mode_permission lib should be added - ctx.AddVariationDependencies(nil, staticLibTag, "robolectric_non_strict_mode_permission") + ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib) } ctx.AddVariationDependencies(nil, staticLibTag, robolectricDefaultLibs...) @@ -139,13 +144,25 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) r.forceOSType = ctx.Config().BuildOS r.forceArchType = ctx.Config().BuildArch + var extraTestRunnerOptions []tradefed.Option + extraTestRunnerOptions = append(extraTestRunnerOptions, tradefed.Option{Name: "java-flags", Value: "-Drobolectric=true"}) + if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) { + extraTestRunnerOptions = append(extraTestRunnerOptions, tradefed.Option{Name: "java-flags", Value: "-Drobolectric.strict.mode=true"}) + } + + var extraOptions []tradefed.Option + var javaHome = ctx.Config().Getenv("ANDROID_JAVA_HOME") + extraOptions = append(extraOptions, tradefed.Option{Name: "java-folder", Value: javaHome}) + r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ - TestConfigProp: r.testProperties.Test_config, - TestConfigTemplateProp: r.testProperties.Test_config_template, - TestSuites: r.testProperties.Test_suites, - AutoGenConfig: r.testProperties.Auto_gen_config, - DeviceTemplate: "${RobolectricTestConfigTemplate}", - HostTemplate: "${RobolectricTestConfigTemplate}", + TestConfigProp: r.testProperties.Test_config, + TestConfigTemplateProp: r.testProperties.Test_config_template, + TestSuites: r.testProperties.Test_suites, + OptionsForAutogenerated: extraOptions, + TestRunnerOptions: extraTestRunnerOptions, + AutoGenConfig: r.testProperties.Auto_gen_config, + DeviceTemplate: "${RobolectricTestConfigTemplate}", + HostTemplate: "${RobolectricTestConfigTemplate}", }) r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data) r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...) @@ -153,25 +170,27 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...) var ok bool - var instrumentedApp *AndroidApp + var instrumentedApp *JavaInfo + var appInfo *AppInfo // TODO: this inserts paths to built files into the test, it should really be inserting the contents. - instrumented := ctx.GetDirectDepsWithTag(instrumentationForTag) + instrumented := ctx.GetDirectDepsProxyWithTag(instrumentationForTag) if len(instrumented) == 1 { - instrumentedApp, ok = instrumented[0].(*AndroidApp) + appInfo, ok = android.OtherModuleProvider(ctx, instrumented[0], AppInfoProvider) if !ok { ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app") } + instrumentedApp = android.OtherModuleProviderOrDefault(ctx, instrumented[0], JavaInfoProvider) } else if !ctx.Config().AllowMissingDependencies() { panic(fmt.Errorf("expected exactly 1 instrumented dependency, got %d", len(instrumented))) } var resourceApk android.Path var manifest android.Path - if instrumentedApp != nil { - manifest = instrumentedApp.mergedManifestFile - resourceApk = instrumentedApp.outputFile + if appInfo != nil { + manifest = appInfo.MergedManifestFile + resourceApk = instrumentedApp.OutputFile } roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar") @@ -179,7 +198,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) extraCombinedJars := android.Paths{roboTestConfigJar} - handleLibDeps := func(dep android.Module) { + handleLibDeps := func(dep android.ModuleProxy) { if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) { if m, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { extraCombinedJars = append(extraCombinedJars, m.ImplementationAndResourcesJars...) @@ -187,25 +206,25 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) } } - for _, dep := range ctx.GetDirectDepsWithTag(libTag) { + for _, dep := range ctx.GetDirectDepsProxyWithTag(libTag) { handleLibDeps(dep) } - for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) { + for _, dep := range ctx.GetDirectDepsProxyWithTag(sdkLibTag) { handleLibDeps(dep) } // handle the runtimeOnly tag for strict_mode - for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) { + for _, dep := range ctx.GetDirectDepsProxyWithTag(roboRuntimeOnlyDepTag) { handleLibDeps(dep) } - if instrumentedApp != nil { - extraCombinedJars = append(extraCombinedJars, instrumentedApp.implementationAndResourcesJar) + if appInfo != nil { + extraCombinedJars = append(extraCombinedJars, instrumentedApp.ImplementationAndResourcesJars...) } r.stem = proptools.StringDefault(r.overridableProperties.Stem, ctx.ModuleName()) r.classLoaderContexts = r.usesLibrary.classLoaderContextForUsesLibDeps(ctx) r.dexpreopter.disableDexpreopt() - r.compile(ctx, nil, nil, nil, extraCombinedJars) + javaInfo := r.compile(ctx, nil, nil, nil, extraCombinedJars) installPath := android.PathForModuleInstall(ctx, r.BaseModuleName()) var installDeps android.InstallPaths @@ -227,8 +246,8 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) installDeps = append(installDeps, installedResourceApk) } - runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag) - for _, runtime := range runtimes.(*robolectricRuntimes).runtimes { + runtimes := ctx.GetDirectDepProxyWithTag("robolectric-android-all-prebuilts", roboRuntimesTag) + for _, runtime := range android.OtherModuleProviderOrDefault(ctx, runtimes, RobolectricRuntimesInfoProvider).Runtimes { installDeps = append(installDeps, runtime) } @@ -242,6 +261,24 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) } r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...) + + if javaInfo != nil { + setExtraJavaInfo(ctx, r, javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + } + + moduleInfoJSON := r.javaLibraryModuleInfoJSON(ctx) + if _, ok := r.testConfig.(android.WritablePath); ok { + moduleInfoJSON.AutoTestConfig = []string{"true"} + } + if r.testConfig != nil { + moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String()) + } + if len(r.testProperties.Test_suites) > 0 { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, r.testProperties.Test_suites...) + } else { + moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") + } } func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) { @@ -292,7 +329,7 @@ func RobolectricTestFactory() android.Module { &module.testProperties) module.Module.dexpreopter.isTest = true - module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) + module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) module.testProperties.Test_suites = []string{"robolectric-tests"} @@ -357,7 +394,7 @@ func (r *robolectricRuntimes) GenerateAndroidBuildActions(ctx android.ModuleCont } if !ctx.Config().AlwaysUsePrebuiltSdks() && r.props.Lib != nil { - runtimeFromSourceModule := ctx.GetDirectDepWithTag(String(r.props.Lib), libTag) + runtimeFromSourceModule := ctx.GetDirectDepProxyWithTag(String(r.props.Lib), libTag) if runtimeFromSourceModule == nil { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{String(r.props.Lib)}) @@ -375,6 +412,10 @@ func (r *robolectricRuntimes) GenerateAndroidBuildActions(ctx android.ModuleCont installedRuntime := ctx.InstallFile(androidAllDir, runtimeName, runtimeFromSourceJar) r.runtimes = append(r.runtimes, installedRuntime) } + + android.SetProvider(ctx, RobolectricRuntimesInfoProvider, RobolectricRuntimesInfo{ + Runtimes: r.runtimes, + }) } func (r *robolectricRuntimes) InstallInTestcases() bool { return true } diff --git a/java/robolectric_test.go b/java/robolectric_test.go index 4775bac64..4bf224b4f 100644 --- a/java/robolectric_test.go +++ b/java/robolectric_test.go @@ -32,6 +32,11 @@ var prepareRobolectricRuntime = android.GroupFixturePreparers( } java_library { + name: "Robolectric_all-target", + srcs: ["Robo.java"] + } + + java_library { name: "mockito-robolectric-prebuilt", srcs: ["Mockito.java"] } @@ -44,6 +49,12 @@ var prepareRobolectricRuntime = android.GroupFixturePreparers( java_library { name: "junitxml", srcs: ["JUnitXml.java"] + + } + + java_library { + name: "ClearcutJunitListenerAar", + srcs: ["Runtime.java"] } java_library_host { @@ -60,6 +71,7 @@ var prepareRobolectricRuntime = android.GroupFixturePreparers( ) func TestRobolectricJniTest(t *testing.T) { + t.Parallel() if runtime.GOOS != "linux" { t.Skip("requires linux") } @@ -93,6 +105,6 @@ func TestRobolectricJniTest(t *testing.T) { CheckModuleHasDependency(t, ctx.TestContext, "robo-test", "android_common", "jni-lib1") // Check that the .so files make it into the output. - module := ctx.ModuleForTests("robo-test", "android_common") + module := ctx.ModuleForTests(t, "robo-test", "android_common") module.Output(installPathPrefix + "/robo-test/lib64/jni-lib1.so") } diff --git a/java/rro.go b/java/rro.go index d277e4ab7..d9f4ff7c8 100644 --- a/java/rro.go +++ b/java/rro.go @@ -139,6 +139,25 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC r.aapt.hasNoCode = true // Do not remove resources without default values nor dedupe resource configurations with the same value aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"} + + // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided. + hasProduct := android.PrefixInList(r.aaptProperties.Aaptflags, "--product") + if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { + aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics()) + } + + if !Bool(r.aaptProperties.Aapt_include_all_resources) { + // Product AAPT config + for _, aaptConfig := range ctx.Config().ProductAAPTConfig() { + aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig) + } + + // Product AAPT preferred config + if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 { + aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig()) + } + } + // Allow the override of "package name" and "overlay target package name" manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName()) if overridden || r.overridableProperties.Package_name != nil { @@ -187,6 +206,8 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ AconfigTextFiles: aconfigTextFilePaths, }) + + buildComplianceMetadata(ctx) } func (r *RuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { @@ -290,7 +311,8 @@ type AutogenRuntimeResourceOverlay struct { properties AutogenRuntimeResourceOverlayProperties - outputFile android.Path + certificate Certificate + outputFile android.Path } type AutogenRuntimeResourceOverlayProperties struct { @@ -380,7 +402,8 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android. return } // Sign the built package - _, certificates := processMainCert(a.ModuleBase, "", nil, ctx) + var certificates []Certificate + a.certificate, certificates = processMainCert(a.ModuleBase, "", nil, ctx) signed := android.PathForModuleOut(ctx, "signed", a.Name()+".apk") SignAppPackage(ctx, signed, a.exportPackage, certificates, nil, nil, "") a.outputFile = signed diff --git a/java/rro_test.go b/java/rro_test.go index 4d791305e..0ccc8e707 100644 --- a/java/rro_test.go +++ b/java/rro_test.go @@ -24,6 +24,7 @@ import ( ) func TestRuntimeResourceOverlay(t *testing.T) { + t.Parallel() fs := android.MockFS{ "baz/res/res/values/strings.xml": nil, "bar/res/res/values/strings.xml": nil, @@ -66,7 +67,7 @@ func TestRuntimeResourceOverlay(t *testing.T) { fs.AddToFixture(), ).RunTestWithBp(t, bp) - m := result.ModuleForTests("foo", "android_common") + m := result.ModuleForTests(t, "foo", "android_common") // Check AAPT2 link flags. aapt2Flags := m.Output("package-res.apk").Args["flags"] @@ -115,7 +116,7 @@ func TestRuntimeResourceOverlay(t *testing.T) { android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path) // A themed module has a different device location - m = result.ModuleForTests("foo_themed", "android_common") + m = result.ModuleForTests(t, "foo_themed", "android_common") androidMkEntries = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0] path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"] expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay/faza")} @@ -129,6 +130,7 @@ func TestRuntimeResourceOverlay(t *testing.T) { } func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureModifyConfig(android.SetKatiEnabledForTests), @@ -153,7 +155,7 @@ func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { // // RRO module with defaults // - m := result.ModuleForTests("foo_with_defaults", "android_common") + m := result.ModuleForTests(t, "foo_with_defaults", "android_common") // Check AAPT2 link flags. aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ") @@ -171,7 +173,7 @@ func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { // // RRO module without defaults // - m = result.ModuleForTests("foo_barebones", "android_common") + m = result.ModuleForTests(t, "foo_barebones", "android_common") // Check AAPT2 link flags. aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ") @@ -216,7 +218,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { }{ { variantName: "android_common", - apkPath: "out/soong/target/product/test_device/product/overlay/foo_overlay.apk", + apkPath: "out/target/product/test_device/product/overlay/foo_overlay.apk", overrides: nil, targetVariant: "android_common", packageFlag: "", @@ -224,7 +226,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { }, { variantName: "android_common_bar_overlay", - apkPath: "out/soong/target/product/test_device/product/overlay/bar_overlay.apk", + apkPath: "out/target/product/test_device/product/overlay/bar_overlay.apk", overrides: []string{"foo_overlay"}, targetVariant: "android_common_bar", packageFlag: "com.android.bar.overlay", @@ -233,7 +235,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { }, } for _, expected := range expectedVariants { - variant := ctx.ModuleForTests("foo_overlay", expected.variantName) + variant := ctx.ModuleForTests(t, "foo_overlay", expected.variantName) // Check the final apk name variant.Output(expected.apkPath) @@ -255,103 +257,6 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { } } -func TestEnforceRRO_propagatesToDependencies(t *testing.T) { - testCases := []struct { - name string - enforceRROTargets []string - rroDirs map[string][]string - }{ - { - name: "no RRO", - enforceRROTargets: nil, - rroDirs: map[string][]string{ - "foo": nil, - "bar": nil, - }, - }, - { - name: "enforce RRO on all", - enforceRROTargets: []string{"*"}, - rroDirs: map[string][]string{ - "foo": {"product/vendor/blah/overlay/lib2/res"}, - "bar": {"product/vendor/blah/overlay/lib2/res"}, - }, - }, - { - name: "enforce RRO on foo", - enforceRROTargets: []string{"foo"}, - rroDirs: map[string][]string{ - "foo": {"product/vendor/blah/overlay/lib2/res"}, - "bar": nil, - }, - }, - } - - productResourceOverlays := []string{ - "product/vendor/blah/overlay", - } - - fs := android.MockFS{ - "lib2/res/values/strings.xml": nil, - "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil, - } - - bp := ` - android_app { - name: "foo", - sdk_version: "current", - resource_dirs: [], - static_libs: ["lib"], - } - - android_app { - name: "bar", - sdk_version: "current", - resource_dirs: [], - static_libs: ["lib"], - } - - android_library { - name: "lib", - sdk_version: "current", - resource_dirs: [], - static_libs: ["lib2"], - } - - android_library { - name: "lib2", - sdk_version: "current", - resource_dirs: ["lib2/res"], - } - ` - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - result := android.GroupFixturePreparers( - PrepareForTestWithJavaDefaultModules, - fs.AddToFixture(), - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.ProductResourceOverlays = productResourceOverlays - if testCase.enforceRROTargets != nil { - variables.EnforceRROTargets = testCase.enforceRROTargets - } - }), - ).RunTestWithBp(t, bp) - - modules := []string{"foo", "bar"} - for _, moduleName := range modules { - module := result.ModuleForTests(moduleName, "android_common") - mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0] - actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"] - if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) { - t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q", - moduleName, testCase.rroDirs[moduleName], actualRRODirs) - } - } - }) - } -} - func TestRuntimeResourceOverlayPartition(t *testing.T) { bp := ` runtime_resource_overlay { @@ -380,28 +285,28 @@ func TestRuntimeResourceOverlayPartition(t *testing.T) { }{ { name: "device_specific", - expectedPath: "out/soong/target/product/test_device/odm/overlay", + expectedPath: "out/target/product/test_device/odm/overlay", }, { name: "soc_specific", - expectedPath: "out/soong/target/product/test_device/vendor/overlay", + expectedPath: "out/target/product/test_device/vendor/overlay", }, { name: "system_ext_specific", - expectedPath: "out/soong/target/product/test_device/system_ext/overlay", + expectedPath: "out/target/product/test_device/system_ext/overlay", }, { name: "product_specific", - expectedPath: "out/soong/target/product/test_device/product/overlay", + expectedPath: "out/target/product/test_device/product/overlay", }, { name: "default", - expectedPath: "out/soong/target/product/test_device/product/overlay", + expectedPath: "out/target/product/test_device/product/overlay", }, } for _, testCase := range testCases { ctx, _ := testJava(t, bp) - mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*RuntimeResourceOverlay) + mod := ctx.ModuleForTests(t, testCase.name, "android_common").Module().(*RuntimeResourceOverlay) android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir) } } @@ -436,7 +341,7 @@ func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) { } `) - foo := result.ModuleForTests("foo", "android_common") + foo := result.ModuleForTests(t, "foo", "android_common") // runtime_resource_overlay module depends on aconfig_declarations listed in flags_packages android.AssertBoolEquals(t, "foo expected to depend on bar", true, diff --git a/java/sdk.go b/java/sdk.go index bb2aa8d7e..27b2434c5 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -381,6 +381,10 @@ func createAPIFingerprint(ctx android.SingletonContext) { } rule.Build("api_fingerprint", "generate api_fingerprint.txt") + + if ctx.Config().BuildOS == android.Linux { + ctx.DistForGoals([]string{"sdk", "droidcore"}, out) + } } func sdkMakeVars(ctx android.MakeVarsContext) { diff --git a/java/sdk_library.go b/java/sdk_library.go index 78917768b..cf31b5095 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -316,6 +316,15 @@ func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) s return name } +func (scopes apiScopes) matchingScopeFromSdkKind(kind android.SdkKind) *apiScope { + for _, scope := range scopes { + if scope.kind == kind { + return scope + } + } + return nil +} + var ( scopeByName = make(map[string]*apiScope) allScopeNames []string @@ -480,6 +489,9 @@ type ApiScopeProperties struct { // Extra libs used when compiling stubs for this scope. Libs []string + + // Name to override the api_surface that is passed down to droidstubs. + Api_surface *string } type sdkLibraryProperties struct { @@ -690,9 +702,9 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.Modul paths.stubsHeaderPath = lib.HeaderJars paths.stubsImplPath = lib.ImplementationJars - libDep := dep.(UsesLibraryDependency) - paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx) - paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx) + libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider).UsesLibraryDependencyInfo + paths.stubsDexJarPath = libDep.DexJarBuildPath + paths.exportableStubsDexJarPath = libDep.DexJarBuildPath return nil } else { return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") @@ -706,8 +718,8 @@ func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx and paths.stubsImplPath = lib.ImplementationJars } - libDep := dep.(UsesLibraryDependency) - paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx) + libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider).UsesLibraryDependencyInfo + paths.stubsDexJarPath = libDep.DexJarBuildPath return nil } else { return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") @@ -720,58 +732,67 @@ func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx and paths.stubsImplPath = lib.ImplementationJars } - libDep := dep.(UsesLibraryDependency) - paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx) + libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider).UsesLibraryDependencyInfo + paths.exportableStubsDexJarPath = libDep.DexJarBuildPath return nil } else { return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") } } -func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider) error) error { - if apiStubsProvider, ok := dep.(ApiStubsProvider); ok { - err := action(apiStubsProvider) - if err != nil { - return err - } - return nil - } else { - return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs") +func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, dep android.Module, + action func(*DroidStubsInfo, *StubsSrcInfo) error) error { + apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider) + if !ok { + return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs") } + + apiStubsSrcProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider) + if !ok { + return fmt.Errorf("expected module that provides StubsSrcInfo, e.g. droidstubs") + } + return action(&apiStubsProvider, &apiStubsSrcProvider) } -func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error { - if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok { - err := action(apiStubsProvider) +func (paths *scopePaths) treatDepAsApiStubsSrcProvider( + ctx android.ModuleContext, dep android.Module, action func(provider *StubsSrcInfo) error) error { + if apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider); ok { + err := action(&apiStubsProvider) if err != nil { return err } return nil } else { - return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs") + return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs") } } -func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider, stubsType StubsType) error { - var annotationsZip, currentApiFilePath, removedApiFilePath android.Path - annotationsZip, annotationsZipErr := provider.AnnotationsZip(stubsType) - currentApiFilePath, currentApiFilePathErr := provider.ApiFilePath(stubsType) - removedApiFilePath, removedApiFilePathErr := provider.RemovedApiFilePath(stubsType) - - combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr) +func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider *DroidStubsInfo, stubsType StubsType) error { + var currentApiFilePathErr, removedApiFilePathErr error + info, err := getStubsInfoForType(provider, stubsType) + if err != nil { + return err + } + if info.ApiFile == nil { + currentApiFilePathErr = fmt.Errorf("expected module that provides ApiFile") + } + if info.RemovedApiFile == nil { + removedApiFilePathErr = fmt.Errorf("expected module that provides RemovedApiFile") + } + combinedError := errors.Join(currentApiFilePathErr, removedApiFilePathErr) if combinedError == nil { - paths.annotationsZip = android.OptionalPathForPath(annotationsZip) - paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath) - paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath) + paths.annotationsZip = android.OptionalPathForPath(info.AnnotationsZip) + paths.currentApiFilePath = android.OptionalPathForPath(info.ApiFile) + paths.removedApiFilePath = android.OptionalPathForPath(info.RemovedApiFile) } return combinedError } -func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error { - stubsSrcJar, err := provider.StubsSrcJar(stubsType) +func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider *StubsSrcInfo, stubsType StubsType) error { + path, err := getStubsSrcInfoForType(provider, stubsType) if err == nil { - paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar) + paths.stubsSrcJar = android.OptionalPathForPath(path) } return err } @@ -781,7 +802,7 @@ func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext if ctx.Config().ReleaseHiddenApiExportableStubs() { stubsType = Exportable } - return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error { + return paths.treatDepAsApiStubsSrcProvider(ctx, dep, func(provider *StubsSrcInfo) error { return paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType) }) } @@ -791,17 +812,17 @@ func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx an if ctx.Config().ReleaseHiddenApiExportableStubs() { stubsType = Exportable } - return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error { - extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, stubsType) - extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType) + return paths.treatDepAsApiStubsProvider(ctx, dep, func(apiStubsProvider *DroidStubsInfo, apiStubsSrcProvider *StubsSrcInfo) error { + extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(apiStubsProvider, stubsType) + extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(apiStubsSrcProvider, stubsType) return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr) }) } -func extractOutputPaths(dep android.Module) (android.Paths, error) { +func extractOutputPaths(ctx android.ModuleContext, dep android.Module) (android.Paths, error) { var paths android.Paths - if sourceFileProducer, ok := dep.(android.SourceFileProducer); ok { - paths = sourceFileProducer.Srcs() + if sourceFileProducer, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok { + paths = sourceFileProducer.Srcs return paths, nil } else { return nil, fmt.Errorf("module %q does not produce source files", dep) @@ -809,17 +830,47 @@ func extractOutputPaths(dep android.Module) (android.Paths, error) { } func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error { - outputPaths, err := extractOutputPaths(dep) + outputPaths, err := extractOutputPaths(ctx, dep) paths.latestApiPaths = outputPaths return err } func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error { - outputPaths, err := extractOutputPaths(dep) + outputPaths, err := extractOutputPaths(ctx, dep) paths.latestRemovedApiPaths = outputPaths return err } +func getStubsInfoForType(info *DroidStubsInfo, stubsType StubsType) (ret *StubsInfo, err error) { + switch stubsType { + case Everything: + ret, err = &info.EverythingStubsInfo, nil + case Exportable: + ret, err = &info.ExportableStubsInfo, nil + default: + ret, err = nil, fmt.Errorf("stubs info not supported for the stub type %s", stubsType.String()) + } + if ret == nil && err == nil { + err = fmt.Errorf("stubs info is null for the stub type %s", stubsType.String()) + } + return ret, err +} + +func getStubsSrcInfoForType(info *StubsSrcInfo, stubsType StubsType) (ret android.Path, err error) { + switch stubsType { + case Everything: + ret, err = info.EverythingStubsSrcJar, nil + case Exportable: + ret, err = info.ExportableStubsSrcJar, nil + default: + ret, err = nil, fmt.Errorf("stubs src info not supported for the stub type %s", stubsType.String()) + } + if ret == nil && err == nil { + err = fmt.Errorf("stubs src info is null for the stub type %s", stubsType.String()) + } + return ret, err +} + type commonToSdkLibraryAndImportProperties struct { // Specifies whether this module can be used as an Android shared library; defaults // to true. @@ -880,6 +931,8 @@ type commonSdkLibraryAndImportModule interface { RootLibraryName() string } +var _ android.ApexModule = (*SdkLibrary)(nil) + func (m *SdkLibrary) RootLibraryName() string { return m.BaseModuleName() } @@ -908,9 +961,9 @@ type commonToSdkLibraryAndImport struct { // This is non-empty only when api_only is false. implLibraryHeaderJars android.Paths - // The reference to the implementation library created by the source module. - // Is nil if the source module does not exist. - implLibraryModule *Library + // The reference to the JavaInfo provided by implementation library created by + // the source module. Is nil if the source module does not exist. + implLibraryInfo *JavaInfo } func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) { @@ -964,6 +1017,10 @@ func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.Mod removedApiFilePaths[kind] = removedApiFilePath } + javaInfo := &JavaInfo{} + setExtraJavaInfo(ctx, ctx.Module(), javaInfo) + android.SetProvider(ctx, JavaInfoProvider, javaInfo) + return SdkLibraryInfo{ EverythingStubDexJarPaths: everythingStubPaths, ExportableStubDexJarPaths: exportableStubPaths, @@ -1200,7 +1257,8 @@ type SdkLibrary struct { commonToSdkLibraryAndImport - builtInstalledForApex []dexpreopterInstall + apexSystemServerDexpreoptInstalls []DexpreopterInstall + apexSystemServerDexJars android.Paths } func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool { @@ -1211,16 +1269,16 @@ var _ UsesLibraryDependency = (*SdkLibrary)(nil) // To satisfy the UsesLibraryDependency interface func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { - if module.implLibraryModule != nil { - return module.implLibraryModule.DexJarBuildPath(ctx) + if module.implLibraryInfo != nil { + return module.implLibraryInfo.DexJarFile } return makeUnsetDexJarPath() } // To satisfy the UsesLibraryDependency interface func (module *SdkLibrary) DexJarInstallPath() android.Path { - if module.implLibraryModule != nil { - return module.implLibraryModule.DexJarInstallPath() + if module.implLibraryInfo != nil { + return module.implLibraryInfo.InstallFile } return nil } @@ -1282,7 +1340,7 @@ func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) { ctx.WalkDeps(func(child android.Module, parent android.Module) bool { - isExternal := !module.depIsInSameApex(ctx, child) + isExternal := !android.IsDepInSameApex(ctx, module, child) if am, ok := child.(android.ApexModule); ok { if !do(ctx, parent, am, isExternal) { return false @@ -1407,11 +1465,11 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) // Collate the components exported by this module. All scope specific modules are exported but // the impl and xml component modules are not. exportedComponents := map[string]struct{}{} - + var implLib android.ModuleProxy // Record the paths to the header jars of the library (stubs and impl). // When this java_sdk_library is depended upon from others via "libs" property, // the recorded paths will be returned depending on the link type of the caller. - ctx.VisitDirectDeps(func(to android.Module) { + ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(to) // Extract information from any of the scope specific dependencies. @@ -1431,7 +1489,8 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) if tag == implLibraryTag { if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...) - module.implLibraryModule = to.(*Library) + module.implLibraryInfo = dep + implLib = to } } }) @@ -1442,44 +1501,44 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) module.hideApexVariantFromMake = true } - if module.implLibraryModule != nil { + if module.implLibraryInfo != nil { if ctx.Device() { - module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile} - module.bootDexJarPath = module.implLibraryModule.bootDexJarPath - module.uncompressDexState = module.implLibraryModule.uncompressDexState - module.active = module.implLibraryModule.active + module.classesJarPaths = module.implLibraryInfo.ImplementationJars + module.bootDexJarPath = module.implLibraryInfo.BootDexJarPath + module.uncompressDexState = module.implLibraryInfo.UncompressDexState + module.active = module.implLibraryInfo.Active } - module.outputFile = module.implLibraryModule.outputFile - module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path()) - module.headerJarFile = module.implLibraryModule.headerJarFile - module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar - module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex - module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath - module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost + module.outputFile = module.implLibraryInfo.OutputFile + module.dexJarFile = makeDexJarPathFromPath(module.implLibraryInfo.DexJarFile.Path()) + module.headerJarFile = module.implLibraryInfo.HeaderJars[0] + module.implementationAndResourcesJar = module.implLibraryInfo.ImplementationAndResourcesJars[0] + module.apexSystemServerDexpreoptInstalls = module.implLibraryInfo.ApexSystemServerDexpreoptInstalls + module.apexSystemServerDexJars = module.implLibraryInfo.ApexSystemServerDexJars + module.dexpreopter.configPath = module.implLibraryInfo.ConfigPath + module.dexpreopter.outputProfilePathOnHost = module.implLibraryInfo.OutputProfilePathOnHost // Properties required for Library.AndroidMkEntries - module.logtagsSrcs = module.implLibraryModule.logtagsSrcs - module.dexpreopter.builtInstalled = module.implLibraryModule.dexpreopter.builtInstalled - module.jacocoReportClassesFile = module.implLibraryModule.jacocoReportClassesFile - module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary - module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip - module.linter.reports = module.implLibraryModule.linter.reports - - if lintInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, LintProvider); ok { + module.logtagsSrcs = module.implLibraryInfo.LogtagsSrcs + module.dexpreopter.builtInstalled = module.implLibraryInfo.BuiltInstalled + module.jacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile + module.dexer.proguardDictionary = module.implLibraryInfo.ProguardDictionary + module.dexer.proguardUsageZip = module.implLibraryInfo.ProguardUsageZip + module.linter.reports = module.implLibraryInfo.LinterReports + + if lintInfo, ok := android.OtherModuleProvider(ctx, implLib, LintProvider); ok { android.SetProvider(ctx, LintProvider, lintInfo) } if !module.Host() { - module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile + module.hostdexInstallFile = module.implLibraryInfo.HostdexInstallFile } - if installFilesInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, android.InstallFilesProvider); ok { + if installFilesInfo, ok := android.OtherModuleProvider(ctx, implLib, android.InstallFilesProvider); ok { if installFilesInfo.CheckbuildTarget != nil { ctx.CheckbuildFile(installFilesInfo.CheckbuildTarget) } } - android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()}) } // Make the set of components exported by this module available for use elsewhere. @@ -1518,17 +1577,32 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } } - if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil { + if module.requiresRuntimeImplementationLibrary() && module.implLibraryInfo != nil { generatingLibs = append(generatingLibs, module.implLibraryModuleName()) - setOutputFiles(ctx, module.implLibraryModule.Module) + setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo) } sdkLibInfo.GeneratingLibs = generatingLibs android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo) } -func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall { - return module.builtInstalledForApex +func setOutputFilesFromJavaInfo(ctx android.ModuleContext, info *JavaInfo) { + ctx.SetOutputFiles(append(android.PathsIfNonNil(info.OutputFile), info.ExtraOutputFiles...), "") + ctx.SetOutputFiles(android.PathsIfNonNil(info.OutputFile), android.DefaultDistTag) + ctx.SetOutputFiles(info.ImplementationAndResourcesJars, ".jar") + ctx.SetOutputFiles(info.HeaderJars, ".hjar") + if info.ProguardDictionary.Valid() { + ctx.SetOutputFiles(android.Paths{info.ProguardDictionary.Path()}, ".proguard_map") + } + ctx.SetOutputFiles(info.GeneratedSrcjars, ".generated_srcjars") +} + +func (module *SdkLibrary) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall { + return module.apexSystemServerDexpreoptInstalls +} + +func (module *SdkLibrary) ApexSystemServerDexJars() android.Paths { + return module.apexSystemServerDexJars } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { @@ -1636,15 +1710,22 @@ func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool { } // Implements android.ApexModule -func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool { - depTag := mctx.OtherModuleDependencyTag(dep) - if depTag == xmlPermissionsFileTag { +func (m *SdkLibrary) GetDepInSameApexChecker() android.DepInSameApexChecker { + return SdkLibraryDepInSameApexChecker{} +} + +type SdkLibraryDepInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m SdkLibraryDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + if tag == xmlPermissionsFileTag { return true } - if dep.Name() == module.implLibraryModuleName() { + if tag == implLibraryTag { return true } - return module.Library.DepIsInSameApex(mctx, dep) + return depIsInSameApex(tag) } // Implements android.ApexModule @@ -1901,10 +1982,6 @@ type SdkLibraryImport struct { commonToSdkLibraryAndImport - // The reference to the xml permissions module created by the source module. - // Is nil if the source module does not exist. - xmlPermissionsFileModule *sdkLibraryXml - // Build path to the dex implementation jar obtained from the prebuilt_apex, if any. dexJarFile OptionalDexJarPath dexJarFileErr error @@ -2059,9 +2136,16 @@ func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) var _ android.ApexModule = (*SdkLibraryImport)(nil) // Implements android.ApexModule -func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool { - depTag := mctx.OtherModuleDependencyTag(dep) - if depTag == xmlPermissionsFileTag { +func (m *SdkLibraryImport) GetDepInSameApexChecker() android.DepInSameApexChecker { + return SdkLibraryImportDepIsInSameApexChecker{} +} + +type SdkLibraryImportDepIsInSameApexChecker struct { + android.BaseDepInSameApexChecker +} + +func (m SdkLibraryImportDepIsInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool { + if tag == xmlPermissionsFileTag { return true } @@ -2071,13 +2155,10 @@ func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, } // Implements android.ApexModule -func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { - // we don't check prebuilt modules for sdk_version - return nil +func (m *SdkLibraryImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } -// Implements android.ApexModule func (module *SdkLibraryImport) UniqueApexVariations() bool { return module.uniqueApexVariations() } @@ -2094,7 +2175,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar") // Record the paths to the prebuilt stubs library and stubs source. - ctx.VisitDirectDeps(func(to android.Module) { + ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) { tag := ctx.OtherModuleDependencyTag(to) // Extract information from any of the scope specific dependencies. @@ -2106,17 +2187,11 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo // is determined by the nature of the dependency which is determined by the tag. scopeTag.extractDepInfo(ctx, to, scopePaths) } else if tag == implLibraryTag { - if implLibrary, ok := to.(*Library); ok { - module.implLibraryModule = implLibrary + if implInfo, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok { + module.implLibraryInfo = implInfo } else { ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to) } - } else if tag == xmlPermissionsFileTag { - if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok { - module.xmlPermissionsFileModule = xmlPermissionsFileModule - } else { - ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to) - } } }) sdkLibInfo := module.generateCommonBuildActions(ctx) @@ -2156,9 +2231,9 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo } module.setOutputFiles(ctx) - if module.implLibraryModule != nil { + if module.implLibraryInfo != nil { generatingLibs = append(generatingLibs, module.implLibraryModuleName()) - setOutputFiles(ctx, module.implLibraryModule.Module) + setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo) } sdkLibInfo.GeneratingLibs = generatingLibs @@ -2177,10 +2252,10 @@ func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) if module.dexJarFile.IsSet() { return module.dexJarFile } - if module.implLibraryModule == nil { + if module.implLibraryInfo == nil { return makeUnsetDexJarPath() } else { - return module.implLibraryModule.DexJarBuildPath(ctx) + return module.implLibraryInfo.DexJarFile } } @@ -2196,10 +2271,10 @@ func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderConte // to satisfy apex.javaDependency interface func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path { - if module.implLibraryModule == nil { + if module.implLibraryInfo == nil { return nil } else { - return module.implLibraryModule.JacocoReportClassesFile() + return module.implLibraryInfo.JacocoReportClassesFile } } @@ -2212,19 +2287,19 @@ var _ ApexDependency = (*SdkLibraryImport)(nil) // to satisfy java.ApexDependency interface func (module *SdkLibraryImport) HeaderJars() android.Paths { - if module.implLibraryModule == nil { + if module.implLibraryInfo == nil { return nil } else { - return module.implLibraryModule.HeaderJars() + return module.implLibraryInfo.HeaderJars } } // to satisfy java.ApexDependency interface func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths { - if module.implLibraryModule == nil { + if module.implLibraryInfo == nil { return nil } else { - return module.implLibraryModule.ImplementationAndResourcesJars() + return module.implLibraryInfo.ImplementationAndResourcesJars } } @@ -2389,8 +2464,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk - implLibrary := sdk.implLibraryModule - if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided { + if sdk.implLibraryInfo != nil && sdk.implLibraryInfo.ProfileGuided { s.DexPreoptProfileGuided = proptools.BoolPtr(true) } } diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go index 768e57a11..578969223 100644 --- a/java/sdk_library_internal.go +++ b/java/sdk_library_internal.go @@ -15,12 +15,13 @@ package java import ( - "android/soong/android" - "android/soong/etc" "fmt" "path" "strings" + "android/soong/android" + "android/soong/etc" + "github.com/google/blueprint/proptools" ) @@ -173,6 +174,20 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) mctx.CreateModule(LibraryFactory, properties...) } +// getApiSurfaceForScope returns the api surface name to use for the apiScope. If one is specified +// in the corresponding ApiScopeProperties.Api_surface property that is used, otherwise the name of +// the apiScope is used. +func (module *SdkLibrary) getApiSurfaceForScope(apiScope *apiScope) *string { + scopeProperties := module.scopeToProperties[apiScope] + + apiSurface := scopeProperties.Api_surface + if apiSurface == nil { + apiSurface = &apiScope.name + } + + return apiSurface +} + // Creates the [Droidstubs] module with ".stubs.source.<[apiScope.name]>" that creates stubs // source files from the given full source files and also updates and checks the API // specification files (i.e. "*-current.txt", "*-removed.txt" files). @@ -226,7 +241,7 @@ func (module *SdkLibrary) createDroidstubs(mctx android.DefaultableHookContext, props.Srcs = append(props.Srcs, module.properties.Srcs...) props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...) props.Sdk_version = module.deviceProperties.Sdk_version - props.Api_surface = &apiScope.name + props.Api_surface = module.getApiSurfaceForScope(apiScope) props.System_modules = module.deviceProperties.System_modules props.Installable = proptools.BoolPtr(false) // A droiddoc module has only one Libs property and doesn't distinguish between @@ -778,7 +793,11 @@ var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil) // from android.ApexModule func (module *sdkLibraryXml) AvailableFor(what string) bool { - return true + return android.CheckAvailableForApex(what, module.ApexAvailableFor()) +} + +func (module *sdkLibraryXml) ApexAvailableFor() []string { + return []string{android.AvailableToPlatform, android.AvailableToAnyApex} } func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -788,10 +807,8 @@ func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { var _ android.ApexModule = (*sdkLibraryXml)(nil) // Implements android.ApexModule -func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { - // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked - return nil +func (m *sdkLibraryXml) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } // File path to the runtime implementation library diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 6031d7230..2cb827dc2 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -25,6 +25,7 @@ import ( ) func TestJavaSdkLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -114,19 +115,19 @@ func TestJavaSdkLibrary(t *testing.T) { `) // check the existence of the internal modules - foo := result.ModuleForTests("foo", "android_common") - result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common") - result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common") - result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common") - result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common") - result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common") - result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common") - result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "") - result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common") - result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common") - result.ModuleForTests("foo.api.public.28", "") - result.ModuleForTests("foo.api.system.28", "") - result.ModuleForTests("foo.api.test.28", "") + foo := result.ModuleForTests(t, "foo", "android_common") + result.ModuleForTests(t, apiScopePublic.stubsLibraryModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopeSystem.stubsLibraryModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopeTest.stubsLibraryModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopeSystem.stubsSourceModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopeTest.stubsSourceModuleName("foo"), "android_common") + result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "") + result.ModuleForTests(t, apiScopePublic.apiLibraryModuleName("foo"), "android_common") + result.ModuleForTests(t, "foo"+sdkXmlFileSuffix, "android_common") + result.ModuleForTests(t, "foo.api.public.28", "") + result.ModuleForTests(t, "foo.api.system.28", "") + result.ModuleForTests(t, "foo.api.test.28", "") exportedComponentsInfo, _ := android.OtherModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider) expectedFooExportedComponents := []string{ @@ -146,7 +147,7 @@ func TestJavaSdkLibrary(t *testing.T) { } android.AssertArrayString(t, "foo exported components", expectedFooExportedComponents, exportedComponentsInfo.Components) - bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac") + bazJavac := result.ModuleForTests(t, "baz", "android_common").Rule("javac") // tests if baz is actually linked to the stubs lib android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar") // ... and not to the impl lib @@ -154,20 +155,20 @@ func TestJavaSdkLibrary(t *testing.T) { // test if baz is not linked to the system variant of foo android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.jar") - bazTestJavac := result.ModuleForTests("baz-test", "android_common").Rule("javac") + bazTestJavac := result.ModuleForTests(t, "baz-test", "android_common").Rule("javac") // tests if baz-test is actually linked to the test stubs lib android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.jar") - baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac") + baz29Javac := result.ModuleForTests(t, "baz-29", "android_common").Rule("javac") // tests if baz-29 is actually linked to the system 29 stubs lib android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/sdk_system_29_foo/android_common/combined/sdk_system_29_foo.jar") - bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac") + bazModule30Javac := result.ModuleForTests(t, "baz-module-30", "android_common").Rule("javac") // tests if "baz-module-30" is actually linked to the module 30 stubs lib android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/sdk_module-lib_30_foo/android_common/combined/sdk_module-lib_30_foo.jar") // test if baz has exported SDK lib names foo and bar to qux - qux := result.ModuleForTests("qux", "android_common") + qux := result.ModuleForTests(t, "qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { requiredSdkLibs, optionalSdkLibs := quxLib.ClassLoaderContexts().UsesLibs() android.AssertDeepEquals(t, "qux exports (required)", []string{"fred", "quuz", "foo", "bar"}, requiredSdkLibs) @@ -175,18 +176,19 @@ func TestJavaSdkLibrary(t *testing.T) { } // test if quuz have created the api_contribution module - result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "") + result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "") - fooImplDexJar := result.ModuleForTests("foo.impl", "android_common").Rule("d8") + fooImplDexJar := result.ModuleForTests(t, "foo.impl", "android_common").Rule("d8") // tests if kotlinc generated files are NOT excluded from output of foo.impl. android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") - barImplDexJar := result.ModuleForTests("bar.impl", "android_common").Rule("d8") + barImplDexJar := result.ModuleForTests(t, "bar.impl", "android_common").Rule("d8") // tests if kotlinc generated files are excluded from output of bar.impl. android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") } func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -218,7 +220,7 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { `) // test that updatability attributes are passed on correctly - fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Output("fooUpdatable.xml") + fooUpdatable := result.ModuleForTests(t, "fooUpdatable.xml", "android_common").Output("fooUpdatable.xml") fooUpdatableContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooUpdatable) android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `on-bootclasspath-since="U"`) android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `on-bootclasspath-before="V"`) @@ -227,7 +229,7 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { // double check that updatability attributes are not written if they don't exist in the bp file // the permissions file for the foo library defined above - fooPermissions := result.ModuleForTests("foo.xml", "android_common").Output("foo.xml") + fooPermissions := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml") fooPermissionsContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooPermissions) android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `on-bootclasspath-since`) android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `on-bootclasspath-before`) @@ -236,6 +238,7 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) { } func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -263,6 +266,7 @@ func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) { } func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -292,6 +296,7 @@ func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes(t *testin } func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -319,6 +324,7 @@ func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk(t *testin } func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleMinSdk(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -347,6 +353,7 @@ func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleM } func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -363,13 +370,14 @@ func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) { } `) // test that updatability attributes are passed on correctly - fooUpdatable := result.ModuleForTests("foo.xml", "android_common").Output("foo.xml") + fooUpdatable := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml") fooUpdatableContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooUpdatable) android.AssertStringDoesContain(t, "foo.xml contents", fooUpdatableContents, `<apex-library`) android.AssertStringDoesNotContain(t, "foo.xml contents", fooUpdatableContents, `<library`) } func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -409,11 +417,11 @@ func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) { {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"] + sdklibCp := result.ModuleForTests(t, 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() + combineJarInputs := result.ModuleForTests(t, 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) } @@ -426,6 +434,7 @@ func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) { } func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -448,13 +457,14 @@ func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { `) // The bar library should depend on the stubs jar. - barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac") + barLibrary := result.ModuleForTests(t, "bar", "android_common").Rule("javac") if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { t.Errorf("expected %q, found %#q", expected, actual) } } func TestJavaSdkLibrary_AccessOutputFiles(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -478,6 +488,7 @@ func TestJavaSdkLibrary_AccessOutputFiles(t *testing.T) { } func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -503,6 +514,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) { } func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -527,6 +539,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) { } func TestJavaSdkLibrary_Deps(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -557,6 +570,7 @@ func TestJavaSdkLibrary_Deps(t *testing.T) { } func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { + t.Parallel() prepareForJavaTest.RunTestWithBp(t, ` java_sdk_library_import { name: "foo", @@ -582,6 +596,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { } func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { + t.Parallel() bp := ` java_sdk_library_import { name: "foo", @@ -592,6 +607,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { ` t.Run("stubs.source", func(t *testing.T) { + t.Parallel() prepareForJavaTest. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.stubs.source"`)). RunTestWithBp(t, bp+` @@ -607,6 +623,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { }) t.Run("api.txt", func(t *testing.T) { + t.Parallel() prepareForJavaTest. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.api.txt"`)). RunTestWithBp(t, bp+` @@ -621,6 +638,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { }) t.Run("removed-api.txt", func(t *testing.T) { + t.Parallel() prepareForJavaTest. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.removed-api.txt"`)). RunTestWithBp(t, bp+` @@ -636,6 +654,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) { } func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { + t.Parallel() prepareForJavaTest. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": enabled api scope "system" depends on disabled scope "public"`)). RunTestWithBp(t, ` @@ -656,6 +675,7 @@ func TestJavaSdkLibrary_InvalidScopes(t *testing.T) { } func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -674,6 +694,7 @@ func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) { } func TestJavaSdkLibrary_ModuleLib(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -694,6 +715,7 @@ func TestJavaSdkLibrary_ModuleLib(t *testing.T) { } func TestJavaSdkLibrary_SystemServer(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -714,6 +736,7 @@ func TestJavaSdkLibrary_SystemServer(t *testing.T) { } func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -774,7 +797,7 @@ func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) { // The bar library should depend on the highest (where system server is highest and public is // lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the // foo-<x> module is <x>. - barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac") + barLibrary := result.ModuleForTests(t, "bar", "android_common").Rule("javac") stubLibraries := []string{ stubsPath("foo-public", apiScopePublic), stubsPath("foo-system", apiScopeSystem), @@ -788,6 +811,7 @@ func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) { } func TestJavaSdkLibraryImport(t *testing.T) { + t.Parallel() result := prepareForJavaTest.RunTestWithBp(t, ` java_library { name: "foo", @@ -826,10 +850,10 @@ func TestJavaSdkLibraryImport(t *testing.T) { `) for _, scope := range []string{"", ".system", ".test"} { - fooModule := result.ModuleForTests("foo"+scope, "android_common") + fooModule := result.ModuleForTests(t, "foo"+scope, "android_common") javac := fooModule.Rule("javac") - sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Output("combined/sdklib.stubs" + scope + ".jar").Output + sdklibStubsJar := result.ModuleForTests(t, "sdklib.stubs"+scope, "android_common").Output("combined/sdklib.stubs" + scope + ".jar").Output android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String()) } @@ -844,6 +868,7 @@ func TestJavaSdkLibraryImport(t *testing.T) { } func TestJavaSdkLibraryImport_WithSource(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -968,15 +993,13 @@ func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer an CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{ // Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib. `prebuilt_sdklib`, - `prebuilt_sdklib`, - `prebuilt_sdklib`, `prebuilt_sdklib.stubs`, `prebuilt_sdklib.stubs.source`, }) // Make sure that dependencies on sdklib that resolve to one of the child libraries use the // prebuilt library. - public := result.ModuleForTests("public", "android_common") + public := result.ModuleForTests(t, "public", "android_common") rule := public.Output("javac/public.jar") inputs := rule.Implicits.Strings() expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar" @@ -986,7 +1009,9 @@ func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer an } func TestJavaSdkLibraryImport_Preferred(t *testing.T) { + t.Parallel() t.Run("prefer", func(t *testing.T) { + t.Parallel() testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer) }) } @@ -994,6 +1019,7 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { // If a module is listed in `mainline_module_contributions, it should be used // It will supersede any other source vs prebuilt selection mechanism like `prefer` attribute func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) { + t.Parallel() bp := ` apex_contributions { name: "my_mainline_module_contributions", @@ -1093,7 +1119,7 @@ func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) { ).RunTestWithBp(t, bp) // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions - public := result.ModuleForTests("public", "android_common") + public := result.ModuleForTests(t, "public", "android_common") rule := public.Output("javac/public.jar") inputs := rule.Implicits.Strings() expectedInputs := []string{ @@ -1113,6 +1139,7 @@ func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) { } func TestJavaSdkLibraryDist(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( PrepareForTestWithJavaBuildComponents, PrepareForTestWithJavaDefaultModules, @@ -1179,7 +1206,8 @@ func TestJavaSdkLibraryDist(t *testing.T) { for _, tt := range testCases { t.Run(tt.module, func(t *testing.T) { - m := result.ModuleForTests(apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library) + t.Parallel() + m := result.ModuleForTests(t, apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library) dists := m.Dists() if len(dists) != 1 { t.Fatalf("expected exactly 1 dist entry, got %d", len(dists)) @@ -1195,6 +1223,7 @@ func TestJavaSdkLibraryDist(t *testing.T) { } func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) { + t.Parallel() preparer := android.GroupFixturePreparers( PrepareForTestWithJavaBuildComponents, PrepareForTestWithJavaDefaultModules, @@ -1279,6 +1308,7 @@ func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) { } func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1300,12 +1330,13 @@ func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) { `) // The foo.stubs.source should depend on bar-lib - fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs) + fooStubsSources := result.ModuleForTests(t, "foo.stubs.source", "android_common").Module().(*Droidstubs) eval := fooStubsSources.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs.GetOrDefault(eval, nil), "bar-lib") } func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1327,12 +1358,13 @@ func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs(t *testing.T) { `) // The foo.stubs.source should depend on bar-lib - fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs) + fooStubsSources := result.ModuleForTests(t, "foo.stubs.source", "android_common").Module().(*Droidstubs) eval := fooStubsSources.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs.GetOrDefault(eval, nil), "bar-lib") } func TestJavaSdkLibrary_ApiLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1377,12 +1409,13 @@ func TestJavaSdkLibrary_ApiLibrary(t *testing.T) { } for _, c := range testCases { - m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary) + m := result.ModuleForTests(t, c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary) android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions) } } func TestStaticDepStubLibrariesVisibility(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1412,6 +1445,7 @@ func TestStaticDepStubLibrariesVisibility(t *testing.T) { } func TestSdkLibraryDependency(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1438,12 +1472,13 @@ func TestSdkLibraryDependency(t *testing.T) { } `) - barPermissions := result.ModuleForTests("bar.xml", "android_common").Output("bar.xml") + barPermissions := result.ModuleForTests(t, "bar.xml", "android_common").Output("bar.xml") barContents := android.ContentFromFileRuleForTests(t, result.TestContext, barPermissions) android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barContents, `dependency="foo"`) } func TestSdkLibraryExportableStubsLibrary(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1480,8 +1515,8 @@ func TestSdkLibraryExportableStubsLibrary(t *testing.T) { exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo") // Check modules generation - result.ModuleForTests(exportableStubsLibraryModuleName, "android_common") - result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common") + result.ModuleForTests(t, exportableStubsLibraryModuleName, "android_common") + result.ModuleForTests(t, exportableSourceStubsLibraryModuleName, "android_common") // Check static lib dependency android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+ @@ -1494,6 +1529,7 @@ func TestSdkLibraryExportableStubsLibrary(t *testing.T) { // For java libraries depending on java_sdk_library(_import) via libs, assert that // rdep gets stubs of source if source is listed in apex_contributions and prebuilt has prefer (legacy mechanism) func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) { + t.Parallel() bp := ` apex_contributions { name: "my_mainline_module_contributions", @@ -1539,7 +1575,7 @@ func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) { result := fixture.RunTestWithBp(t, bp) // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions - public := result.ModuleForTests("mymodule", "android_common") + public := result.ModuleForTests(t, "mymodule", "android_common") rule := public.Output("javac/mymodule.jar") inputs := rule.Implicits.Strings() android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar") @@ -1547,6 +1583,7 @@ func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) { // test that rdep gets resolved to the correct version of a java_sdk_library (source or a specific prebuilt) func TestMultipleSdkLibraryPrebuilts(t *testing.T) { + t.Parallel() bp := ` apex_contributions { name: "my_mainline_module_contributions", @@ -1624,7 +1661,7 @@ func TestMultipleSdkLibraryPrebuilts(t *testing.T) { result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName)) // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions - public := result.ModuleForTests("mymodule", "android_common") + public := result.ModuleForTests(t, "mymodule", "android_common") rule := public.Output("javac/mymodule.jar") inputs := rule.Implicits.Strings() android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, tc.expectedStubPath) @@ -1632,6 +1669,7 @@ func TestMultipleSdkLibraryPrebuilts(t *testing.T) { } func TestStubLinkType(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1668,6 +1706,7 @@ func TestStubLinkType(t *testing.T) { } func TestSdkLibDirectDependency(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -1732,6 +1771,7 @@ func TestSdkLibDirectDependency(t *testing.T) { } func TestSdkLibDirectDependencyWithPrebuiltSdk(t *testing.T) { + t.Parallel() android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, diff --git a/java/sdk_test.go b/java/sdk_test.go index 9bfe6a2b5..49983ada2 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -53,6 +53,7 @@ type classpathTestCase struct { } func TestClasspath(t *testing.T) { + t.Parallel() const frameworkAidl = "-I" + defaultJavaDir + "/framework/aidl" var classpathTestcases = []classpathTestCase{ { @@ -388,17 +389,18 @@ func TestClasspath(t *testing.T) { }, } - t.Parallel() t.Run("basic", func(t *testing.T) { t.Parallel() testClasspathTestCases(t, classpathTestcases, false, false) }) t.Run("Always_use_prebuilt_sdks=true", func(t *testing.T) { + t.Parallel() testClasspathTestCases(t, classpathTestcases, true, false) }) t.Run("UseTransitiveJarsInClasspath", func(t *testing.T) { + t.Parallel() testClasspathTestCases(t, classpathTestcases, false, true) }) } @@ -499,7 +501,7 @@ func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase } checkClasspath := func(t *testing.T, result *android.TestResult, isJava8 bool) { - foo := result.ModuleForTests("foo", variant(result)) + foo := result.ModuleForTests(t, "foo", variant(result)) javac := foo.Rule("javac") var deps []string @@ -571,12 +573,13 @@ func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase // Test with legacy javac -source 1.8 -target 1.8 t.Run("Java language level 8", func(t *testing.T) { + t.Parallel() result := fixtureFactory.RunTestWithBp(t, bpJava8) checkClasspath(t, result, true /* isJava8 */) if testcase.host != android.Host { - aidl := result.ModuleForTests("foo", variant(result)).Rule("aidl") + aidl := result.ModuleForTests(t, "foo", variant(result)).Rule("aidl") android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.") } @@ -584,12 +587,13 @@ func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase // Test with default javac -source 9 -target 9 t.Run("Java language level 9", func(t *testing.T) { + t.Parallel() result := fixtureFactory.RunTestWithBp(t, bp) checkClasspath(t, result, false /* isJava8 */) if testcase.host != android.Host { - aidl := result.ModuleForTests("foo", variant(result)).Rule("aidl") + aidl := result.ModuleForTests(t, "foo", variant(result)).Rule("aidl") android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.") } @@ -602,6 +606,7 @@ func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase // Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8 t.Run("REL + Java language level 8", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8) @@ -610,6 +615,7 @@ func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase // Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9 t.Run("REL + Java language level 9", func(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bp) diff --git a/java/sdk_version_test.go b/java/sdk_version_test.go index 88351d2ef..03d55f70a 100644 --- a/java/sdk_version_test.go +++ b/java/sdk_version_test.go @@ -25,6 +25,7 @@ func stringPtr(v string) *string { } func TestSystemSdkFromVendor(t *testing.T) { + t.Parallel() fixtures := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -57,7 +58,7 @@ func TestSystemSdkFromVendor(t *testing.T) { vendor: true, sdk_version: "system_current", }`) - fooModule := result.ModuleForTests("foo", "android_common") + fooModule := result.ModuleForTests(t, "foo", "android_common") fooClasspath := fooModule.Rule("javac").Args["classpath"] android.AssertStringDoesContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/34/system/android.jar") diff --git a/java/system_modules_test.go b/java/system_modules_test.go index b05b0e497..99301bc52 100644 --- a/java/system_modules_test.go +++ b/java/system_modules_test.go @@ -51,10 +51,11 @@ var addSourceSystemModules = android.FixtureAddTextFile("source/Android.bp", ` `) func TestJavaSystemModules(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers(prepareForJavaTest, addSourceSystemModules).RunTest(t) // check the existence of the source module - sourceSystemModules := result.ModuleForTests("system-modules", "android_common") + sourceSystemModules := result.ModuleForTests(t, "system-modules", "android_common") sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs // The expected paths are the header jars from the source input modules. @@ -78,10 +79,11 @@ var addPrebuiltSystemModules = android.FixtureAddTextFile("prebuilts/Android.bp" `) func TestJavaSystemModulesImport(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers(prepareForJavaTest, addPrebuiltSystemModules).RunTest(t) // check the existence of the renamed prebuilt module - prebuiltSystemModules := result.ModuleForTests("system-modules", "android_common") + prebuiltSystemModules := result.ModuleForTests(t, "system-modules", "android_common") prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs // The expected paths are the header jars from the renamed prebuilt input modules. @@ -90,6 +92,7 @@ func TestJavaSystemModulesImport(t *testing.T) { } func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForJavaTest, addSourceSystemModules, @@ -97,7 +100,7 @@ func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) { ).RunTest(t) // check the existence of the source module - sourceSystemModules := result.ModuleForTests("system-modules", "android_common") + sourceSystemModules := result.ModuleForTests(t, "system-modules", "android_common") sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs // The expected paths are the header jars from the source input modules. @@ -105,7 +108,7 @@ func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) { android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, sourceInputs.RelativeToTop().Strings()) // check the existence of the renamed prebuilt module - prebuiltSystemModules := result.ModuleForTests("prebuilt_system-modules", "android_common") + prebuiltSystemModules := result.ModuleForTests(t, "prebuilt_system-modules", "android_common") prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs // The expected paths are the header jars from the renamed prebuilt input modules. @@ -114,6 +117,7 @@ func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) { } func TestMultipleSystemModulesPrebuilts(t *testing.T) { + t.Parallel() bp := ` // an rdep java_library { diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index 3176ad94c..a60f6b82c 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -58,6 +58,10 @@ func platformSystemServerClasspathFactory() android.Module { return m } +func (m *platformSystemServerClasspathModule) UniqueApexVariations() bool { + return true +} + func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) { return p.classpathFragmentBase().androidMkEntries() } @@ -91,8 +95,10 @@ type SystemServerClasspathModule struct { properties systemServerClasspathFragmentProperties } -func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { - return nil +var _ android.ApexModule = (*SystemServerClasspathModule)(nil) + +func (m *SystemServerClasspathModule) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel { + return android.MinApiLevel } type systemServerClasspathFragmentProperties struct { @@ -116,6 +122,10 @@ func systemServerClasspathFactory() android.Module { return m } +func (m *SystemServerClasspathModule) UniqueApexVariations() bool { + return true +} + func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(s.properties.Contents.GetOrDefault(ctx, nil)) == 0 && len(s.properties.Standalone_contents.GetOrDefault(ctx, nil)) == 0 { ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty") diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go index ba328e7b1..704f5a4f4 100644 --- a/java/systemserver_classpath_fragment_test.go +++ b/java/systemserver_classpath_fragment_test.go @@ -25,6 +25,7 @@ var prepareForTestWithSystemServerClasspath = android.GroupFixturePreparers( ) func TestPlatformSystemServerClasspathVariant(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithSystemServerClasspath, android.FixtureWithRootAndroidBp(` @@ -39,6 +40,7 @@ func TestPlatformSystemServerClasspathVariant(t *testing.T) { } func TestPlatformSystemServerClasspath_ClasspathFragmentPaths(t *testing.T) { + t.Parallel() result := android.GroupFixturePreparers( prepareForTestWithSystemServerClasspath, android.FixtureWithRootAndroidBp(` @@ -50,10 +52,11 @@ func TestPlatformSystemServerClasspath_ClasspathFragmentPaths(t *testing.T) { p := result.Module("platform-systemserverclasspath", "android_common").(*platformSystemServerClasspathModule) android.AssertStringEquals(t, "output filepath", "systemserverclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base()) - android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install filepath", "out/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) } func TestPlatformSystemServerClasspathModule_AndroidMkEntries(t *testing.T) { + t.Parallel() preparer := android.GroupFixturePreparers( prepareForTestWithSystemServerClasspath, android.FixtureWithRootAndroidBp(` @@ -97,6 +100,7 @@ func TestPlatformSystemServerClasspathModule_AndroidMkEntries(t *testing.T) { } func TestSystemServerClasspathFragmentWithoutContents(t *testing.T) { + t.Parallel() prepareForTestWithSystemServerClasspath. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( `\QEither contents or standalone_contents needs to be non-empty\E`)). diff --git a/java/testing.go b/java/testing.go index 0ea4e6408..35319ae58 100644 --- a/java/testing.go +++ b/java/testing.go @@ -18,7 +18,6 @@ import ( "fmt" "reflect" "regexp" - "sort" "strings" "testing" @@ -378,7 +377,6 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterAppBuildComponents(ctx) RegisterAppImportBuildComponents(ctx) RegisterAppSetBuildComponents(ctx) - registerBootclasspathBuildComponents(ctx) registerBootclasspathFragmentBuildComponents(ctx) RegisterDexpreoptBootJarsComponents(ctx) RegisterDocsBuildComponents(ctx) @@ -607,19 +605,18 @@ func gatherRequiredDepsForTest() string { func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string { t.Helper() - module := ctx.ModuleForTests(name, variant).Module() + module := ctx.ModuleForTests(t, name, variant).Module() deps := []string{} ctx.VisitDirectDeps(module, func(m blueprint.Module) { deps = append(deps, m.Name()) }) - sort.Strings(deps) - - return deps + return android.SortedUniqueStrings(deps) } // CheckModuleDependencies checks if the expected dependencies of the module are // identical to the actual dependencies. func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { + t.Helper() deps := getModuleDependencies(t, ctx, name, variant) if actual := deps; !reflect.DeepEqual(expected, actual) { @@ -639,7 +636,7 @@ func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, vari // CheckModuleHasDependency returns true if the module depends on the expected dependency. func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, name, variant string, desiredTag blueprint.DependencyTag, expected string) bool { - module := ctx.ModuleForTests(name, variant).Module() + module := ctx.ModuleForTests(t, name, variant).Module() found := false ctx.VisitDirectDepsWithTags(module, func(m blueprint.Module, tag blueprint.DependencyTag) { if tag == desiredTag && m.Name() == expected { @@ -654,7 +651,7 @@ func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, nam func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) { t.Helper() platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) - pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules) + pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex) android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs) } @@ -669,23 +666,54 @@ func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *androi android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir) } -// ApexNamePairsFromModules returns the apex:module pair for the supplied modules. -func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string { +// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list. +// +// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the +// name of the apex, or platform is it is not part of an apex and <module> is the module name. +func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { + t.Helper() + platformBootclasspath := ctx.ModuleForTests(t, name, variant).Module().(*platformBootclasspathModule) + modules := []android.Module{} + ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) { + modules = append(modules, m.(android.Module)) + }) + + pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex) + android.AssertDeepEquals(t, "module dependencies", expected, pairs) +} + +// apexNamePairsFromModules returns the apex:module pair for the supplied modules. +func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string { pairs := []string{} for _, module := range modules { - pairs = append(pairs, apexNamePairFromModule(ctx, module)) + pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex)) + } + return pairs +} + +// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments. +func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string { + pairs := []string{} + for _, fragment := range fragments { + found := false + for apex, apexFragment := range apexNameToFragment { + if apexFragment == fragment { + pairs = append(pairs, apex+":"+ctx.ModuleName(fragment)) + found = true + } + } + if !found { + pairs = append(pairs, "platform:"+ctx.ModuleName(fragment)) + } } return pairs } -func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string { +func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string { name := module.Name() - var apex string - apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider) - if apexInfo.IsForPlatform() { + apex := modulesToApex[module] + if apex == "" { apex = "platform" - } else { - apex = apexInfo.InApexVariants[0] } return fmt.Sprintf("%s:%s", apex, name) @@ -696,7 +724,7 @@ func apexNamePairFromModule(ctx *android.TestContext, module android.Module) str func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) { t.Helper() platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) - pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments) + pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment) android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs) } @@ -719,7 +747,7 @@ func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hid // Check that the merged file create by platform_compat_config_singleton has the correct inputs. func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) { - sourceGlobalCompatConfig := result.SingletonForTests("platform_compat_config_singleton") + sourceGlobalCompatConfig := result.SingletonForTests(t, "platform_compat_config_singleton") allOutputs := sourceGlobalCompatConfig.AllOutputs() android.AssertIntEquals(t, message+": output len", 1, len(allOutputs)) output := sourceGlobalCompatConfig.Output(allOutputs[0]) |