diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/Android.bp | 2 | ||||
-rw-r--r-- | java/aapt2.go | 28 | ||||
-rw-r--r-- | java/aar.go | 11 | ||||
-rw-r--r-- | java/androidmk.go | 5 | ||||
-rwxr-xr-x | java/app.go | 80 | ||||
-rw-r--r-- | java/base.go | 4 | ||||
-rw-r--r-- | java/bootclasspath_fragment.go | 11 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 3 | ||||
-rw-r--r-- | java/dexpreopt_check.go | 2 | ||||
-rw-r--r-- | java/java.go | 10 | ||||
-rw-r--r-- | java/jdeps.go | 2 | ||||
-rw-r--r-- | java/resourceshrinker.go | 3 | ||||
-rw-r--r-- | java/robolectric.go | 4 | ||||
-rw-r--r-- | java/sdk_library.go | 11 | ||||
-rw-r--r-- | java/sdk_library_test.go | 131 | ||||
-rw-r--r-- | java/systemserver_classpath_fragment.go | 7 | ||||
-rw-r--r-- | java/test_spec_test.go | 133 | ||||
-rw-r--r-- | java/tradefed.go | 4 |
18 files changed, 411 insertions, 40 deletions
diff --git a/java/Android.bp b/java/Android.bp index 4450c4275..cf968713c 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -15,6 +15,7 @@ bootstrap_go_package { "soong-dexpreopt", "soong-genrule", "soong-java-config", + "soong-testing", "soong-provenance", "soong-python", "soong-remoteexec", @@ -112,6 +113,7 @@ bootstrap_go_package { "sdk_library_test.go", "system_modules_test.go", "systemserver_classpath_fragment_test.go", + "test_spec_test.go", ], pluginFor: ["soong_build"], } diff --git a/java/aapt2.go b/java/aapt2.go index 3bb70b53f..17ee6ee42 100644 --- a/java/aapt2.go +++ b/java/aapt2.go @@ -25,17 +25,23 @@ import ( "android/soong/android" ) +func isPathValueResource(res android.Path) bool { + subDir := filepath.Dir(res.String()) + subDir, lastDir := filepath.Split(subDir) + return strings.HasPrefix(lastDir, "values") +} + // Convert input resource file path to output file path. // values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat; // For other resource file, just replace the last "/" with "_" and add .flat extension. func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath { name := res.Base() - subDir := filepath.Dir(res.String()) - subDir, lastDir := filepath.Split(subDir) - if strings.HasPrefix(lastDir, "values") { + if isPathValueResource(res) { name = strings.TrimSuffix(name, ".xml") + ".arsc" } + subDir := filepath.Dir(res.String()) + subDir, lastDir := filepath.Split(subDir) name = lastDir + "_" + name + ".flat" return android.PathForModuleOut(ctx, "aapt2", subDir, name) } @@ -63,7 +69,21 @@ var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile", // aapt2Compile compiles resources and puts the results in the requested directory. func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths, - flags []string) android.WritablePaths { + flags []string, productToFilter string) android.WritablePaths { + if productToFilter != "" && productToFilter != "default" { + // --filter-product leaves only product-specific resources. Product-specific resources only exist + // in value resources (values/*.xml), so filter value resource files only. Ignore other types of + // resources as they don't need to be in product characteristics RRO (and they will cause aapt2 + // compile errors) + filteredPaths := android.Paths{} + for _, path := range paths { + if isPathValueResource(path) { + filteredPaths = append(filteredPaths, path) + } + } + paths = filteredPaths + flags = append([]string{"--filter-product " + productToFilter}, flags...) + } // Shard the input paths so that they can be processed in parallel. If we shard them into too // small chunks, the additional cost of spinning up aapt2 outweighs the performance gain. The diff --git a/java/aar.go b/java/aar.go index 6b8912912..e579008e1 100644 --- a/java/aar.go +++ b/java/aar.go @@ -102,6 +102,9 @@ type aaptProperties struct { // true if RRO is enforced for any of the dependent modules RROEnforcedForDependent bool `blueprint:"mutated"` + + // Filter only specified product and ignore other products + Filter_product *string `blueprint:"mutated"` } type aapt struct { @@ -162,6 +165,10 @@ func (a *aapt) useResourceProcessorBusyBox() bool { return BoolDefault(a.aaptProperties.Use_resource_processor, false) } +func (a *aapt) filterProduct() string { + return String(a.aaptProperties.Filter_product) +} + func (a *aapt) ExportPackage() android.Path { return a.exportPackage } @@ -432,7 +439,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio var compiledResDirs []android.Paths for _, dir := range resDirs { a.resourceFiles = append(a.resourceFiles, dir.files...) - compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()) + compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags, a.filterProduct()).Paths()) } for i, zip := range resZips { @@ -491,7 +498,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio } for _, dir := range overlayDirs { - compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...) + compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags, a.filterProduct()).Paths()...) } var splitPackages android.WritablePaths diff --git a/java/androidmk.go b/java/androidmk.go index 97b303dfb..84f78c89b 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -343,10 +343,15 @@ 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, ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { // App module names can be overridden. diff --git a/java/app.go b/java/app.go index 7b9e6bb14..6d7411d47 100755 --- a/java/app.go +++ b/java/app.go @@ -22,6 +22,7 @@ import ( "path/filepath" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -130,6 +131,16 @@ type appProperties struct { // Specifies the file that contains the allowlist for this app. Privapp_allowlist *string `android:"path"` + + // If set, create an RRO package which contains only resources having PRODUCT_CHARACTERISTICS + // and install the RRO package to /product partition, instead of passing --product argument + // to aapt2. Default is false. + // Setting this will make this APK identical to all targets, regardless of + // PRODUCT_CHARACTERISTICS. + Generate_product_characteristics_rro *bool + + ProductCharacteristicsRROPackageName *string `blueprint:"mutated"` + ProductCharacteristicsRROManifestModuleName *string `blueprint:"mutated"` } // android_app properties that can be overridden by override_android_app @@ -454,8 +465,9 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { aaptLinkFlags := []string{} // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided. + autogenerateRRO := proptools.Bool(a.appProperties.Generate_product_characteristics_rro) hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product") - if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { + if !autogenerateRRO && !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 { aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics()) } @@ -857,7 +869,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path()) } - var extraInstalledPaths android.Paths + var extraInstalledPaths android.InstallPaths for _, extra := range a.extraOutputFiles { installed := ctx.InstallFile(a.installDir, extra.Base(), extra) extraInstalledPaths = append(extraInstalledPaths, installed) @@ -1056,6 +1068,8 @@ func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) { } case ".export-package.apk": return []android.Path{a.exportPackage}, nil + case ".manifest.xml": + return []android.Path{a.aapt.manifestPath}, nil } return a.Library.OutputFiles(tag) } @@ -1085,6 +1099,14 @@ func (a *AndroidApp) IDEInfo(dpInfo *android.IdeInfo) { a.aapt.IDEInfo(dpInfo) } +func (a *AndroidApp) productCharacteristicsRROPackageName() string { + return proptools.String(a.appProperties.ProductCharacteristicsRROPackageName) +} + +func (a *AndroidApp) productCharacteristicsRROManifestModuleName() string { + return proptools.String(a.appProperties.ProductCharacteristicsRROManifestModuleName) +} + // android_app compiles sources and Android resources into an Android application package `.apk` file. func AndroidAppFactory() android.Module { module := &AndroidApp{} @@ -1111,6 +1133,57 @@ func AndroidAppFactory() android.Module { android.InitApexModule(module) android.InitBazelModule(module) + android.AddLoadHook(module, func(ctx android.LoadHookContext) { + a := ctx.Module().(*AndroidApp) + + characteristics := ctx.Config().ProductAAPTCharacteristics() + if characteristics == "default" || characteristics == "" { + module.appProperties.Generate_product_characteristics_rro = nil + // no need to create RRO + return + } + + if !proptools.Bool(module.appProperties.Generate_product_characteristics_rro) { + return + } + + rroPackageName := a.Name() + "__" + strings.ReplaceAll(characteristics, ",", "_") + "__auto_generated_characteristics_rro" + rroManifestName := rroPackageName + "_manifest" + + a.appProperties.ProductCharacteristicsRROPackageName = proptools.StringPtr(rroPackageName) + a.appProperties.ProductCharacteristicsRROManifestModuleName = proptools.StringPtr(rroManifestName) + + rroManifestProperties := struct { + Name *string + Tools []string + Out []string + Srcs []string + Cmd *string + }{ + Name: proptools.StringPtr(rroManifestName), + Tools: []string{"characteristics_rro_generator"}, + Out: []string{"AndroidManifest.xml"}, + Srcs: []string{":" + a.Name() + "{.manifest.xml}"}, + Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $(in) $(out)"), + } + ctx.CreateModule(genrule.GenRuleFactory, &rroManifestProperties) + + rroProperties := struct { + Name *string + Filter_product *string + Aaptflags []string + Manifest *string + Resource_dirs []string + }{ + Name: proptools.StringPtr(rroPackageName), + Filter_product: proptools.StringPtr(characteristics), + Aaptflags: []string{"--auto-add-overlay"}, + Manifest: proptools.StringPtr(":" + rroManifestName), + Resource_dirs: a.aaptProperties.Resource_dirs, + } + ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties) + }) + return module } @@ -1193,6 +1266,7 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.testConfig = a.FixTestConfig(ctx, testConfig) a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path { @@ -1584,7 +1658,7 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to // various unrelated reasons, such as a failure to get manifest from an APK). global := dexpreopt.GetGlobalConfig(ctx) - if global.DisablePreopt || global.OnlyPreoptBootImageAndSystemServer { + if global.DisablePreopt || global.OnlyPreoptArtBootImage { return inputFile } diff --git a/java/base.go b/java/base.go index 3d7d3de01..fdc164e11 100644 --- a/java/base.go +++ b/java/base.go @@ -497,9 +497,6 @@ type Module struct { // list of the xref extraction files kytheFiles android.Paths - // Collect the module directory for IDE info in java/jdeps.go. - modulePaths []string - hideApexVariantFromMake bool sdkVersion android.SdkSpec @@ -2015,7 +2012,6 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { if j.expandJarjarRules != nil { dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) } - dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...) dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...) dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...) dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 7d8a9f7bb..191a65ec1 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -23,6 +23,7 @@ import ( "android/soong/android" "android/soong/dexpreopt" + "android/soong/testing" "github.com/google/blueprint/proptools" @@ -238,9 +239,6 @@ type BootclasspathFragmentModule struct { sourceOnlyProperties SourceOnlyBootclasspathProperties - // Collect the module directory for IDE info in java/jdeps.go. - modulePaths []string - // Path to the boot image profile. profilePath android.WritablePath } @@ -471,9 +469,6 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Generate classpaths.proto config b.generateClasspathProtoBuildActions(ctx) - // Collect the module directory for IDE info in java/jdeps.go. - b.modulePaths = append(b.modulePaths, ctx.ModuleDir()) - // Gather the bootclasspath fragment's contents. var contents []android.Module ctx.VisitDirectDeps(func(module android.Module) { @@ -505,6 +500,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo if ctx.Module() != ctx.FinalModule() { b.HideFromMake() } + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } // getProfileProviderApex returns the name of the apex that provides a boot image profile, or an @@ -582,7 +578,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. // TODO(b/202896428): Add better way to handle this. _, unknown = android.RemoveFromList("android.car-module", unknown) - if len(unknown) > 0 { + if isActiveModule(ctx.Module()) && len(unknown) > 0 { ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) } } @@ -801,7 +797,6 @@ func (b *BootclasspathFragmentModule) getProfilePath() android.Path { // Collect information for opening IDE project files in java/jdeps.go. func (b *BootclasspathFragmentModule) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Deps = append(dpInfo.Deps, b.properties.Contents...) - dpInfo.Paths = append(dpInfo.Paths, b.modulePaths...) } type bootclasspathFragmentMemberType struct { diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index c0f73afc5..5fb36df6d 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -610,7 +610,8 @@ func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) profile := bootImageProfileRule(ctx, imageConfig) // If dexpreopt of boot image jars should be skipped, stop after generating a profile. - if SkipDexpreoptBootJars(ctx) { + global := dexpreopt.GetGlobalConfig(ctx) + if SkipDexpreoptBootJars(ctx) || (global.OnlyPreoptArtBootImage && imageConfig.name != "art") { return } diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index 7499481de..33be60352 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -68,7 +68,7 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod // The check should be skipped on unbundled builds because system server jars are not preopted on // unbundled builds since the artifacts are installed into the system image, not the APEXes. - if global.DisablePreopt || len(targets) == 0 || ctx.Config().UnbundledBuild() { + if global.DisablePreopt || global.OnlyPreoptArtBootImage || len(targets) == 0 || ctx.Config().UnbundledBuild() { return } diff --git a/java/java.go b/java/java.go index dd0418894..bb9357cc7 100644 --- a/java/java.go +++ b/java/java.go @@ -27,6 +27,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" "android/soong/remoteexec" + "android/soong/testing" "android/soong/ui/metrics/bp2build_metrics_proto" "github.com/google/blueprint" @@ -640,7 +641,7 @@ type Library struct { exportedProguardFlagFiles android.Paths - InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) + InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths) } var _ android.ApexModule = (*Library)(nil) @@ -719,12 +720,9 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.compile(ctx, nil, nil, nil) - // Collect the module directory for IDE info in java/jdeps.go. - j.modulePaths = append(j.modulePaths, ctx.ModuleDir()) - exclusivelyForApex := !apexInfo.IsForPlatform() if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { - var extraInstallDeps android.Paths + var extraInstallDeps android.InstallPaths if j.InstallMixin != nil { extraInstallDeps = j.InstallMixin(ctx, j.outputFile) } @@ -1228,10 +1226,12 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.Test.generateAndroidBuildActionsWithConfig(ctx, configs) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.generateAndroidBuildActionsWithConfig(ctx, nil) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) { diff --git a/java/jdeps.go b/java/jdeps.go index 4c8c11c5d..7e3a14f55 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -75,7 +75,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules) dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars) dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars) - dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths) + dpInfo.Paths = []string{ctx.ModuleDir(module)} dpInfo.Static_libs = android.FirstUniqueStrings(dpInfo.Static_libs) dpInfo.Libs = android.FirstUniqueStrings(dpInfo.Libs) moduleInfos[name] = dpInfo diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go index bf1b04d94..af13aa3cb 100644 --- a/java/resourceshrinker.go +++ b/java/resourceshrinker.go @@ -23,7 +23,8 @@ import ( var shrinkResources = pctx.AndroidStaticRule("shrinkResources", blueprint.RuleParams{ // Note that we suppress stdout to avoid successful log confirmations. - Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources >/dev/null`, + Command: `RESOURCESHRINKER_OPTS=-Dcom.android.tools.r8.dexContainerExperiment ` + + `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources >/dev/null`, CommandDeps: []string{"${config.ResourceShrinkerCmd}"}, }, "raw_resources") diff --git a/java/robolectric.go b/java/robolectric.go index af5633934..a66b31007 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/java/config" + "android/soong/testing" "android/soong/tradefed" "github.com/google/blueprint/proptools" @@ -225,7 +226,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) } installPath := android.PathForModuleInstall(ctx, r.BaseModuleName()) - var installDeps android.Paths + var installDeps android.InstallPaths if r.manifest != nil { r.data = append(r.data, r.manifest) @@ -253,6 +254,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) } r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, diff --git a/java/sdk_library.go b/java/sdk_library.go index ea451743b..fb2781213 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -624,6 +624,13 @@ type sdkLibraryProperties struct { Legacy_errors_allowed *bool } + // Determines if the module contributes to any api surfaces. + // This property should be set to true only if the module is listed under + // frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp. + // Otherwise, this property should be set to false. + // Defaults to false. + Contribute_to_android_api *bool + // TODO: determines whether to create HTML doc or not // Html_doc *bool } @@ -1966,6 +1973,10 @@ func (module *SdkLibrary) UniqueApexVariations() bool { return module.uniqueApexVariations() } +func (module *SdkLibrary) ContributeToApi() bool { + return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false) +} + // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { moduleMinApiLevel := module.Library.MinSdkVersion(mctx) diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 21f0bab37..82f8a4d50 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -1068,6 +1068,137 @@ 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) { + bp := ` + apex_contributions { + name: "my_mainline_module_contributions", + api_domain: "my_mainline_module", + contents: [ + // legacy mechanism prefers the prebuilt + // mainline_module_contributions supersedes this since source is listed explicitly + "sdklib.prebuilt_preferred_using_legacy_flags", + + // legacy mechanism prefers the source + // mainline_module_contributions supersedes this since prebuilt is listed explicitly + "prebuilt_sdklib.source_preferred_using_legacy_flags", + ], + } + all_apex_contributions { + name: "all_apex_contributions", + } + java_sdk_library { + name: "sdklib.prebuilt_preferred_using_legacy_flags", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + system: { + enabled: true, + } + } + java_sdk_library_import { + name: "sdklib.prebuilt_preferred_using_legacy_flags", + prefer: true, // prebuilt is preferred using legacy mechanism + public: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + system: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + } + java_sdk_library { + name: "sdklib.source_preferred_using_legacy_flags", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + system: { + enabled: true, + } + } + java_sdk_library_import { + name: "sdklib.source_preferred_using_legacy_flags", + prefer: false, // source is preferred using legacy mechanism + public: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + system: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + } + + // rdeps + java_library { + name: "public", + srcs: ["a.java"], + libs: [ + // this should get source since source is listed in my_mainline_module_contributions + "sdklib.prebuilt_preferred_using_legacy_flags.stubs", + "sdklib.prebuilt_preferred_using_legacy_flags.stubs.system", + + // this should get prebuilt since source is listed in my_mainline_module_contributions + "sdklib.source_preferred_using_legacy_flags.stubs", + "sdklib.source_preferred_using_legacy_flags.stubs.system", + + ], + } + ` + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("sdklib.source_preferred_using_legacy_flags", "sdklib.prebuilt_preferred_using_legacy_flags"), + android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { + android.RegisterApexContributionsBuildComponents(ctx) + }), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.BuildFlags = map[string]string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions", + } + }), + ).RunTestWithBp(t, bp) + + // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions + public := result.ModuleForTests("public", "android_common") + rule := public.Output("javac/public.jar") + inputs := rule.Implicits.Strings() + expectedInputs := []string{ + // source + "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.jar", + "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.jar", + + // prebuilt + "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.jar", + "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar", + } + for _, expected := range expectedInputs { + if !android.InList(expected, inputs) { + t.Errorf("expected %q to contain %q", inputs, expected) + } + } +} + func TestJavaSdkLibraryEnforce(t *testing.T) { partitionToBpOption := func(partition string) string { switch partition { diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index 17d301b70..30dd55fa9 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -87,9 +87,6 @@ type SystemServerClasspathModule struct { ClasspathFragmentBase properties systemServerClasspathFragmentProperties - - // Collect the module directory for IDE info in java/jdeps.go. - modulePaths []string } func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { @@ -129,9 +126,6 @@ func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.Mo configuredJars = configuredJars.AppendList(&standaloneConfiguredJars) classpathJars = append(classpathJars, standaloneClasspathJars...) s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) - - // Collect the module directory for IDE info in java/jdeps.go. - s.modulePaths = append(s.modulePaths, ctx.ModuleDir()) } func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { @@ -242,7 +236,6 @@ func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpM func (s *SystemServerClasspathModule) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Deps = append(dpInfo.Deps, s.properties.Contents...) dpInfo.Deps = append(dpInfo.Deps, s.properties.Standalone_contents...) - dpInfo.Paths = append(dpInfo.Paths, s.modulePaths...) } type systemServerClasspathFragmentMemberType struct { diff --git a/java/test_spec_test.go b/java/test_spec_test.go new file mode 100644 index 000000000..39aff4cef --- /dev/null +++ b/java/test_spec_test.go @@ -0,0 +1,133 @@ +package java + +import ( + "strings" + "testing" + + "android/soong/android" + soongTesting "android/soong/testing" + "android/soong/testing/test_spec_proto" + "google.golang.org/protobuf/proto" +) + +func TestTestSpec(t *testing.T) { + bp := `test_spec { + name: "module-name", + teamId: "12345", + tests: [ + "java-test-module-name-one", + "java-test-module-name-two" + ] + } + + java_test { + name: "java-test-module-name-one", + } + + java_test { + name: "java-test-module-name-two", + }` + result := runTest(t, android.FixtureExpectsNoErrors, bp) + + module := result.ModuleForTests( + "module-name", "", + ).Module().(*soongTesting.TestSpecModule) + + // Check that the provider has the right contents + data := result.ModuleProvider( + module, soongTesting.TestSpecProviderKey, + ).(soongTesting.TestSpecProviderData) + if !strings.HasSuffix( + data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb", + ) { + t.Errorf( + "Missing intermediates path in provider: %s", + data.IntermediatePath.String(), + ) + } + + buildParamsSlice := module.BuildParamsForTests() + var metadata = "" + for _, params := range buildParamsSlice { + if params.Rule.String() == "android/soong/android.writeFile" { + metadata = params.Args["content"] + } + } + + metadataList := make([]*test_spec_proto.TestSpec_OwnershipMetadata, 0, 2) + teamId := "12345" + bpFilePath := "Android.bp" + targetNames := []string{ + "java-test-module-name-one", "java-test-module-name-two", + } + + for _, test := range targetNames { + targetName := test + metadata := test_spec_proto.TestSpec_OwnershipMetadata{ + TrendyTeamId: &teamId, + TargetName: &targetName, + Path: &bpFilePath, + } + metadataList = append(metadataList, &metadata) + } + testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList} + protoData, _ := proto.Marshal(&testSpecMetadata) + rawData := string(protoData) + formattedData := strings.ReplaceAll(rawData, "\n", "\\n") + expectedMetadata := "'" + formattedData + "\\n'" + + if metadata != expectedMetadata { + t.Errorf( + "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata, + expectedMetadata, + ) + } + + // Tests for all_test_spec singleton. + singleton := result.SingletonForTests("all_test_specs") + rule := singleton.Rule("all_test_specs_rule") + prebuiltOs := result.Config.PrebuiltOS() + expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb" + expectedOutputFile := "out/soong/ownership/all_test_specs.pb" + expectedInputFile := "out/soong/.intermediates/module-name/intermediateTestSpecMetadata.pb" + if !strings.Contains( + strings.TrimSpace(rule.Output.String()), + expectedOutputFile, + ) { + t.Errorf( + "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s", + rule.Output.String(), expectedOutputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.Inputs[0].String()), + expectedInputFile, + ) { + t.Errorf( + "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s", + rule.Inputs[0].String(), expectedInputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.RuleParams.Command), + expectedCmd, + ) { + t.Errorf( + "Retrieved cmd: %s is not equal to expectedCmd: %s", + rule.RuleParams.Command, expectedCmd, + ) + } +} + +func runTest( + t *testing.T, errorHandler android.FixtureErrorHandler, bp string, +) *android.TestResult { + return android.GroupFixturePreparers( + soongTesting.PrepareForTestWithTestSpecBuildComponents, + PrepareForIntegrationTestWithJava, + ). + ExtendWithErrorHandler(errorHandler). + RunTestWithBp(t, bp) +} diff --git a/java/tradefed.go b/java/tradefed.go index ebbdec13d..349b327e8 100644 --- a/java/tradefed.go +++ b/java/tradefed.go @@ -30,8 +30,8 @@ func tradefedJavaLibraryFactory() android.Module { return module } -func tradefedJavaLibraryInstall(ctx android.ModuleContext, path android.Path) android.Paths { +func tradefedJavaLibraryInstall(ctx android.ModuleContext, path android.Path) android.InstallPaths { installedPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "tradefed"), ctx.ModuleName()+".jar", path) - return android.Paths{installedPath} + return android.InstallPaths{installedPath} } |