summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.bp16
-rw-r--r--java/aapt2.go114
-rw-r--r--java/aar.go1004
-rw-r--r--java/aar_test.go100
-rw-r--r--java/android_manifest.go48
-rw-r--r--java/android_manifest_test.go135
-rw-r--r--java/android_resources.go82
-rw-r--r--java/androidmk.go113
-rw-r--r--java/androidmk_test.go168
-rw-r--r--[-rwxr-xr-x]java/app.go779
-rw-r--r--java/app_builder.go41
-rw-r--r--java/app_import.go214
-rw-r--r--java/app_import_test.go237
-rw-r--r--java/app_set.go35
-rw-r--r--java/app_test.go1272
-rw-r--r--java/base.go919
-rw-r--r--java/boot_jars.go4
-rw-r--r--java/bootclasspath.go10
-rw-r--r--java/bootclasspath_fragment.go363
-rw-r--r--java/bootclasspath_fragment_test.go108
-rw-r--r--java/builder.go163
-rw-r--r--java/classpath_element.go11
-rw-r--r--java/classpath_fragment.go32
-rw-r--r--java/code_metadata_test.go115
-rw-r--r--java/config/Android.bp1
-rw-r--r--java/config/config.go40
-rw-r--r--java/config/droidstubs.go64
-rw-r--r--java/config/error_prone.go21
-rw-r--r--java/config/kotlin.go5
-rw-r--r--java/config/makevars.go5
-rw-r--r--java/container_test.go129
-rw-r--r--java/core-libraries/Android.bp264
-rw-r--r--java/core-libraries/TxtStubLibraries.bp156
-rw-r--r--java/device_host_converter.go44
-rw-r--r--java/device_host_converter_test.go13
-rw-r--r--java/dex.go222
-rw-r--r--java/dex_test.go335
-rw-r--r--java/dexpreopt.go303
-rw-r--r--java/dexpreopt_bootjars.go528
-rw-r--r--java/dexpreopt_check.go4
-rw-r--r--java/dexpreopt_config.go131
-rw-r--r--java/dexpreopt_config_test.go20
-rw-r--r--java/dexpreopt_config_testing.go209
-rw-r--r--java/dexpreopt_test.go6
-rw-r--r--java/droiddoc.go90
-rw-r--r--java/droiddoc_test.go6
-rw-r--r--java/droidstubs.go1042
-rw-r--r--java/droidstubs_test.go155
-rw-r--r--java/fuzz.go35
-rw-r--r--java/fuzz_test.go4
-rw-r--r--java/gen.go55
-rw-r--r--java/generated_java_library.go116
-rw-r--r--java/generated_java_library_test.go65
-rw-r--r--java/genrule.go2
-rw-r--r--java/hiddenapi.go21
-rw-r--r--java/hiddenapi_modular.go291
-rw-r--r--java/hiddenapi_monolithic.go24
-rw-r--r--java/hiddenapi_singleton.go14
-rw-r--r--java/hiddenapi_singleton_test.go43
-rw-r--r--java/jacoco.go4
-rw-r--r--java/java.go1516
-rw-r--r--java/java_test.go1157
-rw-r--r--java/jdeps.go9
-rw-r--r--java/kotlin.go7
-rw-r--r--java/legacy_core_platform_api_usage.go1
-rw-r--r--java/lint.go106
-rw-r--r--java/lint_defaults.txt14
-rw-r--r--java/lint_test.go153
-rw-r--r--java/platform_bootclasspath.go179
-rw-r--r--java/platform_bootclasspath_test.go31
-rw-r--r--java/platform_compat_config.go45
-rw-r--r--java/plugin.go35
-rw-r--r--java/prebuilt_apis.go137
-rw-r--r--java/prebuilt_apis_test.go23
-rw-r--r--java/proto.go57
-rw-r--r--java/ravenwood.go278
-rw-r--r--java/ravenwood_test.go186
-rw-r--r--java/resourceshrinker.go43
-rw-r--r--java/resourceshrinker_test.go53
-rw-r--r--java/robolectric.go126
-rw-r--r--java/robolectric_test.go98
-rw-r--r--java/rro.go18
-rw-r--r--java/rro_test.go50
-rw-r--r--java/sdk.go120
-rw-r--r--java/sdk_library.go1231
-rw-r--r--java/sdk_library_test.go624
-rw-r--r--java/sdk_version_test.go66
-rw-r--r--java/support_libraries.go2
-rw-r--r--java/system_modules.go37
-rw-r--r--java/system_modules_test.go85
-rw-r--r--java/systemserver_classpath_fragment.go14
-rw-r--r--java/test_spec_test.go122
-rw-r--r--java/testing.go216
-rw-r--r--java/tradefed.go4
94 files changed, 12612 insertions, 4781 deletions
diff --git a/java/Android.bp b/java/Android.bp
index 4af2a14eb..a941754db 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -9,12 +9,13 @@ bootstrap_go_package {
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-aconfig",
"soong-android",
- "soong-bazel",
"soong-cc",
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-testing",
"soong-provenance",
"soong-python",
"soong-remoteexec",
@@ -48,6 +49,7 @@ bootstrap_go_package {
"droidstubs.go",
"fuzz.go",
"gen.go",
+ "generated_java_library.go",
"genrule.go",
"hiddenapi.go",
"hiddenapi_modular.go",
@@ -65,7 +67,7 @@ bootstrap_go_package {
"plugin.go",
"prebuilt_apis.go",
"proto.go",
- "resourceshrinker.go",
+ "ravenwood.go",
"robolectric.go",
"rro.go",
"sdk.go",
@@ -79,10 +81,13 @@ bootstrap_go_package {
],
testSrcs: [
"aar_test.go",
+ "android_manifest_test.go",
"androidmk_test.go",
"app_import_test.go",
"app_set_test.go",
"app_test.go",
+ "code_metadata_test.go",
+ "container_test.go",
"bootclasspath_fragment_test.go",
"device_host_converter_test.go",
"dex_test.go",
@@ -92,6 +97,7 @@ bootstrap_go_package {
"droidstubs_test.go",
"fuzz_test.go",
"genrule_test.go",
+ "generated_java_library_test.go",
"hiddenapi_singleton_test.go",
"jacoco_test.go",
"java_test.go",
@@ -103,12 +109,14 @@ bootstrap_go_package {
"plugin_test.go",
"prebuilt_apis_test.go",
"proto_test.go",
- "resourceshrinker_test.go",
+ "ravenwood_test.go",
"rro_test.go",
- "sdk_test.go",
"sdk_library_test.go",
+ "sdk_test.go",
+ "sdk_version_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 7845a0b23..f704fc6fc 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
@@ -146,20 +166,25 @@ func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
blueprint.RuleParams{
- Command: `rm -rf $genDir && ` +
- `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
- `--output-text-symbols ${rTxt} $inFlags && ` +
- `${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
- `${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
+ Command: `$preamble` +
+ `${config.Aapt2Cmd} link -o $out $flags --proguard $proguardOptions ` +
+ `--output-text-symbols ${rTxt} $inFlags` +
+ `$postamble`,
CommandDeps: []string{
"${config.Aapt2Cmd}",
"${config.SoongZipCmd}",
- "${config.ExtractJarPackagesCmd}",
},
Restat: true,
},
- "flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
+ "flags", "inFlags", "proguardOptions", "rTxt", "extraPackages", "preamble", "postamble")
+
+var aapt2ExtractExtraPackagesRule = pctx.AndroidStaticRule("aapt2ExtractExtraPackages",
+ blueprint.RuleParams{
+ Command: `${config.ExtractJarPackagesCmd} -i $in -o $out --prefix '--extra-packages '`,
+ CommandDeps: []string{"${config.ExtractJarPackagesCmd}"},
+ Restat: true,
+ })
var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
blueprint.RuleParams{
@@ -175,11 +200,10 @@ var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
})
func aapt2Link(ctx android.ModuleContext,
- packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
+ packageRes, genJar, proguardOptions, rTxt android.WritablePath,
flags []string, deps android.Paths,
- compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
-
- genDir := android.PathForModuleGen(ctx, "aapt2", "R")
+ compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths,
+ featureFlagsPaths android.Paths) {
var inFlags []string
@@ -217,7 +241,7 @@ func aapt2Link(ctx android.ModuleContext,
}
// Set auxiliary outputs as implicit outputs to establish correct dependency chains.
- implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
+ implicitOutputs := append(splitPackages, proguardOptions, rTxt)
linkOutput := packageRes
// AAPT2 ignores assets in overlays. Merge them after linking.
@@ -232,31 +256,61 @@ func aapt2Link(ctx android.ModuleContext,
})
}
+ for _, featureFlagsPath := range featureFlagsPaths {
+ deps = append(deps, featureFlagsPath)
+ inFlags = append(inFlags, "--feature-flags", "@"+featureFlagsPath.String())
+ }
+
+ // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
+ // values via the flags parameter when it wants to split outputs.
+ // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
+ // tidy.
+ args := map[string]string{
+ "flags": strings.Join(flags, " "),
+ "inFlags": strings.Join(inFlags, " "),
+ "proguardOptions": proguardOptions.String(),
+ "rTxt": rTxt.String(),
+ }
+
+ if genJar != nil {
+ // Generating java source files from aapt2 was requested, use aapt2LinkAndGenRule and pass it
+ // genJar and genDir args.
+ genDir := android.PathForModuleGen(ctx, "aapt2", "R")
+ ctx.Variable(pctx, "aapt2GenDir", genDir.String())
+ ctx.Variable(pctx, "aapt2GenJar", genJar.String())
+ implicitOutputs = append(implicitOutputs, genJar)
+ args["preamble"] = `rm -rf $aapt2GenDir && `
+ args["postamble"] = `&& ${config.SoongZipCmd} -write_if_changed -jar -o $aapt2GenJar -C $aapt2GenDir -D $aapt2GenDir && ` +
+ `rm -rf $aapt2GenDir`
+ args["flags"] += " --java $aapt2GenDir"
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: aapt2LinkRule,
Description: "aapt2 link",
Implicits: deps,
Output: linkOutput,
ImplicitOutputs: implicitOutputs,
- // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
- // values via the flags parameter when it wants to split outputs.
- // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
- // tidy.
- Args: map[string]string{
- "flags": strings.Join(flags, " "),
- "inFlags": strings.Join(inFlags, " "),
- "proguardOptions": proguardOptions.String(),
- "genDir": genDir.String(),
- "genJar": genJar.String(),
- "rTxt": rTxt.String(),
- "extraPackages": extraPackages.String(),
- },
+ Args: args,
+ })
+}
+
+// aapt2ExtractExtraPackages takes a srcjar generated by aapt2 or a classes jar generated by ResourceProcessorBusyBox
+// and converts it to a text file containing a list of --extra_package arguments for passing to Make modules so they
+// correctly generate R.java entries for packages provided by transitive dependencies.
+func aapt2ExtractExtraPackages(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aapt2ExtractExtraPackagesRule,
+ Description: "aapt2 extract extra packages",
+ Input: in,
+ Output: out,
})
}
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} convert --output-format $format $in -o $out`,
+ Command: `${config.Aapt2Cmd} convert --enable-compact-entries ` +
+ `--output-format $format $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
}, "format",
)
diff --git a/java/aar.go b/java/aar.go
index f1b137de1..2f49a959d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -17,11 +17,11 @@ package java
import (
"fmt"
"path/filepath"
+ "slices"
"strconv"
"strings"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
"github.com/google/blueprint"
@@ -29,12 +29,10 @@ import (
)
type AndroidLibraryDependency interface {
- LibraryDependency
ExportPackage() android.Path
- ExportedRRODirs() []rroDir
- ExportedStaticPackages() android.Paths
- ExportedManifests() android.Paths
- ExportedAssets() android.OptionalPath
+ ResourcesNodeDepSet() *android.DepSet[*resourcesNode]
+ RRODirsDepSet() *android.DepSet[rroDir]
+ ManifestsDepSet() *android.DepSet[android.Path]
SetRROEnforcedForDependent(enforce bool)
IsRROEnforced(ctx android.BaseModuleContext) bool
}
@@ -47,7 +45,7 @@ func RegisterAARBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_library_import", AARImportFactory)
ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+ ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator)
})
}
@@ -67,6 +65,9 @@ type aaptProperties struct {
// ones.
Aapt_include_all_resources *bool
+ // list of files to use as assets.
+ Assets []string `android:"path"`
+
// list of directories relative to the Blueprints file containing assets.
// Defaults to ["assets"] if a directory called assets exists. Set to []
// to disable the default.
@@ -89,35 +90,59 @@ type aaptProperties struct {
// do not include AndroidManifest from dependent libraries
Dont_merge_manifests *bool
+ // If use_resource_processor is set, use Bazel's resource processor instead of aapt2 to generate R.class files.
+ // The resource processor produces more optimal R.class files that only list resources in the package of the
+ // library that provided them, as opposed to aapt2 which produces R.java files for every package containing
+ // every resource. Using the resource processor can provide significant build time speedups, but requires
+ // fixing the module to use the correct package to reference each resource, and to avoid having any other
+ // libraries in the tree that use the same package name. Defaults to false, but will default to true in the
+ // future.
+ Use_resource_processor *bool
+
// 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"`
+
+ // Names of aconfig_declarations modules that specify aconfig flags that the module depends on.
+ Flags_packages []string
}
type aapt struct {
- aaptSrcJar android.Path
- exportPackage android.Path
- manifestPath android.Path
- transitiveManifestPaths android.Paths
- proguardOptionsFile android.Path
- rroDirs []rroDir
- rTxt android.Path
- extraAaptPackagesFile android.Path
- mergedManifestFile android.Path
- noticeFile android.OptionalPath
- assetPackage android.OptionalPath
- isLibrary bool
- defaultManifestVersion string
- useEmbeddedNativeLibs bool
- useEmbeddedDex bool
- usesNonSdkApis bool
- hasNoCode bool
- LoggingParent string
- resourceFiles android.Paths
+ aaptSrcJar android.Path
+ transitiveAaptRJars android.Paths
+ transitiveAaptResourcePackagesFile android.Path
+ exportPackage android.Path
+ manifestPath android.Path
+ proguardOptionsFile android.Path
+ rTxt android.Path
+ rJar android.Path
+ extraAaptPackagesFile android.Path
+ mergedManifestFile android.Path
+ noticeFile android.OptionalPath
+ assetPackage android.OptionalPath
+ isLibrary bool
+ defaultManifestVersion string
+ useEmbeddedNativeLibs bool
+ useEmbeddedDex bool
+ usesNonSdkApis bool
+ hasNoCode bool
+ LoggingParent string
+ resourceFiles android.Paths
splitNames []string
splits []split
aaptProperties aaptProperties
+
+ resourcesNodesDepSet *android.DepSet[*resourcesNode]
+ rroDirsDepSet *android.DepSet[rroDir]
+ manifestsDepSet *android.DepSet[android.Path]
+
+ manifestValues struct {
+ applicationId string
+ }
}
type split struct {
@@ -138,20 +163,29 @@ func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
}
}
+func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
+ return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) &&
+ // TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
+ !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
+}
+
+func (a *aapt) filterProduct() string {
+ return String(a.aaptProperties.Filter_product)
+}
+
func (a *aapt) ExportPackage() android.Path {
return a.exportPackage
}
-
-func (a *aapt) ExportedRRODirs() []rroDir {
- return a.rroDirs
+func (a *aapt) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.resourcesNodesDepSet
}
-func (a *aapt) ExportedManifests() android.Paths {
- return a.transitiveManifestPaths
+func (a *aapt) RRODirsDepSet() *android.DepSet[rroDir] {
+ return a.rroDirsDepSet
}
-func (a *aapt) ExportedAssets() android.OptionalPath {
- return a.assetPackage
+func (a *aapt) ManifestsDepSet() *android.DepSet[android.Path] {
+ return a.manifestsDepSet
}
func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
@@ -175,9 +209,14 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte
// Flags specified in Android.bp
linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
- linkFlags = append(linkFlags, "--no-static-lib-packages")
+ linkFlags = append(linkFlags, "--enable-compact-entries")
// Find implicit or explicit asset and resource dirs
+ assets := android.PathsRelativeToModuleSourceDir(android.SourceInput{
+ Context: ctx,
+ Paths: a.aaptProperties.Assets,
+ IncludeDirs: false,
+ })
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
@@ -212,6 +251,28 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte
assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
assetDeps = append(assetDeps, a.noticeFile.Path())
}
+ if len(assets) > 0 {
+ // aapt2 doesn't support adding individual asset files. Create a temp directory to hold asset
+ // files and pass it to aapt2.
+ tmpAssetDir := android.PathForModuleOut(ctx, "tmp_asset_dir")
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Text("rm -rf").Text(tmpAssetDir.String()).
+ Text("&&").
+ Text("mkdir -p").Text(tmpAssetDir.String())
+
+ for _, asset := range assets {
+ output := tmpAssetDir.Join(ctx, asset.Rel())
+ assetDeps = append(assetDeps, output)
+ rule.Command().Text("mkdir -p").Text(filepath.Dir(output.String()))
+ rule.Command().Text("cp").Input(asset).Output(output)
+ }
+
+ rule.Build("tmp_asset_dir", "tmp_asset_dir")
+
+ assetDirStrings = append(assetDirStrings, tmpAssetDir.String())
+ }
linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
linkDeps = append(linkDeps, manifestPath)
@@ -287,23 +348,32 @@ var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
-func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
- classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
- enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
+type aaptBuildActionOptions struct {
+ sdkContext android.SdkContext
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+ excludedLibs []string
+ enforceDefaultTargetSdkVersion bool
+ forceNonFinalResourceIDs bool
+ extraLinkFlags []string
+ aconfigTextFiles android.Paths
+ usesLibrary *usesLibrary
+}
+
+func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptions) {
- transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
- aaptLibs(ctx, sdkContext, classLoaderContexts)
+ staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedExportPackages, libFlags :=
+ aaptLibs(ctx, opts.sdkContext, opts.classLoaderContexts, opts.usesLibrary)
// Exclude any libraries from the supplied list.
- classLoaderContexts = classLoaderContexts.ExcludeLibs(excludedLibs)
+ opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
- SdkContext: sdkContext,
- ClassLoaderContexts: classLoaderContexts,
+ SdkContext: opts.sdkContext,
+ ClassLoaderContexts: opts.classLoaderContexts,
IsLibrary: a.isLibrary,
DefaultManifestVersion: a.defaultManifestVersion,
UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
@@ -311,16 +381,24 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
UseEmbeddedDex: a.useEmbeddedDex,
HasNoCode: a.hasNoCode,
LoggingParent: a.LoggingParent,
- EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
+ EnforceDefaultTargetSdkVersion: opts.enforceDefaultTargetSdkVersion,
})
+ staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
+ sharedDeps := transitiveAarDeps(sharedResourcesNodesDepSet.ToList())
+
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
- a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...)
- a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...)
-
- if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
- a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary)
+ transitiveManifestPaths := append(android.Paths{manifestPath}, additionalManifests...)
+ transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...)
+
+ if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
+ manifestMergerParams := ManifestMergerParams{
+ staticLibManifests: transitiveManifestPaths[1:],
+ isLibrary: a.isLibrary,
+ packageName: a.manifestValues.applicationId,
+ }
+ a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], manifestMergerParams)
if !a.isLibrary {
// Only use the merged manifest for applications. For libraries, the transitive closure of manifests
// will be propagated to the final application and merged there. The merged manifest for libraries is
@@ -331,28 +409,38 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
a.mergedManifestFile = manifestPath
}
- compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
+ compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath)
- rroDirs = append(rroDirs, staticRRODirs...)
linkFlags = append(linkFlags, libFlags...)
- linkDeps = append(linkDeps, libDeps...)
- linkFlags = append(linkFlags, extraLinkFlags...)
+ linkDeps = append(linkDeps, sharedExportPackages...)
+ linkDeps = append(linkDeps, staticDeps.resPackages()...)
+ linkFlags = append(linkFlags, opts.extraLinkFlags...)
if a.isLibrary {
linkFlags = append(linkFlags, "--static-lib")
}
+ if opts.forceNonFinalResourceIDs {
+ linkFlags = append(linkFlags, "--non-final-ids")
+ }
+
+ linkFlags = append(linkFlags, "--no-static-lib-packages")
+ if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
+ // When building an android_library using ResourceProcessorBusyBox pass --merge-only to skip resource
+ // references validation until the final app link step when all static libraries are present.
+ linkFlags = append(linkFlags, "--merge-only")
+ }
packageRes := android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
rTxt := android.PathForModuleOut(ctx, "R.txt")
// This file isn't used by Soong, but is generated for exporting
extraPackages := android.PathForModuleOut(ctx, "extra_packages")
+ var transitiveRJars android.Paths
+ var srcJar android.WritablePath
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 {
@@ -363,7 +451,32 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
var compiledRes, compiledOverlay android.Paths
- compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
+ // AAPT2 overlays are in lowest to highest priority order, reverse the topological order
+ // of transitiveStaticLibs.
+ transitiveStaticLibs := android.ReversePaths(staticDeps.resPackages())
+
+ if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
+ // When building an android_library with ResourceProcessorBusyBox enabled treat static library dependencies
+ // as imports. The resources from dependencies will not be merged into this module's package-res.apk, and
+ // instead modules depending on this module will reference package-res.apk from all transitive static
+ // dependencies.
+ for _, sharedDep := range sharedDeps {
+ if sharedDep.usedResourceProcessor {
+ transitiveRJars = append(transitiveRJars, sharedDep.rJar)
+ }
+ }
+ for _, staticDep := range staticDeps {
+ linkDeps = append(linkDeps, staticDep.resPackage)
+ linkFlags = append(linkFlags, "-I "+staticDep.resPackage.String())
+ if staticDep.usedResourceProcessor {
+ transitiveRJars = append(transitiveRJars, staticDep.rJar)
+ }
+ }
+ } else {
+ // When building an app or building a library without ResourceProcessorBusyBox enabled all static
+ // dependencies are compiled into this module's package-res.apk as overlays.
+ compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
+ }
if len(transitiveStaticLibs) > 0 {
// If we are using static android libraries, every source file becomes an overlay.
@@ -386,7 +499,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
}
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
@@ -404,12 +517,23 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
})
}
- aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
- linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
+ if !a.useResourceProcessorBusyBox(ctx) {
+ // the subdir "android" is required to be filtered by package names
+ srcJar = android.PathForModuleGen(ctx, "android", "R.srcjar")
+ }
+ // No need to specify assets from dependencies to aapt2Link for libraries, all transitive assets will be
+ // provided to the final app aapt2Link step.
+ var transitiveAssets android.Paths
+ if !a.isLibrary {
+ transitiveAssets = android.ReverseSliceInPlace(staticDeps.assets())
+ }
+ aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
+ linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages,
+ opts.aconfigTextFiles)
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
- if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 {
+ if android.PrefixInList(linkFlags, "-A ") {
assets := android.PathForModuleOut(ctx, "assets.zip")
ctx.Build(pctx, android.BuildParams{
Rule: extractAssetsRule,
@@ -420,21 +544,173 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
a.assetPackage = android.OptionalPathForPath(assets)
}
+ if a.useResourceProcessorBusyBox(ctx) {
+ rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags,
+ opts.forceNonFinalResourceIDs)
+ aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
+ transitiveRJars = append(transitiveRJars, rJar)
+ a.rJar = rJar
+ } else {
+ aapt2ExtractExtraPackages(ctx, extraPackages, srcJar)
+ }
+
+ transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
+ transitiveAaptResourcePackages = slices.DeleteFunc(transitiveAaptResourcePackages, func(p string) bool {
+ return p == packageRes.String()
+ })
+ transitiveAaptResourcePackagesFile := android.PathForModuleOut(ctx, "transitive-res-packages")
+ android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
+
+ // Reverse the list of R.jar files so that the current module comes first, and direct dependencies come before
+ // transitive dependencies.
+ transitiveRJars = android.ReversePaths(transitiveRJars)
+
a.aaptSrcJar = srcJar
+ a.transitiveAaptRJars = transitiveRJars
+ a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
a.exportPackage = packageRes
a.manifestPath = manifestPath
a.proguardOptionsFile = proguardOptionsFile
- a.rroDirs = rroDirs
a.extraAaptPackagesFile = extraPackages
a.rTxt = rTxt
a.splits = splits
+ a.resourcesNodesDepSet = android.NewDepSetBuilder[*resourcesNode](android.TOPOLOGICAL).
+ Direct(&resourcesNode{
+ resPackage: a.exportPackage,
+ manifest: a.manifestPath,
+ additionalManifests: additionalManifests,
+ rTxt: a.rTxt,
+ rJar: a.rJar,
+ assets: a.assetPackage,
+
+ usedResourceProcessor: a.useResourceProcessorBusyBox(ctx),
+ }).
+ Transitive(staticResourcesNodesDepSet).Build()
+ a.rroDirsDepSet = android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL).
+ Direct(rroDirs...).
+ Transitive(staticRRODirsDepSet).Build()
+ a.manifestsDepSet = android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).
+ Direct(a.manifestPath).
+ DirectSlice(additionalManifests).
+ Transitive(staticManifestsDepSet).Build()
}
-// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
- transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
+var resourceProcessorBusyBox = pctx.AndroidStaticRule("resourceProcessorBusyBox",
+ blueprint.RuleParams{
+ Command: "${config.JavaCmd} -cp ${config.ResourceProcessorBusyBox} " +
+ "com.google.devtools.build.android.ResourceProcessorBusyBox --tool=GENERATE_BINARY_R -- @${out}.args && " +
+ "if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out}; fi",
+ CommandDeps: []string{"${config.ResourceProcessorBusyBox}"},
+ Rspfile: "${out}.args",
+ RspfileContent: "--primaryRTxt ${rTxt} --primaryManifest ${manifest} --classJarOutput ${out}.tmp ${args}",
+ Restat: true,
+ }, "rTxt", "manifest", "args")
+
+// resourceProcessorBusyBoxGenerateBinaryR converts the R.txt file produced by aapt2 into R.class files
+// using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
+// supports producing classes for static dependencies that only include resources from that dependency.
+func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
+ rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string,
+ forceNonFinalIds bool) {
+
+ var args []string
+ var deps android.Paths
+
+ if !isLibrary {
+ // When compiling an app, pass all R.txt and AndroidManifest.xml from transitive static library dependencies
+ // to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each
+ // package.
+ args, deps = transitiveDeps.resourceProcessorDeps()
+ if forceNonFinalIds {
+ args = append(args, "--finalFields=false")
+ }
+ } else {
+ // When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this
+ // library. Pass --finalFields=false so that the R.class file contains non-final fields so they don't get
+ // inlined into the library before the final IDs are assigned during app compilation.
+ args = append(args, "--finalFields=false")
+ }
+
+ for i, arg := range aaptFlags {
+ const AAPT_CUSTOM_PACKAGE = "--custom-package"
+ if strings.HasPrefix(arg, AAPT_CUSTOM_PACKAGE) {
+ pkg := strings.TrimSpace(strings.TrimPrefix(arg, AAPT_CUSTOM_PACKAGE))
+ if pkg == "" && i+1 < len(aaptFlags) {
+ pkg = aaptFlags[i+1]
+ }
+ args = append(args, "--packageForR "+pkg)
+ }
+ }
+
+ deps = append(deps, rTxt, manifest)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: resourceProcessorBusyBox,
+ Output: rJar,
+ Implicits: deps,
+ Description: "ResourceProcessorBusyBox",
+ Args: map[string]string{
+ "rTxt": rTxt.String(),
+ "manifest": manifest.String(),
+ "args": strings.Join(args, " "),
+ },
+ })
+}
+
+type resourcesNode struct {
+ resPackage android.Path
+ manifest android.Path
+ additionalManifests android.Paths
+ rTxt android.Path
+ rJar android.Path
+ assets android.OptionalPath
+
+ usedResourceProcessor bool
+}
+
+type transitiveAarDeps []*resourcesNode
+
+func (t transitiveAarDeps) resPackages() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ paths = append(paths, dep.resPackage)
+ }
+ return paths
+}
+
+func (t transitiveAarDeps) manifests() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ paths = append(paths, dep.manifest)
+ paths = append(paths, dep.additionalManifests...)
+ }
+ return paths
+}
+
+func (t transitiveAarDeps) resourceProcessorDeps() (args []string, deps android.Paths) {
+ for _, dep := range t {
+ args = append(args, "--library="+dep.rTxt.String()+","+dep.manifest.String())
+ deps = append(deps, dep.rTxt, dep.manifest)
+ }
+ return args, deps
+}
- var sharedLibs android.Paths
+func (t transitiveAarDeps) assets() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ if dep.assets.Valid() {
+ paths = append(paths, dep.assets.Path())
+ }
+ }
+ return paths
+}
+
+// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
+func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext,
+ classLoaderContexts dexpreopt.ClassLoaderContextMap, usesLibrary *usesLibrary) (
+ staticResourcesNodes, sharedResourcesNodes *android.DepSet[*resourcesNode], staticRRODirs *android.DepSet[rroDir],
+ staticManifests *android.DepSet[android.Path], sharedLibs android.Paths, flags []string) {
if classLoaderContexts == nil {
// Not all callers need to compute class loader context, those who don't just pass nil.
@@ -447,6 +723,11 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
+ var staticResourcesNodeDepSets []*android.DepSet[*resourcesNode]
+ var sharedResourcesNodeDepSets []*android.DepSet[*resourcesNode]
+ rroDirsDepSetBuilder := android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL)
+ manifestsDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL)
+
ctx.VisitDirectDeps(func(module android.Module) {
depTag := ctx.OtherModuleDependencyTag(module)
@@ -461,6 +742,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case sdkLibTag, libTag:
if exportPackage != nil {
+ sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
sharedLibs = append(sharedLibs, exportPackage)
}
case frameworkResTag:
@@ -469,32 +751,34 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
}
case staticLibTag:
if exportPackage != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
- transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
- transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- if aarDep.ExportedAssets().Valid() {
- assets = append(assets, aarDep.ExportedAssets().Path())
- }
-
- outer:
- for _, d := range aarDep.ExportedRRODirs() {
- for _, e := range staticRRODirs {
- if d.path == e.path {
- continue outer
- }
- }
- staticRRODirs = append(staticRRODirs, d)
- }
+ staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
+ rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet())
+ manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet())
}
}
addCLCFromDep(ctx, module, classLoaderContexts)
+ if usesLibrary != nil {
+ addMissingOptionalUsesLibsFromDep(ctx, module, usesLibrary)
+ }
})
- deps = append(deps, sharedLibs...)
- deps = append(deps, transitiveStaticLibs...)
-
- if len(transitiveStaticLibs) > 0 {
+ // AAPT2 overlays are in lowest to highest priority order, the topological order will be reversed later.
+ // Reverse the dependency order now going into the depset so that it comes out in order after the second
+ // reverse later.
+ // NOTE: this is legacy and probably incorrect behavior, for most other cases (e.g. conflicting classes in
+ // dependencies) the highest priority dependency is listed first, but for resources the highest priority
+ // dependency has to be listed last. This is also inconsistent with the way manifests from the same
+ // transitive dependencies are merged.
+ staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
+ android.ReverseSliceInPlace(staticResourcesNodeDepSets))
+ sharedResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
+ android.ReverseSliceInPlace(sharedResourcesNodeDepSets))
+
+ staticRRODirs = rroDirsDepSetBuilder.Build()
+ staticManifests = manifestsDepSetBuilder.Build()
+
+ if len(staticResourcesNodes.ToList()) > 0 {
flags = append(flags, "--auto-add-overlay")
}
@@ -502,61 +786,62 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
flags = append(flags, "-I "+sharedLib.String())
}
- transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
- transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
-
- return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags
+ return staticResourcesNodes, sharedResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
}
type AndroidLibrary struct {
Library
aapt
- android.BazelModuleBase
androidLibraryProperties androidLibraryProperties
aarFile android.WritablePath
-
- exportedStaticPackages android.Paths
-}
-
-var _ android.OutputFileProducer = (*AndroidLibrary)(nil)
-
-// For OutputFileProducer interface
-func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".aar":
- return []android.Path{a.aarFile}, nil
- default:
- return a.Library.OutputFiles(tag)
- }
-}
-
-func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
}
var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ a.usesLibrary.deps(ctx, false)
a.Module.deps(ctx)
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
- a.usesLibrary.deps(ctx, false)
+
+ for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false)
+ if a.usesLibrary.shouldDisableDexpreopt {
+ a.dexpreopter.disableDexpreopt()
+ }
+ aconfigTextFilePaths := getAconfigFilePaths(ctx)
+ a.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: android.SdkContext(a),
+ classLoaderContexts: a.classLoaderContexts,
+ enforceDefaultTargetSdkVersion: false,
+ aconfigTextFiles: aconfigTextFilePaths,
+ usesLibrary: &a.usesLibrary,
+ },
+ )
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
- ctx.CheckbuildFile(a.proguardOptionsFile)
- ctx.CheckbuildFile(a.exportPackage)
- ctx.CheckbuildFile(a.aaptSrcJar)
+ a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
+
+ ctx.CheckbuildFile(a.aapt.proguardOptionsFile)
+ ctx.CheckbuildFile(a.aapt.exportPackage)
+ if a.useResourceProcessorBusyBox(ctx) {
+ ctx.CheckbuildFile(a.aapt.rJar)
+ } else {
+ ctx.CheckbuildFile(a.aapt.aaptSrcJar)
+ }
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -565,10 +850,32 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
a.linter.manifest = a.aapt.manifestPath
a.linter.resources = a.aapt.resourceFiles
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
- a.proguardOptionsFile)
+ proguardSpecInfo := a.collectProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
+ exportedProguardFlagsFiles := proguardSpecInfo.ProguardFlagsFiles.ToList()
+ a.extraProguardFlagsFiles = append(a.extraProguardFlagsFiles, exportedProguardFlagsFiles...)
+ a.extraProguardFlagsFiles = append(a.extraProguardFlagsFiles, a.proguardOptionsFile)
+
+ combinedExportedProguardFlagFile := android.PathForModuleOut(ctx, "export_proguard_flags")
+ writeCombinedProguardFlagsFile(ctx, combinedExportedProguardFlagFile, exportedProguardFlagsFiles)
+ a.combinedExportedProguardFlagsFile = combinedExportedProguardFlagFile
+
+ var extraSrcJars android.Paths
+ var extraCombinedJars android.Paths
+ var extraClasspathJars android.Paths
+ if a.useResourceProcessorBusyBox(ctx) {
+ // When building a library with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox for this
+ // library and each of the transitive static android_library dependencies has already created an
+ // R.class file for the appropriate package. Add all of those R.class files to the classpath.
+ extraClasspathJars = a.transitiveAaptRJars
+ } else {
+ // When building a library without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
+ // R.java files for the library's package and the packages from all transitive static android_library
+ // dependencies. Compile the srcjar alongside the rest of the sources.
+ extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
+ }
- a.Module.compile(ctx, a.aaptSrcJar)
+ a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
var res android.Paths
@@ -577,33 +884,39 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.CheckbuildFile(a.aarFile)
}
- a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
- android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
- ctx.VisitDirectDeps(func(m android.Module) {
- if ctx.OtherModuleDependencyTag(m) == staticLibTag {
- if lib, ok := m.(LibraryDependency); ok {
- a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
- }
- if alib, ok := m.(AndroidLibraryDependency); ok {
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportPackage())
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportedStaticPackages()...)
- }
- }
- })
- a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
- a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
-
prebuiltJniPackages := android.Paths{}
ctx.VisitDirectDeps(func(module android.Module) {
- if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
}
})
if len(prebuiltJniPackages) > 0 {
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+ android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{
JniPackages: prebuiltJniPackages,
})
}
+
+ android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
+ AconfigTextFiles: aconfigTextFilePaths,
+ })
+
+ a.setOutputFiles(ctx)
+}
+
+func (a *AndroidLibrary) setOutputFiles(ctx android.ModuleContext) {
+ ctx.SetOutputFiles([]android.Path{a.aarFile}, ".aar")
+ setOutputFiles(ctx, a.Library.Module)
+}
+
+func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(dpInfo)
+ a.aapt.IDEInfo(dpInfo)
+}
+
+func (a *aapt) IDEInfo(dpInfo *android.IdeInfo) {
+ if a.rJar != nil {
+ dpInfo.Jars = append(dpInfo.Jars, a.rJar.String())
+ }
}
// android_library builds and links sources into a `.jar` file for the device along with Android resources.
@@ -618,14 +931,14 @@ func AndroidLibraryFactory() android.Module {
module.Module.addHostAndDeviceProperties()
module.AddProperties(
&module.aaptProperties,
- &module.androidLibraryProperties)
+ &module.androidLibraryProperties,
+ &module.sourceProperties)
module.androidLibraryProperties.BuildAAR = true
module.Module.linter.library = true
android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
@@ -658,13 +971,15 @@ type AARImportProperties struct {
// will be passed transitively through android_libraries to an android_app.
//TODO(b/241138093) evaluate whether we can have this flag default to true for Bazel conversion
Extract_jni *bool
+
+ // If set, overrides the manifest extracted from the AAR with the provided path.
+ Manifest *string `android:"path"`
}
type AARImport struct {
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
prebuilt android.Prebuilt
// Functionality common to Module and Import.
@@ -674,14 +989,20 @@ type AARImport struct {
properties AARImportProperties
- classpathFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
- extraAaptPackagesFile android.WritablePath
- manifest android.WritablePath
- assetsPackage android.WritablePath
-
- exportedStaticPackages android.Paths
+ headerJarFile android.WritablePath
+ implementationJarFile android.WritablePath
+ implementationAndResourcesJarFile android.WritablePath
+ proguardFlags android.WritablePath
+ exportPackage android.WritablePath
+ transitiveAaptResourcePackagesFile android.Path
+ extraAaptPackagesFile android.WritablePath
+ manifest android.Path
+ assetsPackage android.WritablePath
+ rTxt android.WritablePath
+ rJar android.WritablePath
+
+ resourcesNodesDepSet *android.DepSet[*resourcesNode]
+ manifestsDepSet *android.DepSet[android.Path]
hideApexVariantFromMake bool
@@ -690,20 +1011,9 @@ type AARImport struct {
sdkVersion android.SdkSpec
minSdkVersion android.ApiLevel
-}
-var _ android.OutputFileProducer = (*AARImport)(nil)
-
-// For OutputFileProducer interface
-func (a *AARImport) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".aar":
- return []android.Path{a.aarPath}, nil
- case "":
- return []android.Path{a.classpathFile}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
+ usesLibrary
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
}
func (a *AARImport) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -738,25 +1048,16 @@ var _ AndroidLibraryDependency = (*AARImport)(nil)
func (a *AARImport) ExportPackage() android.Path {
return a.exportPackage
}
-
-func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
- return android.Paths{a.proguardFlags}
-}
-
-func (a *AARImport) ExportedRRODirs() []rroDir {
- return nil
-}
-
-func (a *AARImport) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
+func (a *AARImport) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.resourcesNodesDepSet
}
-func (a *AARImport) ExportedManifests() android.Paths {
- return android.Paths{a.manifest}
+func (a *AARImport) RRODirsDepSet() *android.DepSet[rroDir] {
+ return android.NewDepSet[rroDir](android.TOPOLOGICAL, nil, nil)
}
-func (a *AARImport) ExportedAssets() android.OptionalPath {
- return android.OptionalPathForPath(a.assetsPackage)
+func (a *AARImport) ManifestsDepSet() *android.DepSet[android.Path] {
+ return a.manifestsDepSet
}
// RRO enforcement is not available on aar_import since its RRO dirs are not
@@ -792,6 +1093,8 @@ func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
+
+ a.usesLibrary.deps(ctx, false)
}
type JniPackageInfo struct {
@@ -800,7 +1103,7 @@ type JniPackageInfo struct {
JniPackages android.Paths
}
-var JniPackageProvider = blueprint.NewProvider(JniPackageInfo{})
+var JniPackageProvider = blueprint.NewProvider[JniPackageInfo]()
// Unzip an AAR and extract the JNI libs for $archString.
var extractJNI = pctx.AndroidStaticRule("extractJNI",
@@ -810,7 +1113,7 @@ var extractJNI = pctx.AndroidStaticRule("extractJNI",
`jni_files=$$(find $outDir/jni -type f) && ` +
// print error message if there are no JNI libs for this arch
`[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
- `${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
+ `${config.SoongZipCmd} -o $out -L 0 -P 'lib/${archString}' ` +
`-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
CommandDeps: []string{"${config.SoongZipCmd}"},
},
@@ -837,7 +1140,8 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.sdkVersion = a.SdkVersion(ctx)
a.minSdkVersion = a.MinSdkVersion(ctx)
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
aarName := ctx.ModuleName() + ".aar"
a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
@@ -848,20 +1152,43 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
}
+ jarName := ctx.ModuleName() + ".jar"
extractedAARDir := android.PathForModuleOut(ctx, "aar")
- a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
- a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
- a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
+ classpathFile := extractedAARDir.Join(ctx, jarName)
+
+ extractedManifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")
+ providedManifest := android.OptionalPathForModuleSrc(ctx, a.properties.Manifest)
+ if providedManifest.Valid() {
+ a.manifest = providedManifest.Path()
+ } else {
+ a.manifest = extractedManifest
+ }
+
+ a.rTxt = extractedAARDir.Join(ctx, "R.txt")
a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
+ a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
+ ProguardFlagsFiles: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ android.Paths{a.proguardFlags},
+ transitiveProguardFlags,
+ ),
+ UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ nil,
+ transitiveUnconditionalExportedFlags,
+ ),
+ })
ctx.Build(pctx, android.BuildParams{
Rule: unzipAAR,
Input: a.aarPath,
- Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage},
+ Outputs: android.WritablePaths{classpathFile, a.proguardFlags, extractedManifest, a.assetsPackage, a.rTxt},
Description: "unzip AAR",
Args: map[string]string{
"outDir": extractedAARDir.String(),
- "combinedClassesJar": a.classpathFile.String(),
+ "combinedClassesJar": classpathFile.String(),
"assetsPackage": a.assetsPackage.String(),
},
})
@@ -874,57 +1201,148 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
- rTxt := android.PathForModuleOut(ctx, "R.txt")
+ aaptRTxt := android.PathForModuleOut(ctx, "R.txt")
a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
var linkDeps android.Paths
linkFlags := []string{
"--static-lib",
- "--no-static-lib-packages",
+ "--merge-only",
"--auto-add-overlay",
+ "--no-static-lib-packages",
}
linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
linkDeps = append(linkDeps, a.manifest)
- transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
- aaptLibs(ctx, android.SdkContext(a), nil)
+ staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags :=
+ aaptLibs(ctx, android.SdkContext(a), nil, nil)
- _ = staticLibManifests
- _ = staticRRODirs
+ _ = sharedResourcesNodesDepSet
+ _ = staticRRODirsDepSet
- linkDeps = append(linkDeps, libDeps...)
- linkFlags = append(linkFlags, libFlags...)
+ staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
- overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
+ linkDeps = append(linkDeps, sharedLibs...)
+ linkDeps = append(linkDeps, staticDeps.resPackages()...)
+ linkFlags = append(linkFlags, libFlags...)
- aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
- linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
+ overlayRes := android.Paths{flata}
- // Merge this import's assets with its dependencies' assets (if there are any).
- if len(transitiveAssets) > 0 {
- mergedAssets := android.PathForModuleOut(ctx, "merged-assets.zip")
- inputZips := append(android.Paths{a.assetsPackage}, transitiveAssets...)
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeAssetsRule,
- Inputs: inputZips,
- Output: mergedAssets,
- Description: "merge assets from dependencies and self",
- })
- a.assetsPackage = mergedAssets
+ // Treat static library dependencies of static libraries as imports.
+ transitiveStaticLibs := staticDeps.resPackages()
+ linkDeps = append(linkDeps, transitiveStaticLibs...)
+ for _, staticLib := range transitiveStaticLibs {
+ linkFlags = append(linkFlags, "-I "+staticLib.String())
}
+ transitiveAssets := android.ReverseSliceInPlace(staticDeps.assets())
+ aapt2Link(ctx, a.exportPackage, nil, proguardOptionsFile, aaptRTxt,
+ linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
+
+ a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil, false)
+
+ aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
+
+ resourcesNodesDepSetBuilder := android.NewDepSetBuilder[*resourcesNode](android.TOPOLOGICAL)
+ resourcesNodesDepSetBuilder.Direct(&resourcesNode{
+ resPackage: a.exportPackage,
+ manifest: a.manifest,
+ rTxt: a.rTxt,
+ rJar: a.rJar,
+ assets: android.OptionalPathForPath(a.assetsPackage),
+
+ usedResourceProcessor: true,
+ })
+ resourcesNodesDepSetBuilder.Transitive(staticResourcesNodesDepSet)
+ a.resourcesNodesDepSet = resourcesNodesDepSetBuilder.Build()
+
+ manifestDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(a.manifest)
+ manifestDepSetBuilder.Transitive(staticManifestsDepSet)
+ a.manifestsDepSet = manifestDepSetBuilder.Build()
+
+ transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
+ transitiveAaptResourcePackages = slices.DeleteFunc(transitiveAaptResourcePackages, func(p string) bool {
+ return p == a.exportPackage.String()
+ })
+ transitiveAaptResourcePackagesFile := android.PathForModuleOut(ctx, "transitive-res-packages")
+ android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
+ a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
+
a.collectTransitiveHeaderJars(ctx)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(a.classpathFile),
+
+ a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
+ var staticJars android.Paths
+ var staticHeaderJars android.Paths
+ var staticResourceJars android.Paths
+ ctx.VisitDirectDeps(func(module android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ tag := ctx.OtherModuleDependencyTag(module)
+ switch tag {
+ case staticLibTag:
+ staticJars = append(staticJars, dep.ImplementationJars...)
+ staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
+ staticResourceJars = append(staticResourceJars, dep.ResourceJars...)
+ }
+ }
+ addCLCFromDep(ctx, module, a.classLoaderContexts)
+ addMissingOptionalUsesLibsFromDep(ctx, module, &a.usesLibrary)
+ })
+
+ var implementationJarFile android.OutputPath
+ if len(staticJars) > 0 {
+ combineJars := append(android.Paths{classpathFile}, staticJars...)
+ implementationJarFile = android.PathForModuleOut(ctx, "combined", jarName).OutputPath
+ TransformJarsToJar(ctx, implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+ } else {
+ implementationJarFile = classpathFile
+ }
+
+ var resourceJarFile android.Path
+ if len(staticResourceJars) > 1 {
+ combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", staticResourceJars, android.OptionalPath{},
+ false, nil, nil)
+ resourceJarFile = combinedJar
+ } else if len(staticResourceJars) == 1 {
+ resourceJarFile = staticResourceJars[0]
+ }
+
+ // merge implementation jar with resources if necessary
+ implementationAndResourcesJar := implementationJarFile
+ if resourceJarFile != nil {
+ jars := android.Paths{resourceJarFile, implementationAndResourcesJar}
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ implementationAndResourcesJar = combinedJar
+ }
+
+ a.implementationJarFile = implementationJarFile
+ // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
+ a.implementationAndResourcesJarFile = implementationAndResourcesJar.WithoutRel()
+
+ if len(staticHeaderJars) > 0 {
+ combineJars := append(android.Paths{classpathFile}, staticHeaderJars...)
+ a.headerJarFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, a.headerJarFile, "combine header jars", combineJars, android.OptionalPath{}, false, nil, nil)
+ } else {
+ a.headerJarFile = classpathFile
+ }
+
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(a.headerJarFile),
+ ResourceJars: android.PathsIfNonNil(resourceJarFile),
TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
- ImplementationJars: android.PathsIfNonNil(a.classpathFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationAndResourcesJarFile),
+ ImplementationJars: android.PathsIfNonNil(a.implementationJarFile),
+ StubsLinkType: Implementation,
+ // TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
if proptools.Bool(a.properties.Extract_jni) {
@@ -946,23 +1364,26 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
},
})
}
-
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
- JniPackages: a.jniPackages,
- })
}
+
+ android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{
+ JniPackages: a.jniPackages,
+ })
+
+ ctx.SetOutputFiles([]android.Path{a.implementationAndResourcesJarFile}, "")
+ ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar")
}
func (a *AARImport) HeaderJars() android.Paths {
- return android.Paths{a.classpathFile}
+ return android.Paths{a.headerJarFile}
}
func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
- return android.Paths{a.classpathFile}
+ return android.Paths{a.implementationAndResourcesJarFile}
}
-func (a *AARImport) DexJarBuildPath() android.Path {
- return nil
+func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ return OptionalDexJarPath{}
}
func (a *AARImport) DexJarInstallPath() android.Path {
@@ -970,9 +1391,11 @@ func (a *AARImport) DexJarInstallPath() android.Path {
}
func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
- return nil
+ return a.classLoaderContexts
}
+var _ UsesLibraryDependency = (*AARImport)(nil)
+
var _ android.ApexModule = (*AARImport)(nil)
// Implements android.ApexModule
@@ -981,13 +1404,19 @@ func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.M
}
// Implements android.ApexModule
-func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
return nil
}
var _ android.PrebuiltInterface = (*AARImport)(nil)
+func (a *AARImport) UsesLibrary() *usesLibrary {
+ return &a.usesLibrary
+}
+
+var _ ModuleWithUsesLibrary = (*AARImport)(nil)
+
// android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
//
// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
@@ -995,140 +1424,13 @@ var _ android.PrebuiltInterface = (*AARImport)(nil)
func AARImportFactory() android.Module {
module := &AARImport{}
- module.AddProperties(&module.properties)
+ module.AddProperties(
+ &module.properties,
+ &module.usesLibrary.usesLibraryProperties,
+ )
android.InitPrebuiltModule(module, &module.properties.Aars)
android.InitApexModule(module)
InitJavaModuleMultiTargets(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
-
-type bazelAapt struct {
- Manifest bazel.Label
- Resource_files bazel.LabelListAttribute
-}
-
-type bazelAndroidLibrary struct {
- *javaLibraryAttributes
- *bazelAapt
-}
-
-type bazelAndroidLibraryImport struct {
- Aar bazel.Label
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
- Sdk_version bazel.StringAttribute
-}
-
-func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
- manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
-
- resourceFiles := bazel.LabelList{
- Includes: []bazel.Label{},
- }
- for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
- files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
- resourceFiles.Includes = append(resourceFiles.Includes, files...)
- }
- return &bazelAapt{
- android.BazelLabelForModuleSrcSingle(ctx, manifest),
- bazel.MakeLabelListAttribute(resourceFiles),
- }
-}
-
-func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{})
- exportableStaticLibs := []string{}
- // TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel.
- for _, depName := range a.properties.Static_libs {
- if dep, ok := ctx.ModuleFromName(depName); ok {
- switch dep.(type) {
- case *AARImport, *Import:
- exportableStaticLibs = append(exportableStaticLibs, depName)
- }
- }
- }
- name := android.RemoveOptionalPrebuiltPrefix(a.Name())
- deps := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(append(a.properties.Static_libs, a.properties.Libs...))))
- exports := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(exportableStaticLibs))
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aar_import",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- },
- android.CommonAttributes{Name: name},
- &bazelAndroidLibraryImport{
- Aar: aars.Includes[0],
- Deps: bazel.MakeLabelListAttribute(deps),
- Exports: bazel.MakeLabelListAttribute(exports),
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- )
-
- neverlink := true
- ctx.CreateBazelTargetModule(
- AndroidLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- },
- },
- )
-
-}
-func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- }
-}
-
-func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2buildInfo.DepLabels
-
- deps := depLabels.Deps
- if !commonAttrs.Srcs.IsEmpty() {
- deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
- } else if !depLabels.Deps.IsEmpty() {
- ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
- }
- name := a.Name()
- props := AndroidLibraryBazelTargetModuleProperties()
-
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name},
- &bazelAndroidLibrary{
- &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Exports: depLabels.StaticDeps,
- },
- a.convertAaptAttrsWithBp2Build(ctx),
- },
- )
-
- neverlink := true
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.deviceProperties.Sdk_version},
- Java_version: bazel.StringAttribute{Value: a.properties.Java_version},
- },
- },
- },
- )
-}
diff --git a/java/aar_test.go b/java/aar_test.go
index 8afa039c4..ebad310ab 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -15,8 +15,9 @@
package java
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestAarImportProducesJniPackages(t *testing.T) {
@@ -52,7 +53,7 @@ func TestAarImportProducesJniPackages(t *testing.T) {
appMod := ctx.Module(tc.name, "android_common")
appTestMod := ctx.ModuleForTests(tc.name, "android_common")
- info, ok := ctx.ModuleProvider(appMod, JniPackageProvider).(JniPackageInfo)
+ info, ok := android.SingletonModuleProvider(ctx, appMod, JniPackageProvider)
if !ok {
t.Errorf("expected android_library_import to have JniPackageProvider")
}
@@ -81,3 +82,98 @@ func TestAarImportProducesJniPackages(t *testing.T) {
})
}
}
+
+func TestLibraryFlagsPackages(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ container: "com.android.foo",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+
+ // android_library module depends on aconfig_declarations listed in flags_packages
+ android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
+
+func TestAndroidLibraryOutputFilesRel(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ srcs: ["a.java"],
+ java_resources: ["foo.txt"],
+ }
+
+ android_library_import {
+ name: "bar",
+ aars: ["bar_prebuilt.aar"],
+
+ }
+
+ android_library_import {
+ name: "baz",
+ aars: ["baz_prebuilt.aar"],
+ static_libs: ["foo", "bar"],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ bar := result.ModuleForTests("bar", "android_common")
+ baz := result.ModuleForTests("baz", "android_common")
+
+ fooOutputPaths := foo.OutputFiles(t, "")
+ barOutputPaths := bar.OutputFiles(t, "")
+ bazOutputPaths := baz.OutputFiles(t, "")
+
+ android.AssertPathsRelativeToTopEquals(t, "foo output path",
+ []string{"out/soong/.intermediates/foo/android_common/withres/foo.jar"}, fooOutputPaths)
+ android.AssertPathsRelativeToTopEquals(t, "bar output path",
+ []string{"out/soong/.intermediates/bar/android_common/aar/bar.jar"}, barOutputPaths)
+ android.AssertPathsRelativeToTopEquals(t, "baz output path",
+ []string{"out/soong/.intermediates/baz/android_common/withres/baz.jar"}, bazOutputPaths)
+
+ android.AssertStringEquals(t, "foo relative output path",
+ "foo.jar", fooOutputPaths[0].Rel())
+ android.AssertStringEquals(t, "bar relative output path",
+ "bar.jar", barOutputPaths[0].Rel())
+ android.AssertStringEquals(t, "baz relative output path",
+ "baz.jar", bazOutputPaths[0].Rel())
+}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index f2ebfa6a2..0c77968e6 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -71,12 +71,15 @@ func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionLev
return targetSdkVersionLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
}
-// Helper function that casts android.Module to java.androidTestApp
-// If this type conversion is possible, it queries whether the test app is included in an MTS suite
+// Helper function that returns true if android_test, android_test_helper_app, java_test are in an MTS suite.
func includedInMts(module android.Module) bool {
if test, ok := module.(androidTestApp); ok {
return test.includedInTestSuite("mts")
}
+ // java_test
+ if test, ok := module.(*Test); ok {
+ return android.PrefixInList(test.testProperties.Test_suites, "mts")
+ }
return false
}
@@ -152,9 +155,10 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
if params.SdkContext != nil {
targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params)
- if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
- targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
- deps = append(deps, ApiFingerprintPath(ctx))
+ if useApiFingerprint, fingerprintTargetSdkVersion, fingerprintDeps :=
+ UseApiFingerprint(ctx); useApiFingerprint && ctx.ModuleName() != "framework-res" {
+ targetSdkVersion = fingerprintTargetSdkVersion
+ deps = append(deps, fingerprintDeps)
}
args = append(args, "--targetSdkVersion ", targetSdkVersion)
@@ -169,9 +173,10 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err)
}
- if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
- minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
- deps = append(deps, ApiFingerprintPath(ctx))
+ if useApiFingerprint, fingerprintMinSdkVersion, fingerprintDeps :=
+ UseApiFingerprint(ctx); useApiFingerprint && ctx.ModuleName() != "framework-res" {
+ minSdkVersion = fingerprintMinSdkVersion
+ deps = append(deps, fingerprintDeps)
}
if err != nil {
@@ -200,13 +205,24 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
return fixedManifest.WithoutRel()
}
-func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths,
- isLibrary bool) android.Path {
+type ManifestMergerParams struct {
+ staticLibManifests android.Paths
+ isLibrary bool
+ packageName string
+}
+
+func manifestMerger(ctx android.ModuleContext, manifest android.Path,
+ params ManifestMergerParams) android.Path {
- var args string
- if !isLibrary {
+ var args []string
+ if !params.isLibrary {
// Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests.
- args = "--remove-tools-declarations"
+ args = append(args, "--remove-tools-declarations")
+ }
+
+ packageName := params.packageName
+ if packageName != "" {
+ args = append(args, "--property PACKAGE="+packageName)
}
mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
@@ -214,11 +230,11 @@ func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibM
Rule: manifestMergerRule,
Description: "merge manifest",
Input: manifest,
- Implicits: staticLibManifests,
+ Implicits: params.staticLibManifests,
Output: mergedManifest,
Args: map[string]string{
- "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "),
- "args": args,
+ "libs": android.JoinWithPrefix(params.staticLibManifests.Strings(), "--libs "),
+ "args": strings.Join(args, " "),
},
})
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
new file mode 100644
index 000000000..7c9188462
--- /dev/null
+++ b/java/android_manifest_test.go
@@ -0,0 +1,135 @@
+// Copyright 2023 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 (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestManifestMerger(t *testing.T) {
+ bp := `
+ android_app {
+ name: "app",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ resource_dirs: ["app/res"],
+ manifest: "app/AndroidManifest.xml",
+ additional_manifests: ["app/AndroidManifest2.xml"],
+ static_libs: ["direct", "direct_import"],
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ additional_manifests: ["direct/AndroidManifest2.xml"],
+ static_libs: ["transitive", "transitive_import"],
+ }
+
+ android_library {
+ name: "transitive",
+ sdk_version: "current",
+ srcs: ["transitive/transitive.java"],
+ resource_dirs: ["transitive/res"],
+ manifest: "transitive/AndroidManifest.xml",
+ additional_manifests: ["transitive/AndroidManifest2.xml"],
+ }
+
+ android_library_import {
+ name: "direct_import",
+ sdk_version: "current",
+ aars: ["direct_import.aar"],
+ static_libs: ["direct_import_dep"],
+ }
+
+ android_library_import {
+ name: "direct_import_dep",
+ sdk_version: "current",
+ aars: ["direct_import_dep.aar"],
+ }
+
+ android_library_import {
+ name: "transitive_import",
+ sdk_version: "current",
+ aars: ["transitive_import.aar"],
+ static_libs: ["transitive_import_dep"],
+ }
+
+ android_library_import {
+ name: "transitive_import_dep",
+ sdk_version: "current",
+ aars: ["transitive_import_dep.aar"],
+ }
+ `
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
+
+ manifestMergerRule := result.ModuleForTests("app", "android_common").Rule("manifestMerger")
+ android.AssertPathRelativeToTopEquals(t, "main manifest",
+ "out/soong/.intermediates/app/android_common/manifest_fixer/AndroidManifest.xml",
+ manifestMergerRule.Input)
+ android.AssertPathsRelativeToTopEquals(t, "lib manifests",
+ []string{
+ "app/AndroidManifest2.xml",
+ "out/soong/.intermediates/direct/android_common/manifest_fixer/AndroidManifest.xml",
+ "direct/AndroidManifest2.xml",
+ "out/soong/.intermediates/transitive/android_common/manifest_fixer/AndroidManifest.xml",
+ "transitive/AndroidManifest2.xml",
+ "out/soong/.intermediates/transitive_import/android_common/aar/AndroidManifest.xml",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/AndroidManifest.xml",
+ "out/soong/.intermediates/direct_import/android_common/aar/AndroidManifest.xml",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/AndroidManifest.xml",
+ },
+ manifestMergerRule.Implicits)
+}
+
+func TestManifestValuesApplicationIdSetsPackageName(t *testing.T) {
+ bp := `
+ android_test {
+ name: "test",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ manifest: "test/AndroidManifest.xml",
+ additional_manifests: ["test/AndroidManifest2.xml"],
+ static_libs: ["direct"],
+ test_suites: ["device-tests"],
+ manifest_values: {
+ applicationId: "new_package_name"
+ },
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ additional_manifests: ["direct/AndroidManifest2.xml"],
+ }
+
+ `
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
+
+ manifestMergerRule := result.ModuleForTests("test", "android_common").Rule("manifestMerger")
+ android.AssertStringMatches(t,
+ "manifest merger args",
+ manifestMergerRule.Args["args"],
+ "--property PACKAGE=new_package_name")
+}
diff --git a/java/android_resources.go b/java/android_resources.go
index 8c5908f69..038a260d9 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -21,14 +21,6 @@ import (
"android/soong/android"
)
-func init() {
- registerOverlayBuildComponents(android.InitRegistrationContext)
-}
-
-func registerOverlayBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
-}
-
var androidResourceIgnoreFilenames = []string{
".svn",
".git",
@@ -84,7 +76,38 @@ type globbedResourceDir struct {
func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
rroDirs []rroDir) {
- overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
+ overlayData := ctx.Config().Once(overlayDataKey, func() interface{} {
+ var overlayData []overlayGlobResult
+
+ appendOverlayData := func(overlayDirs []string, t overlayType) {
+ for i := range overlayDirs {
+ // Iterate backwards through the list of overlay directories so that the later, lower-priority
+ // directories in the list show up earlier in the command line to aapt2.
+ overlay := overlayDirs[len(overlayDirs)-1-i]
+ var result overlayGlobResult
+ result.dir = overlay
+ result.overlayType = t
+
+ files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
+ if err != nil {
+ ctx.ModuleErrorf("failed to glob resource dir %q: %s", overlay, err.Error())
+ continue
+ }
+ var paths android.Paths
+ for _, f := range files {
+ if !strings.HasSuffix(f, "/") {
+ paths = append(paths, android.PathForSource(ctx, f))
+ }
+ }
+ result.paths = android.PathsToDirectorySortedPaths(paths)
+ overlayData = append(overlayData, result)
+ }
+ }
+
+ appendOverlayData(ctx.Config().DeviceResourceOverlays(), device)
+ appendOverlayData(ctx.Config().ProductResourceOverlays(), product)
+ return overlayData
+ }).([]overlayGlobResult)
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
rroEnabled := a.IsRROEnforced(ctx)
@@ -110,44 +133,3 @@ func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (
return res, rroDirs
}
-
-func OverlaySingletonFactory() android.Singleton {
- return overlaySingleton{}
-}
-
-type overlaySingleton struct{}
-
-func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var overlayData []overlayGlobResult
-
- appendOverlayData := func(overlayDirs []string, t overlayType) {
- for i := range overlayDirs {
- // Iterate backwards through the list of overlay directories so that the later, lower-priority
- // directories in the list show up earlier in the command line to aapt2.
- overlay := overlayDirs[len(overlayDirs)-1-i]
- var result overlayGlobResult
- result.dir = overlay
- result.overlayType = t
-
- files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
- if err != nil {
- ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
- continue
- }
- var paths android.Paths
- for _, f := range files {
- if !strings.HasSuffix(f, "/") {
- paths = append(paths, android.PathForSource(ctx, f))
- }
- }
- result.paths = android.PathsToDirectorySortedPaths(paths)
- overlayData = append(overlayData, result)
- }
- }
-
- appendOverlayData(ctx.Config().DeviceResourceOverlays(), device)
- appendOverlayData(ctx.Config().ProductResourceOverlays(), product)
- ctx.Config().Once(overlayDataKey, func() interface{} {
- return overlayData
- })
-}
diff --git a/java/androidmk.go b/java/androidmk.go
index 9c21633fb..a1bc90494 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -17,9 +17,10 @@ package java
import (
"fmt"
"io"
- "strings"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
@@ -79,6 +80,9 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
} else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
// Platform variant. If not available for the platform, we don't need Make module.
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
+ } else if proptools.Bool(library.properties.Headers_only) {
+ // If generating headers only then don't expose to Make.
+ entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
} else {
entriesList = append(entriesList, android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
@@ -87,11 +91,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if len(library.logtagsSrcs) > 0 {
- var logtags []string
- for _, l := range library.logtagsSrcs {
- logtags = append(logtags, l.Rel())
- }
- entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
+ entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", library.logtagsSrcs.Strings()...)
}
if library.installFile == nil {
@@ -200,26 +200,24 @@ func (j *TestHelperLibrary) AndroidMkEntries() []android.AndroidMkEntries {
func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
if prebuilt.hideApexVariantFromMake {
- // For a library imported from a prebuilt APEX, we don't need a Make module for itself, as we
- // don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
- // is preopted.
- dexpreoptEntries := prebuilt.dexpreopter.AndroidMkEntriesForApex()
- return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
+ return []android.AndroidMkEntries{}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Class: "JAVA_LIBRARIES",
+ OverrideName: prebuilt.BaseModuleName(),
+ OutputFile: android.OptionalPathForPath(prebuilt.combinedImplementationFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
if prebuilt.dexJarFile.IsSet() {
entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path())
}
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedHeaderFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedImplementationFile)
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -244,6 +242,7 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
}
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -257,18 +256,20 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.implementationJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.headerJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.implementationJarFile)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
+ entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackagesFile)
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -331,15 +332,23 @@ 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.
entries.SetString("LOCAL_MODULE", app.installApkName)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall)
+ if app.headerJarFile != nil {
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", app.headerJarFile)
+ }
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage)
if app.dexJarFile.IsSet() {
entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile.Path())
@@ -368,8 +377,13 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
filterRRO := func(filter overlayType) android.Paths {
var paths android.Paths
- for _, d := range app.rroDirs {
+ 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)
}
}
@@ -399,22 +413,11 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
} else {
+ var names []string
for _, jniLib := range app.jniLibs {
- entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
- var partitionTag string
-
- // Mimic the creation of partition_tag in build/make,
- // which defaults to an empty string when the partition is system.
- // Otherwise, capitalize with a leading _
- if jniLib.partition == "system" {
- partitionTag = ""
- } else {
- split := strings.Split(jniLib.partition, "/")
- partitionTag = "_" + strings.ToUpper(split[len(split)-1])
- }
- entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(),
- jniLib.name+":"+partitionTag)
+ names = append(names, jniLib.name)
}
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", names...)
}
if len(app.jniCoverageOutputs) > 0 {
@@ -432,6 +435,8 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
}
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
+
+ entries.AddStrings("LOCAL_SOONG_LOGTAGS_FILES", app.logtagsSrcs.Strings()...)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -450,11 +455,6 @@ func (a *AndroidApp) getOverriddenPackages() []string {
if len(a.overridableAppProperties.Overrides) > 0 {
overridden = append(overridden, a.overridableAppProperties.Overrides...)
}
- // When APK name is overridden via PRODUCT_PACKAGE_NAME_OVERRIDES
- // ensure that the original name is overridden.
- if a.Stem() != a.installApkName {
- overridden = append(overridden, a.Stem())
- }
return overridden
}
@@ -508,9 +508,10 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
}
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.exportPackage)
+ entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", a.transitiveAaptResourcePackagesFile)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", a.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
- entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...)
+ entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.combinedExportedProguardFlagsFile)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
})
@@ -527,8 +528,8 @@ func (jd *Javadoc) AndroidMkEntries() []android.AndroidMkEntries {
if BoolDefault(jd.properties.Installable, true) {
entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", jd.docZip)
}
- if jd.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.stubsSrcJar)
+ if jd.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.exportableStubsSrcJar)
}
},
},
@@ -566,7 +567,7 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
outputFile = android.OptionalPathForPath(dstubs.apiFile)
}
if !outputFile.Valid() {
- outputFile = android.OptionalPathForPath(dstubs.apiVersionsXml)
+ outputFile = android.OptionalPathForPath(dstubs.everythingArtifacts.apiVersionsXml)
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
@@ -574,17 +575,17 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- if dstubs.Javadoc.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.stubsSrcJar)
+ if dstubs.Javadoc.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.exportableStubsSrcJar)
}
- if dstubs.apiVersionsXml != nil {
- entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.apiVersionsXml)
+ if dstubs.everythingArtifacts.apiVersionsXml != nil {
+ entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.exportableArtifacts.apiVersionsXml)
}
- if dstubs.annotationsZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.annotationsZip)
+ if dstubs.everythingArtifacts.annotationsZip != nil {
+ entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.exportableArtifacts.annotationsZip)
}
- if dstubs.metadataZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
+ if dstubs.everythingArtifacts.metadataZip != nil {
+ entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.exportableArtifacts.metadataZip)
}
},
},
@@ -669,9 +670,10 @@ func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
return nil
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "APPS",
- OutputFile: android.OptionalPathForPath(a.outputFile),
- Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
+ Class: "APPS",
+ OutputFile: android.OptionalPathForPath(a.outputFile),
+ OverrideName: a.BaseModuleName(), // TODO (spandandas): Add a test
+ Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", a.Privileged())
@@ -684,6 +686,7 @@ func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
if Bool(a.properties.Export_package_resources) {
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
}
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -717,6 +720,7 @@ func (r *RuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_CERTIFICATE", r.certificate.AndroidMkString())
entries.SetPath("LOCAL_MODULE_PATH", r.installDir)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", r.properties.Overrides...)
+ // TODO: LOCAL_ACONFIG_FILES -- Might eventually need aconfig flags?
},
},
}}
@@ -734,6 +738,7 @@ func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_APK_SET_INSTALL_FILE", apkSet.PackedAdditionalOutputs())
entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts -- Both declarations and values
},
},
},
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 1232cd1ee..243a2791e 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -20,8 +20,6 @@ import (
"android/soong/android"
"android/soong/cc"
-
- "github.com/google/blueprint/proptools"
)
func TestRequired(t *testing.T) {
@@ -161,8 +159,8 @@ func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) {
moduleName string
expected []string
}{
- {"foo-shared_library", []string{"foo-shared_library.xml"}},
- {"foo-no_shared_library", nil},
+ {"foo-shared_library", []string{"foo-shared_library.impl", "foo-shared_library.xml"}},
+ {"foo-no_shared_library", []string{"foo-no_shared_library.impl"}},
}
for _, tc := range testCases {
mod := result.ModuleForTests(tc.moduleName, "android_common").Module()
@@ -256,148 +254,50 @@ func TestGetOverriddenPackages(t *testing.T) {
}
}
-func TestJniPartition(t *testing.T) {
- bp := `
- cc_library {
- name: "libjni_system",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- }
-
- cc_library {
- name: "libjni_system_ext",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- system_ext_specific: true,
- }
-
- cc_library {
- name: "libjni_odm",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- device_specific: true,
- }
-
- cc_library {
- name: "libjni_product",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- product_specific: true,
- }
-
- cc_library {
- name: "libjni_vendor",
- system_shared_libs: [],
- sdk_version: "current",
- stl: "none",
- soc_specific: true,
- }
-
- android_app {
- name: "test_app_system_jni_system",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system"],
- }
-
+func TestJniAsRequiredDeps(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ cc.PrepareForTestWithCcDefaultModules,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(t, `
android_app {
- name: "test_app_system_jni_system_ext",
- privileged: true,
+ name: "app",
+ jni_libs: ["libjni"],
platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system_ext"],
}
android_app {
- name: "test_app_system_ext_jni_system",
- privileged: true,
+ name: "app_embedded",
+ jni_libs: ["libjni"],
platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system"],
- system_ext_specific: true
- }
-
- android_app {
- name: "test_app_system_ext_jni_system_ext",
- sdk_version: "core_platform",
- jni_libs: ["libjni_system_ext"],
- system_ext_specific: true
+ use_embedded_native_libs: true,
}
- android_app {
- name: "test_app_product_jni_product",
- sdk_version: "core_platform",
- jni_libs: ["libjni_product"],
- product_specific: true
- }
-
- android_app {
- name: "test_app_vendor_jni_odm",
- sdk_version: "core_platform",
- jni_libs: ["libjni_odm"],
- soc_specific: true
+ cc_library {
+ name: "libjni",
+ system_shared_libs: [],
+ stl: "none",
}
+ `)
- android_app {
- name: "test_app_odm_jni_vendor",
- sdk_version: "core_platform",
- jni_libs: ["libjni_vendor"],
- device_specific: true
- }
- android_app {
- name: "test_app_system_jni_multiple",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system", "libjni_system_ext"],
- }
- android_app {
- name: "test_app_vendor_jni_multiple",
- sdk_version: "core_platform",
- jni_libs: ["libjni_odm", "libjni_vendor"],
- soc_specific: true
- }
- `
- arch := "arm64"
- ctx := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- cc.PrepareForTestWithCcDefaultModules,
- android.PrepareForTestWithAndroidMk,
- android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.DeviceArch = proptools.StringPtr(arch)
- }),
- ).
- RunTestWithBp(t, bp)
- testCases := []struct {
- name string
- partitionNames []string
- partitionTags []string
+ testcases := []struct {
+ name string
+ expected []string
}{
- {"test_app_system_jni_system", []string{"libjni_system"}, []string{""}},
- {"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
- {"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}},
- {"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
- {"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}},
- {"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}},
- {"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}},
- {"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}},
- {"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}},
+ {
+ name: "app",
+ expected: []string{"libjni"},
+ },
+ {
+ name: "app_embedded",
+ expected: nil,
+ },
}
- for _, test := range testCases {
- t.Run(test.name, func(t *testing.T) {
- mod := ctx.ModuleForTests(test.name, "android_common").Module()
- entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
- for i := range test.partitionNames {
- actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i]
- expected := test.partitionNames[i] + ":" + test.partitionTags[i]
- android.AssertStringEquals(t, "Expected and actual differ", expected, actual)
- }
- })
+ for _, tc := range testcases {
+ mod := ctx.ModuleForTests(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 706f99a83..19dc8d5d1 100755..100644
--- a/java/app.go
+++ b/java/app.go
@@ -18,23 +18,42 @@ package java
// related module types, including their override variants.
import (
+ "fmt"
"path/filepath"
"strings"
+ "android/soong/testing"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc"
"android/soong/dexpreopt"
+ "android/soong/genrule"
"android/soong/tradefed"
)
func init() {
RegisterAppBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("ModifyAllowlistCmd", "modify_permissions_allowlist")
}
+var (
+ modifyAllowlist = pctx.AndroidStaticRule("modifyAllowlist",
+ blueprint.RuleParams{
+ Command: "${ModifyAllowlistCmd} $in $packageName $out",
+ CommandDeps: []string{"${ModifyAllowlistCmd}"},
+ }, "packageName")
+)
+
+type FlagsPackages struct {
+ // Paths to the aconfig dump output text files that are consumed by aapt2
+ AconfigTextFiles android.Paths
+}
+
+var FlagsPackagesProvider = blueprint.NewProvider[FlagsPackages]()
+
func RegisterAppBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_app", AndroidAppFactory)
ctx.RegisterModuleType("android_test", AndroidTestFactory)
@@ -115,6 +134,19 @@ type appProperties struct {
// Prefer using other specific properties if build behaviour must be changed; avoid using this
// flag for anything but neverallow rules (unless the behaviour change is invisible to owners).
Updatable *bool
+
+ // 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
@@ -147,7 +179,6 @@ type overridableAppProperties struct {
}
type AndroidApp struct {
- android.BazelModuleBase
Library
aapt
android.OverridableModuleBase
@@ -179,18 +210,16 @@ type AndroidApp struct {
android.ApexBundleDepsInfo
javaApiUsedByOutputFile android.ModuleOutPath
+
+ privAppAllowlist android.OptionalPath
}
func (a *AndroidApp) IsInstallable() bool {
return Bool(a.properties.Installable)
}
-func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
- return nil
-}
-
-func (a *AndroidApp) ExportedStaticPackages() android.Paths {
- return nil
+func (a *AndroidApp) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.aapt.resourcesNodesDepSet
}
func (a *AndroidApp) OutputFile() android.Path {
@@ -205,6 +234,10 @@ func (a *AndroidApp) JniCoverageOutputs() android.Paths {
return a.jniCoverageOutputs
}
+func (a *AndroidApp) PrivAppAllowlist() android.OptionalPath {
+ return a.privAppAllowlist
+}
+
var _ AndroidLibraryDependency = (*AndroidApp)(nil)
type Certificate struct {
@@ -223,13 +256,13 @@ func (c Certificate) AndroidMkString() string {
}
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
- a.Module.deps(ctx)
-
if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion(ctx).Specified() {
ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
}
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
+ a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
+ a.Module.deps(ctx)
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
@@ -248,19 +281,41 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
variation := append(jniTarget.Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"})
- // If the app builds against an Android SDK use the SDK variant of JNI dependencies
- // unless jni_uses_platform_apis is set.
- // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already
- // have stable APIs through the VNDK.
- if (usesSDK && !a.RequiresStableAPIs(ctx) &&
- !Bool(a.appProperties.Jni_uses_platform_apis)) ||
- Bool(a.appProperties.Jni_uses_sdk_apis) {
+ // Test whether to use the SDK variant or the non-SDK variant of JNI dependencies.
+ // Many factors are considered here.
+ // 1. Basically, the selection follows whether the app has sdk_version set or not.
+ jniUsesSdkVariant := usesSDK
+ // 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it
+ if Bool(a.appProperties.Jni_uses_sdk_apis) {
+ jniUsesSdkVariant = true
+ }
+ if Bool(a.appProperties.Jni_uses_platform_apis) {
+ jniUsesSdkVariant = false
+ }
+ // 3. Then the use of SDK variant is again prohibited for the following cases:
+ // 3.1. the app is shipped on unbundled partitions like vendor. Since the entire
+ // partition (not only the app) is considered unbudled, there's no need to use the
+ // SDK variant.
+ // 3.2. the app doesn't support embedding the JNI libs
+ if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) {
+ jniUsesSdkVariant = false
+ }
+ if jniUsesSdkVariant {
variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
}
- ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
- }
- a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
+ // Use the installable dep tag when the JNIs are not embedded
+ var tag dependencyTag
+ if a.shouldEmbedJnis(ctx) {
+ tag = jniLibTag
+ } else {
+ tag = jniInstallTag
+ }
+ ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+ }
+ for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -269,6 +324,16 @@ func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+ if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) {
+ // There are a few uids that are explicitly considered privileged regardless of their
+ // app's location. Bluetooth is one such app. It should arguably be moved to priv-app,
+ // but for now, allow it not to be in priv-app.
+ privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth"
+ if !privilegedBecauseOfUid {
+ ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)")
+ }
+ }
+
for _, cert := range a.appProperties.Additional_certificates {
cert = android.SrcIsModule(cert)
if cert != "" {
@@ -280,12 +345,52 @@ func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato
}
}
+// TODO(b/156476221): Remove this allowlist
+var (
+ missingMinSdkVersionMtsAllowlist = []string{
+ "CellBroadcastReceiverGoogleUnitTests",
+ "CellBroadcastReceiverUnitTests",
+ "CtsBatterySavingTestCases",
+ "CtsDeviceAndProfileOwnerApp23",
+ "CtsDeviceAndProfileOwnerApp30",
+ "CtsIntentSenderApp",
+ "CtsJobSchedulerTestCases",
+ "CtsMimeMapTestCases",
+ "CtsTareTestCases",
+ "LibStatsPullTests",
+ "MediaProviderClientTests",
+ "TeleServiceTests",
+ "TestExternalImsServiceApp",
+ "TestSmsRetrieverApp",
+ "TetheringPrivilegedTests",
+ }
+)
+
+func checkMinSdkVersionMts(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
+ if includedInMts(ctx.Module()) && !minSdkVersion.Specified() && !android.InList(ctx.ModuleName(), missingMinSdkVersionMtsAllowlist) {
+ ctx.PropertyErrorf("min_sdk_version", "min_sdk_version is a required property for tests included in MTS")
+ }
+}
+
func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx))
+ applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId
+ if applicationId != nil {
+ if a.overridableAppProperties.Package_name != nil {
+ ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
+ }
+ a.aapt.manifestValues.applicationId = *applicationId
+ }
a.generateAndroidBuildActions(ctx)
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: true,
+ })
+
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkAppSdkVersions(ctx)
+ a.checkEmbedJnis(ctx)
a.generateAndroidBuildActions(ctx)
a.generateJavaUsedByApex(ctx)
}
@@ -295,7 +400,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if !a.SdkVersion(ctx).Stable() {
ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.SdkVersion(ctx))
}
- if String(a.deviceProperties.Min_sdk_version) == "" {
+ if String(a.overridableProperties.Min_sdk_version) == "" {
ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
}
@@ -319,6 +424,17 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
a.checkSdkVersions(ctx)
}
+// Ensures that use_embedded_native_libs are set for apk-in-apex
+func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ apkInApex := !apexInfo.IsForPlatform()
+ hasJnis := len(a.appProperties.Jni_libs) > 0
+
+ if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
+ ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
+ }
+}
+
// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it.
// This check is enforced for "updatable" APKs (including APK-in-APEX).
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
@@ -349,7 +465,7 @@ func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(ctx), err)
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
!apexInfo.IsForPlatform()
}
@@ -370,13 +486,13 @@ func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
return false
}
- return shouldUncompressDex(ctx, &a.dexpreopter)
+ return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}
func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
- !apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
+ Bool(a.appProperties.Updatable) ||
+ a.appProperties.AlwaysPackageNativeLibs
}
func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
@@ -396,6 +512,30 @@ func (a *AndroidApp) renameResourcesPackage() bool {
return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true)
}
+func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) {
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ switch tag {
+ case staticLibTag:
+ if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok {
+ aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...)
+ }
+
+ case aconfigDeclarationTag:
+ if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
+ aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+ "flags_packages property, but %s is not aconfig_declarations module type",
+ dep.Name(),
+ )
+ }
+ }
+ })
+
+ return android.FirstUniquePaths(aconfigTextFilePaths)
+}
+
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis)
if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule {
@@ -409,9 +549,11 @@ 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 {
- aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
+ characteristics := ctx.Config().ProductAAPTCharacteristics()
+ if !autogenerateRRO && !hasProduct && len(characteristics) > 0 && characteristics != "default" {
+ aaptLinkFlags = append(aaptLinkFlags, "--product", characteristics)
}
if !Bool(a.aaptProperties.Aapt_include_all_resources) {
@@ -441,27 +583,59 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
a.aapt.splitNames = a.appProperties.Package_splits
a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent)
if a.Updatable() {
- a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
+ if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" {
+ a.aapt.defaultManifestVersion = override
+ } else {
+ a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
+ }
}
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts,
- a.usesLibraryProperties.Exclude_uses_libs, a.enforceDefaultTargetSdkVersion(), aaptLinkFlags...)
+
+ // Use non final ids if we are doing optimized shrinking and are using R8.
+ nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled()
+
+ aconfigTextFilePaths := getAconfigFilePaths(ctx)
+
+ a.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: android.SdkContext(a),
+ classLoaderContexts: a.classLoaderContexts,
+ excludedLibs: a.usesLibraryProperties.Exclude_uses_libs,
+ enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
+ forceNonFinalResourceIDs: nonFinalIds,
+ extraLinkFlags: aaptLinkFlags,
+ aconfigTextFiles: aconfigTextFilePaths,
+ usesLibrary: &a.usesLibrary,
+ },
+ )
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
+
+ android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
+ AconfigTextFiles: aconfigTextFilePaths,
+ })
}
func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
var staticLibProguardFlagFiles android.Paths
ctx.VisitDirectDeps(func(m android.Module) {
- if lib, ok := m.(LibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
- staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+ depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
+ staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...)
+ if ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.ProguardFlagsFiles.ToList()...)
}
})
staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
+ a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
+ if !(a.dexProperties.optimizedResourceShrinkingEnabled(ctx)) {
+ // When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
+ // live for code references and (transitively) mark these as live.
+ // In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
+ // dead code alive)
+ a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
+ }
}
func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
@@ -478,7 +652,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 {
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path) {
a.dexpreopter.installPath = a.installPath(ctx)
a.dexpreopter.isApp = true
if a.dexProperties.Uncompress_dex == nil {
@@ -491,11 +665,40 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.manifestFile = a.mergedManifestFile
a.dexpreopter.preventInstall = a.appProperties.PreventInstall
+ var packageResources = a.exportPackage
+
if ctx.ModuleName() != "framework-res" {
- a.Module.compile(ctx, a.aaptSrcJar)
+ if a.dexProperties.resourceShrinkingEnabled(ctx) {
+ protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
+ aapt2Convert(ctx, protoFile, packageResources, "proto")
+ a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
+ }
+
+ var extraSrcJars android.Paths
+ var extraClasspathJars android.Paths
+ var extraCombinedJars android.Paths
+ if a.useResourceProcessorBusyBox(ctx) {
+ // When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already
+ // created R.class files that provide IDs for resources in busybox/R.jar. Pass that file in the
+ // classpath when compiling everything else, and add it to the final classes jar.
+ extraClasspathJars = android.Paths{a.aapt.rJar}
+ extraCombinedJars = android.Paths{a.aapt.rJar}
+ } else {
+ // When building an app without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
+ // R.java files for the app's package and the packages from all transitive static android_library
+ // dependencies. Compile the srcjar alongside the rest of the sources.
+ extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
+ }
+
+ a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
+ if a.dexProperties.resourceShrinkingEnabled(ctx) {
+ binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
+ aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
+ packageResources = binaryResources
+ }
}
- return a.dexJarFile.PathOrNil()
+ return a.dexJarFile.PathOrNil(), packageResources
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
@@ -591,7 +794,6 @@ func processMainCert(m android.ModuleBase, certPropValue string, certificates []
}
}
-
return mainCertificate, certificates
}
@@ -599,18 +801,57 @@ func (a *AndroidApp) InstallApkName() string {
return a.installApkName
}
+func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.Path {
+ if a.appProperties.Privapp_allowlist == nil {
+ return nil
+ }
+
+ isOverrideApp := a.GetOverriddenBy() != ""
+ if !isOverrideApp {
+ // if this is not an override, we don't need to rewrite the existing privapp allowlist
+ return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist)
+ }
+
+ if a.overridableAppProperties.Package_name == nil {
+ ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist")
+ }
+
+ packageName := *a.overridableAppProperties.Package_name
+ fileName := "privapp_allowlist_" + packageName + ".xml"
+ outPath := android.PathForModuleOut(ctx, fileName).OutputPath
+ ctx.Build(pctx, android.BuildParams{
+ Rule: modifyAllowlist,
+ Input: android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist),
+ Output: outPath,
+ Args: map[string]string{
+ "packageName": packageName,
+ },
+ })
+ return &outPath
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
- if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
}
a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
+ // Unlike installApkName, a.stem should respect base module name for override_android_app.
+ // Therefore, use ctx.ModuleName() instead of a.Name().
+ a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
+
// Check if the install APK name needs to be overridden.
- a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Stem())
+ // Both android_app and override_android_app module are expected to possess
+ // its module bound apk path. However, override_android_app inherits ctx.ModuleName()
+ // from the base module. Therefore, use a.Name() which represents
+ // the module name for both android_app and override_android_app.
+ a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(
+ proptools.StringDefault(a.overridableProperties.Stem, a.Name()))
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
@@ -625,6 +866,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+ if a.usesLibrary.shouldDisableDexpreopt {
+ a.dexpreopter.disableDexpreopt()
+ }
var noticeAssetPath android.WritablePath
if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
@@ -643,22 +887,13 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
-
// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
a.usesLibrary.freezeEnforceUsesLibraries()
- // Add implicit SDK libraries to <uses-library> list.
- requiredUsesLibs, optionalUsesLibs := a.classLoaderContexts.UsesLibs()
- for _, usesLib := range requiredUsesLibs {
- a.usesLibrary.addLib(usesLib, false)
- }
- for _, usesLib := range optionalUsesLibs {
- a.usesLibrary.addLib(usesLib, true)
- }
-
// Check that the <uses-library> list is coherent with the manifest.
if a.usesLibrary.enforceUsesLibraries() {
- manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
+ manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(
+ ctx, a.mergedManifestFile, &a.classLoaderContexts)
apkDeps = append(apkDeps, manifestCheckFile)
}
@@ -669,9 +904,11 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.linter.resources = a.aapt.resourceFiles
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
- dexJarFile := a.dexBuildActions(ctx)
+ dexJarFile, packageResources := a.dexBuildActions(ctx)
- jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+ // 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)
+ jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion)
jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
if ctx.Failed() {
@@ -693,7 +930,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
}
rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, Bool(a.dexProperties.Optimize.Shrink_resources))
+ CreateAndSignAppPackage(ctx, packageFile, packageResources, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
a.outputFile = packageFile
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -722,7 +959,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
if v4SigningRequested {
v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
}
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, false)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -734,21 +971,68 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
a.bundleFile = bundleFile
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ allowlist := a.createPrivappAllowlist(ctx)
+ if allowlist != nil {
+ a.privAppAllowlist = android.OptionalPathForPath(allowlist)
+ }
// Install the app package.
- if (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() &&
- !a.appProperties.PreventInstall {
+ shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
+ if shouldInstallAppPackage {
+ if a.privAppAllowlist.Valid() {
+ allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions")
+ allowlistInstallFilename := a.installApkName + ".xml"
+ 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)
}
+ // If we don't embed jni libs, make sure that those are installed along with the
+ // app, and also place symlinks to the installed paths under the lib/<arch>
+ // directory of the app installation directory. ex:
+ // /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so
+ if !a.embeddedJniLibs {
+ for _, jniLib := range jniLibs {
+ archStr := jniLib.target.Arch.ArchType.String()
+ symlinkDir := a.installDir.Join(ctx, "lib", archStr)
+ for _, installedLib := range jniLib.installPaths {
+ // install the symlink itself
+ symlinkName := installedLib.Base()
+ symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib)
+ ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget)
+ }
+ }
+ }
ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
}
a.buildAppDependencyInfo(ctx)
+
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: a.BaseModuleName(),
+ isPrebuilt: false,
+ },
+ )
+
+ a.setOutputFiles(ctx)
+}
+
+func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) {
+ ctx.SetOutputFiles([]android.Path{a.proguardOptionsFile}, ".aapt.proguardOptionsFile")
+ if a.aaptSrcJar != nil {
+ ctx.SetOutputFiles([]android.Path{a.aaptSrcJar}, ".aapt.srcjar")
+ }
+ if a.rJar != nil {
+ ctx.SetOutputFiles([]android.Path{a.rJar}, ".aapt.jar")
+ }
+ ctx.SetOutputFiles([]android.Path{a.outputFile}, ".apk")
+ ctx.SetOutputFiles([]android.Path{a.exportPackage}, ".export-package.apk")
+ ctx.SetOutputFiles([]android.Path{a.aapt.manifestPath}, ".manifest.xml")
+ setOutputFiles(ctx, a.Library.Module)
}
type appDepsInterface interface {
@@ -761,15 +1045,39 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
shouldCollectRecursiveNativeDeps bool,
checkNativeSdkVersion bool) ([]jniLib, android.Paths, []Certificate) {
- var jniLibs []jniLib
- var prebuiltJniPackages android.Paths
- var certificates []Certificate
- seenModulePaths := make(map[string]bool)
-
if checkNativeSdkVersion {
checkNativeSdkVersion = app.SdkVersion(ctx).Specified() &&
app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
}
+ jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
+ checkNativeSdkVersion, func(dep cc.LinkableInterface) bool {
+ return !dep.IsNdk(ctx.Config()) && !dep.IsStubs()
+ })
+
+ var certificates []Certificate
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ otherName := ctx.OtherModuleName(module)
+ tag := ctx.OtherModuleDependencyTag(module)
+
+ if tag == certificateTag {
+ if dep, ok := module.(*AndroidAppCertificate); ok {
+ certificates = append(certificates, dep.Certificate)
+ } else {
+ ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
+ }
+ }
+ })
+ return jniLib, prebuiltJniPackages, certificates
+}
+
+func collectJniDeps(ctx android.ModuleContext,
+ shouldCollectRecursiveNativeDeps bool,
+ checkNativeSdkVersion bool,
+ filter func(cc.LinkableInterface) 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 {
otherName := ctx.OtherModuleName(module)
@@ -777,7 +1085,7 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
if dep, ok := module.(cc.LinkableInterface); ok {
- if dep.IsNdk(ctx.Config()) || dep.IsStubs() {
+ if filter != nil && !filter(dep) {
return false
}
@@ -801,6 +1109,7 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(),
partition: dep.Partition(),
+ installPaths: dep.FilesToInstall(),
})
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{otherName})
@@ -814,22 +1123,14 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
return shouldCollectRecursiveNativeDeps
}
- if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
}
- if tag == certificateTag {
- if dep, ok := module.(*AndroidAppCertificate); ok {
- certificates = append(certificates, dep.Certificate)
- } else {
- ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
- }
- }
-
return false
})
- return jniLibs, prebuiltJniPackages, certificates
+ return jniLibs, prebuiltJniPackages
}
func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
@@ -922,22 +1223,11 @@ func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.
return a.Library.DepIsInSameApex(ctx, dep)
}
-// For OutputFileProducer interface
-func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".aapt.srcjar":
- return []android.Path{a.aaptSrcJar}, nil
- case ".export-package.apk":
- return []android.Path{a.exportPackage}, nil
- }
- return a.Library.OutputFiles(tag)
-}
-
func (a *AndroidApp) Privileged() bool {
return Bool(a.appProperties.Privileged)
}
-func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+func (a *AndroidApp) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
}
@@ -953,12 +1243,26 @@ func (a *AndroidApp) EnableCoverageIfNeeded() {}
var _ cc.Coverage = (*AndroidApp)(nil)
+func (a *AndroidApp) IDEInfo(dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(dpInfo)
+ 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{}
module.Module.dexProperties.Optimize.EnabledByDefault = true
module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true)
+ module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
module.Module.properties.Instrument = true
module.Module.properties.Supports_static_instrumentation = true
@@ -968,7 +1272,8 @@ func AndroidAppFactory() android.Module {
module.AddProperties(
&module.aaptProperties,
&module.appProperties,
- &module.overridableAppProperties)
+ &module.overridableAppProperties,
+ &module.Library.sourceProperties)
module.usesLibrary.enforce = true
@@ -976,11 +1281,72 @@ func AndroidAppFactory() android.Module {
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
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", "aapt2"},
+ Out: []string{"AndroidManifest.xml"},
+ Srcs: []string{":" + a.Name() + "{.apk}"},
+ Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(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,
+ }
+ if !Bool(a.aaptProperties.Aapt_include_all_resources) {
+ for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+ rroProperties.Aaptflags = append(rroProperties.Aaptflags, "-c", aaptConfig)
+ }
+ }
+ ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties)
+ })
return module
}
+// A dictionary of values to be overridden in the manifest.
+type Manifest_values struct {
+ // Overrides the value of package_name in the manifest
+ ApplicationId *string
+}
+
type appTestProperties struct {
// The name of the android_app module that the tests will run against.
Instrumentation_for *string
@@ -990,6 +1356,8 @@ type appTestProperties struct {
// If specified, the mainline module package name in the test config is overwritten by it.
Mainline_package_name *string
+
+ Manifest_values Manifest_values
}
type AndroidTest struct {
@@ -1021,6 +1389,7 @@ func (a *AndroidTestHelperApp) includedInTestSuite(searchPrefix string) bool {
}
func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx))
var configs []tradefed.Config
if a.appTestProperties.Instrumentation_target_package != nil {
a.additionalAaptFlags = append(a.additionalAaptFlags,
@@ -1032,6 +1401,13 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
}
}
+ applicationId := a.appTestProperties.Manifest_values.ApplicationId
+ if applicationId != nil {
+ if a.overridableAppProperties.Package_name != nil {
+ ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
+ }
+ a.aapt.manifestValues.applicationId = *applicationId
+ }
a.generateAndroidBuildActions(ctx)
for _, module := range a.testProperties.Test_mainline_modules {
@@ -1043,6 +1419,22 @@ 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)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
+ InstalledFiles: a.data,
+ OutputFile: a.OutputFile(),
+ TestConfig: a.testConfig,
+ HostRequiredModuleNames: a.HostRequiredModuleNames(),
+ TestSuites: a.testProperties.Test_suites,
+ IsHost: false,
+ LocalCertificate: a.certificate.AndroidMkString(),
+ IsUnitTest: Bool(a.testProperties.Test_options.Unit_test),
+ })
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: true,
+ TopLevelTarget: true,
+ })
+
}
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
@@ -1119,6 +1511,7 @@ func AndroidTestFactory() android.Module {
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
+
return module
}
@@ -1134,6 +1527,8 @@ type appTestHelperAppProperties struct {
// Install the test into a folder named for the module in all test suites.
Per_testcase_directory *bool
+
+ Manifest_values Manifest_values
}
type AndroidTestHelperApp struct {
@@ -1176,7 +1571,6 @@ func AndroidTestHelperAppFactory() android.Module {
type AndroidAppCertificate struct {
android.ModuleBase
- android.BazelModuleBase
properties AndroidAppCertificateProperties
Certificate Certificate
@@ -1193,7 +1587,6 @@ func AndroidAppCertificateFactory() android.Module {
module := &AndroidAppCertificate{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
@@ -1220,7 +1613,7 @@ func (i *OverrideAndroidApp) GenerateAndroidBuildActions(_ android.ModuleContext
func OverrideAndroidAppModuleFactory() android.Module {
m := &OverrideAndroidApp{}
m.AddProperties(
- &OverridableDeviceProperties{},
+ &OverridableProperties{},
&overridableAppProperties{},
)
@@ -1234,9 +1627,13 @@ type OverrideAndroidTest struct {
android.OverrideModuleBase
}
-func (i *OverrideAndroidTest) GenerateAndroidBuildActions(_ android.ModuleContext) {
+func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: true,
+ TopLevelTarget: true,
+ })
}
// override_android_test is used to create an android_app module based on another android_test by overriding
@@ -1284,6 +1681,9 @@ type UsesLibraryProperties struct {
// provide the android.test.base statically and use jarjar to rename them so they do not collide
// with the classes provided by the android.test.base library.
Exclude_uses_libs []string
+
+ // The module names of optional uses-library libraries that are missing from the source tree.
+ Missing_optional_uses_libs []string `blueprint:"mutated"`
}
// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
@@ -1295,22 +1695,16 @@ type usesLibrary struct {
// Whether to enforce verify_uses_library check.
enforce bool
-}
-func (u *usesLibrary) addLib(lib string, optional bool) {
- if !android.InList(lib, u.usesLibraryProperties.Uses_libs) && !android.InList(lib, u.usesLibraryProperties.Optional_uses_libs) {
- if optional {
- u.usesLibraryProperties.Optional_uses_libs = append(u.usesLibraryProperties.Optional_uses_libs, lib)
- } else {
- u.usesLibraryProperties.Uses_libs = append(u.usesLibraryProperties.Uses_libs, lib)
- }
- }
+ // Whether dexpreopt should be disabled
+ shouldDisableDexpreopt bool
}
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) {
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
- ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
+ presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx)
+ ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...)
// Only add these extra dependencies if the module is an app that depends on framework
// libs. This avoids creating a cyclic dependency:
// e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
@@ -1321,26 +1715,24 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo
ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
+ _, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs, presentOptionalUsesLibs)
+ u.usesLibraryProperties.Missing_optional_uses_libs = diff
} else {
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
}
}
-// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
-// build.
+// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree.
func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
- optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
- return optionalUsesLibs
-}
-
-// Helper function to replace string in a list.
-func replaceInList(list []string, oldstr, newstr string) {
- for i, str := range list {
- if str == oldstr {
- list[i] = newstr
+ optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs, func(s string) bool {
+ exists := ctx.OtherModuleExists(s)
+ if !exists && !android.InList(ctx.ModuleName(), ctx.Config().BuildWarningBadOptionalUsesLibsAllowlist()) {
+ fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s)
}
- }
+ return exists
+ })
+ return optionalUsesLibs
}
// Returns a map of module names of shared library dependencies to the paths to their dex jars on
@@ -1371,18 +1763,22 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
}
}
+ // Skip java_sdk_library dependencies that provide stubs, but not an implementation.
+ // This will be restricted to optional_uses_libs
+ if sdklib, ok := m.(SdkLibraryDependency); ok {
+ if tag == usesLibOptTag && sdklib.DexJarBuildPath(ctx).PathOrNil() == nil {
+ u.shouldDisableDexpreopt = true
+ return
+ }
+ }
+
if lib, ok := m.(UsesLibraryDependency); ok {
libName := dep
if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
libName = *ulib.ProvidesUsesLib()
- // Replace module name with library name in `uses_libs`/`optional_uses_libs` in
- // order to pass verify_uses_libraries check (which compares these properties
- // against library names written in the manifest).
- replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
- replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
- lib.DexJarBuildPath().PathOrNil(), lib.DexJarInstallPath(),
+ lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
@@ -1413,7 +1809,7 @@ func (u *usesLibrary) freezeEnforceUsesLibraries() {
// an APK with the manifest embedded in it (manifest_check will know which one it is by the file
// extension: APKs are supposed to end with '.apk').
func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile android.Path,
- outputFile android.WritablePath) android.Path {
+ outputFile android.WritablePath, classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
@@ -1422,7 +1818,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
}
@@ -1441,140 +1837,37 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a
cmd.Flag("--enforce-uses-libraries-relax")
}
- for _, lib := range u.usesLibraryProperties.Uses_libs {
+ requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
+ for _, lib := range requiredUsesLibs {
cmd.FlagWithArg("--uses-library ", lib)
}
-
- for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
+ for _, lib := range optionalUsesLibs {
cmd.FlagWithArg("--optional-uses-library ", lib)
}
+ // Also add missing optional uses libs, as the manifest check expects them.
+ // Note that what we add here are the module names of those missing libs, not library names, while
+ // the manifest check actually expects library names. However, the case where a library is missing
+ // and the module name != the library name is too rare for us to handle.
+ for _, lib := range u.usesLibraryProperties.Missing_optional_uses_libs {
+ cmd.FlagWithArg("--missing-optional-uses-library ", lib)
+ }
+
rule.Build("verify_uses_libraries", "verify <uses-library>")
return outputFile
}
// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against
// the build system and returns the path to a copy of the manifest.
-func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
+func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path,
+ classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
- return u.verifyUsesLibraries(ctx, manifest, outputFile)
+ return u.verifyUsesLibraries(ctx, manifest, outputFile, classLoaderContexts)
}
// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build
// system and returns the path to a copy of the APK.
-func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
- u.verifyUsesLibraries(ctx, apk, nil) // for APKs manifest_check does not write output file
- outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
- return outputFile
-}
-
-// For Bazel / bp2build
-
-type bazelAndroidAppCertificateAttributes struct {
- Certificate string
-}
-
-func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- androidAppCertificateBp2Build(ctx, m)
-}
-
-func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) {
- var certificate string
- if module.properties.Certificate != nil {
- certificate = *module.properties.Certificate
- }
-
- attrs := &bazelAndroidAppCertificateAttributes{
- Certificate: certificate,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "android_app_certificate",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
-}
-
-type manifestValueAttribute struct {
- MinSdkVersion *string
-}
-
-type bazelAndroidAppAttributes struct {
- *javaCommonAttributes
- *bazelAapt
- Deps bazel.LabelListAttribute
- Custom_package *string
- Certificate bazel.LabelAttribute
- Certificate_name bazel.StringAttribute
- Manifest_values *manifestValueAttribute
-}
-
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2BuildInfo := a.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
-
- aapt := a.convertAaptAttrsWithBp2Build(ctx)
-
- certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
-
- manifestValues := &manifestValueAttribute{}
- // TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build
- // MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
- minSdkVersion := a.MinSdkVersion(ctx)
- if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
- minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx)
- if err == nil {
- manifestValues.MinSdkVersion = &minSdkStr
- }
- }
-
- appAttrs := &bazelAndroidAppAttributes{
- // TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
- Custom_package: a.overridableAppProperties.Package_name,
- Certificate: certificate,
- Certificate_name: certificateName,
- Manifest_values: manifestValues,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "android_binary",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- }
-
- if !bp2BuildInfo.hasKotlin {
- appAttrs.javaCommonAttributes = commonAttrs
- appAttrs.bazelAapt = aapt
- appAttrs.Deps = deps
- } else {
- ktName := a.Name() + "_kt"
- ctx.CreateBazelTargetModule(
- AndroidLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: ktName},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- },
- bazelAapt: aapt,
- },
- )
-
- appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
- appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
- appAttrs.javaCommonAttributes = &javaCommonAttributes{
- Sdk_version: commonAttrs.Sdk_version,
- }
- }
-
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: a.Name()},
- appAttrs,
- )
-
+func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path,
+ classLoaderContexts *dexpreopt.ClassLoaderContextMap) {
+ u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file
}
diff --git a/java/app_builder.go b/java/app_builder.go
index d20a6bfe4..943ce317b 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -52,7 +52,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk",
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string, shrinkResources bool) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -71,12 +71,6 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa
Output: unsignedApk,
Implicits: deps,
})
-
- if shrinkResources {
- shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
- ShrinkResources(ctx, unsignedApk, shrunkenApk)
- unsignedApk = shrunkenApk
- }
SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
}
@@ -225,8 +219,6 @@ func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePat
})
}
-const jniJarOutputPathString = "jniJarOutput.zip"
-
func TransformJniLibsToJar(
ctx android.ModuleContext,
outputFile android.WritablePath,
@@ -258,7 +250,10 @@ func TransformJniLibsToJar(
rule = zipRE
args["implicits"] = strings.Join(deps.Strings(), ",")
}
- jniJarPath := android.PathForModuleOut(ctx, jniJarOutputPathString)
+ var jniJarPath android.WritablePath = android.PathForModuleOut(ctx, "jniJarOutput.zip")
+ if len(prebuiltJniPackages) == 0 {
+ jniJarPath = outputFile
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "zip jni libs",
@@ -266,12 +261,26 @@ func TransformJniLibsToJar(
Implicits: deps,
Args: args,
})
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeAssetsRule,
- Description: "merge prebuilt JNI packages",
- Inputs: append(prebuiltJniPackages, jniJarPath),
- Output: outputFile,
- })
+ if len(prebuiltJniPackages) > 0 {
+ var mergeJniJarPath android.WritablePath = android.PathForModuleOut(ctx, "mergeJniJarOutput.zip")
+ if !uncompressJNI {
+ mergeJniJarPath = outputFile
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: mergeAssetsRule,
+ Description: "merge prebuilt JNI packages",
+ Inputs: append(prebuiltJniPackages, jniJarPath),
+ Output: mergeJniJarPath,
+ })
+
+ if uncompressJNI {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: uncompressEmbeddedJniLibsRule,
+ Input: mergeJniJarPath,
+ Output: outputFile,
+ })
+ }
+ }
}
func (a *AndroidApp) generateJavaUsedByApex(ctx android.ModuleContext) {
diff --git a/java/app_import.go b/java/app_import.go
index 85b35ebaa..fa87997cf 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -18,6 +18,7 @@ package java
import (
"reflect"
+ "strings"
"github.com/google/blueprint"
@@ -49,6 +50,12 @@ var (
CommandDeps: []string{"${config.Zip2ZipCmd}"},
Description: "Uncompress dex files",
})
+
+ checkPresignedApkRule = pctx.AndroidStaticRule("check-presigned-apk", blueprint.RuleParams{
+ Command: "build/soong/scripts/check_prebuilt_presigned_apk.py --aapt2 ${config.Aapt2Cmd} --zipalign ${config.ZipAlign} $extraArgs $in $out",
+ CommandDeps: []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"},
+ Description: "Check presigned apk",
+ }, "extraArgs")
)
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -62,9 +69,10 @@ type AndroidAppImport struct {
android.ApexModuleBase
prebuilt android.Prebuilt
- properties AndroidAppImportProperties
- dpiVariants interface{}
- archVariants interface{}
+ properties AndroidAppImportProperties
+ dpiVariants interface{}
+ archVariants interface{}
+ arch_dpiVariants interface{}
outputFile android.Path
certificate Certificate
@@ -73,8 +81,6 @@ type AndroidAppImport struct {
usesLibrary usesLibrary
- preprocessed bool
-
installPath android.InstallPath
hideApexVariantFromMake bool
@@ -128,6 +134,23 @@ type AndroidAppImportProperties struct {
// Optional. Install to a subdirectory of the default install path for the module
Relative_install_path *string
+
+ // Whether the prebuilt apk can be installed without additional processing. Default is false.
+ Preprocessed *bool
+
+ // Whether or not to skip checking the preprocessed apk for proper alignment and uncompressed
+ // JNI libs and dex files. Default is false
+ Skip_preprocessed_apk_checks *bool
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // 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"`
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -135,10 +158,12 @@ func (a *AndroidAppImport) IsInstallable() bool {
}
// Updates properties with variant-specific values.
-func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
+// This happens as a DefaultableHook instead of a LoadHook because we want to run it after
+// soong config variables are applied.
+func (a *AndroidAppImport) processVariants(ctx android.DefaultableHookContext) {
config := ctx.Config()
+ dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName(DpiGroupName)
- dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
// Try DPI variant matches in the reverse-priority order so that the highest priority match
// overwrites everything else.
// TODO(jungjw): Can we optimize this by making it priority order?
@@ -148,11 +173,27 @@ func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
if config.ProductAAPTPreferredConfig() != "" {
MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
}
-
- archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
+ archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName(ArchGroupName)
archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
+ // Process "arch" includes "dpi_variants"
+ archStructPtr := reflect.ValueOf(a.arch_dpiVariants).Elem().FieldByName(ArchGroupName)
+ if archStruct := archStructPtr.Elem(); archStruct.IsValid() {
+ archPartPropsPtr := archStruct.FieldByName(proptools.FieldNameForProperty(archType.Name))
+ if archPartProps := archPartPropsPtr.Elem(); archPartProps.IsValid() {
+ archDpiPropsPtr := archPartProps.FieldByName(DpiGroupName)
+ if archDpiProps := archDpiPropsPtr.Elem(); archDpiProps.IsValid() {
+ for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
+ MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPrebuiltDPI()[i])
+ }
+ if config.ProductAAPTPreferredConfig() != "" {
+ MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPreferredConfig())
+ }
+ }
+ }
+ }
+
if String(a.properties.Apk) == "" {
// Disable this module since the apk property is still empty after processing all matching
// variants. This likely means there is no matching variant, and the default variant doesn't
@@ -201,7 +242,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
// Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
// with them may invalidate pre-existing signature data.
- if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || a.preprocessed) {
+ if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || Bool(a.properties.Preprocessed)) {
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Output: outputPath,
@@ -219,7 +260,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
// 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() || a.preprocessed {
+ if ctx.Config().UnbundledBuild() || proptools.Bool(a.properties.Preprocessed) {
return false
}
@@ -228,7 +269,7 @@ func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
return ctx.Config().UncompressPrivAppDex()
}
- return shouldUncompressDex(ctx, &a.dexpreopter)
+ return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}
func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -239,16 +280,28 @@ func (a *AndroidAppImport) InstallApkName() string {
return a.BaseModuleName()
}
+func (a *AndroidAppImport) BaseModuleName() string {
+ return proptools.StringDefault(a.properties.Source_module_name, a.ModuleBase.Name())
+}
+
func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
if a.Name() == "prebuilt_framework-res" {
ctx.ModuleErrorf("prebuilt_framework-res found. This used to have special handling in soong, but was removed due to prebuilt_framework-res no longer existing. This check is to ensure it doesn't come back without readding the special handling.")
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
}
+ if Bool(a.properties.Preprocessed) {
+ if a.properties.Presigned != nil && !*a.properties.Presigned {
+ ctx.ModuleErrorf("Setting preprocessed: true implies presigned: true, so you cannot set presigned to false")
+ }
+ t := true
+ a.properties.Presigned = &t
+ }
+
numCertPropsSet := 0
if String(a.properties.Certificate) != "" {
numCertPropsSet++
@@ -260,11 +313,9 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
numCertPropsSet++
}
if numCertPropsSet != 1 {
- ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
+ ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set")
}
- _, _, certificates := collectAppDeps(ctx, a, false, false)
-
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
@@ -295,12 +346,15 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+ if a.usesLibrary.shouldDisableDexpreopt {
+ a.dexpreopter.disableDexpreopt()
+ }
if a.usesLibrary.enforceUsesLibraries() {
- srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+ a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk, &a.dexpreopter.classLoaderContexts)
}
- a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+ a.dexpreopter.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), jnisUncompressed)
if a.dexpreopter.uncompressedDex {
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
ctx.Build(pctx, android.BuildParams{
@@ -317,12 +371,21 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
// Sign or align the package if package has not been preprocessed
- if a.preprocessed {
- a.outputFile = srcApk
+ if proptools.Bool(a.properties.Preprocessed) {
+ validationStamp := a.validatePresignedApk(ctx, srcApk)
+ output := android.PathForModuleOut(ctx, apkFilename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: output,
+ Validation: validationStamp,
+ })
+ a.outputFile = output
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
+ _, _, certificates := collectAppDeps(ctx, a, false, false)
a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", apkFilename)
var lineageFile android.Path
@@ -335,8 +398,9 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile, rotationMinSdkVersion)
a.outputFile = signed
} else {
+ validationStamp := a.validatePresignedApk(ctx, srcApk)
alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
- TransformZipAlign(ctx, alignedApk, jnisUncompressed)
+ TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{validationStamp})
a.outputFile = alignedApk
a.certificate = PresignedCertificate
}
@@ -349,9 +413,43 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: a.BaseModuleName(),
+ isPrebuilt: true,
+ prebuiltInfo: a.properties.Prebuilt_info,
+ },
+ )
+
+ ctx.SetOutputFiles([]android.Path{a.outputFile}, "")
+
// TODO: androidmk converter jni libs
}
+func (a *AndroidAppImport) validatePresignedApk(ctx android.ModuleContext, srcApk android.Path) android.Path {
+ stamp := android.PathForModuleOut(ctx, "validated-prebuilt", "check.stamp")
+ var extraArgs []string
+ if a.Privileged() {
+ extraArgs = append(extraArgs, "--privileged")
+ }
+ if proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
+ extraArgs = append(extraArgs, "--skip-preprocessed-apk-checks")
+ }
+ if proptools.Bool(a.properties.Preprocessed) {
+ extraArgs = append(extraArgs, "--preprocessed")
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: checkPresignedApkRule,
+ Input: srcApk,
+ Output: stamp,
+ Args: map[string]string{
+ "extraArgs": strings.Join(extraArgs, " "),
+ },
+ })
+ return stamp
+}
+
func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
return &a.prebuilt
}
@@ -376,18 +474,29 @@ func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath {
return a.provenanceMetaDataFile
}
+func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath {
+ return android.OptionalPath{}
+}
+
+const (
+ ArchGroupName = "Arch"
+ DpiGroupName = "Dpi_variants"
+)
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
+var archdpiVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
func initAndroidAppImportVariantGroupTypes() {
- dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
+ dpiVariantGroupType = createVariantGroupType(supportedDpis, DpiGroupName)
archNames := make([]string, len(android.ArchTypeList()))
for i, archType := range android.ArchTypeList() {
archNames[i] = archType.Name
}
- archVariantGroupType = createVariantGroupType(archNames, "Arch")
+ archVariantGroupType = createVariantGroupType(archNames, ArchGroupName)
+ archdpiVariantGroupType = createArchDpiVariantGroupType(archNames, supportedDpis)
}
// Populates all variant struct properties at creation time.
@@ -397,6 +506,9 @@ func (a *AndroidAppImport) populateAllVariantStructs() {
a.archVariants = reflect.New(archVariantGroupType).Interface()
a.AddProperties(a.archVariants)
+
+ a.arch_dpiVariants = reflect.New(archdpiVariantGroupType).Interface()
+ a.AddProperties(a.arch_dpiVariants)
}
func (a *AndroidAppImport) Privileged() bool {
@@ -451,6 +563,48 @@ func createVariantGroupType(variants []string, variantGroupName string) reflect.
})
}
+func createArchDpiVariantGroupType(archNames []string, dpiNames []string) reflect.Type {
+ props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
+
+ dpiVariantFields := make([]reflect.StructField, len(dpiNames))
+ for i, variant_dpi := range dpiNames {
+ dpiVariantFields[i] = reflect.StructField{
+ Name: proptools.FieldNameForProperty(variant_dpi),
+ Type: props,
+ }
+ }
+ dpiVariantGroupStruct := reflect.StructOf(dpiVariantFields)
+ dpi_struct := reflect.StructOf([]reflect.StructField{
+ {
+ Name: DpiGroupName,
+ Type: reflect.PointerTo(dpiVariantGroupStruct),
+ },
+ })
+
+ archVariantFields := make([]reflect.StructField, len(archNames))
+ for i, variant_arch := range archNames {
+ archVariantFields[i] = reflect.StructField{
+ Name: proptools.FieldNameForProperty(variant_arch),
+ Type: reflect.PointerTo(dpi_struct),
+ }
+ }
+ archVariantGroupStruct := reflect.StructOf(archVariantFields)
+
+ return_struct := reflect.StructOf([]reflect.StructField{
+ {
+ Name: ArchGroupName,
+ Type: reflect.PointerTo(archVariantGroupStruct),
+ },
+ })
+ return return_struct
+}
+
+func (a *AndroidAppImport) UsesLibrary() *usesLibrary {
+ return &a.usesLibrary
+}
+
+var _ ModuleWithUsesLibrary = (*AndroidAppImport)(nil)
+
// android_app_import imports a prebuilt apk with additional processing specified in the module.
// DPI-specific apk source files can be specified using dpi_variants. Example:
//
@@ -473,7 +627,7 @@ func AndroidAppImportFactory() android.Module {
module.AddProperties(&module.dexpreoptProperties)
module.AddProperties(&module.usesLibrary.usesLibraryProperties)
module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
module.processVariants(ctx)
})
@@ -487,11 +641,6 @@ func AndroidAppImportFactory() android.Module {
return module
}
-type androidTestImportProperties struct {
- // Whether the prebuilt apk can be installed without additional processing. Default is false.
- Preprocessed *bool
-}
-
type AndroidTestImport struct {
AndroidAppImport
@@ -508,14 +657,10 @@ type AndroidTestImport struct {
Per_testcase_directory *bool
}
- testImportProperties androidTestImportProperties
-
data android.Paths
}
func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.preprocessed = Bool(a.testImportProperties.Preprocessed)
-
a.generateAndroidBuildActions(ctx)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
@@ -532,9 +677,8 @@ func AndroidTestImportFactory() android.Module {
module.AddProperties(&module.properties)
module.AddProperties(&module.dexpreoptProperties)
module.AddProperties(&module.testProperties)
- module.AddProperties(&module.testImportProperties)
module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
module.processVariants(ctx)
})
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 80930248e..496fc1308 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -40,8 +40,8 @@ func TestAndroidAppImport(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ 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")
}
@@ -74,8 +74,8 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. They shouldn't exist.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.")
}
@@ -101,8 +101,8 @@ func TestAndroidAppImport_Presigned(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ 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")
}
// Make sure signing was skipped and aligning was done.
@@ -210,8 +210,8 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ 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")
}
@@ -411,6 +411,27 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
installPath: "/system/app/foo/foo.apk",
},
{
+ name: "matching arch without default",
+ bp: `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ arch: {
+ arm64: {
+ apk: "prebuilts/apk/app_arm64.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
+ artifactPath: "prebuilts/apk/app_arm64.apk",
+ installPath: "/system/app/foo/foo.apk",
+ },
+ {
name: "no matching arch",
bp: `
android_app_import {
@@ -451,29 +472,137 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) {
artifactPath: "prebuilts/apk/app_arm.apk",
installPath: "/system/app/foo/foo.apk",
},
+ {
+ name: "matching arch and dpi_variants",
+ bp: `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ arch: {
+ arm64: {
+ apk: "prebuilts/apk/app_arm64.apk",
+ dpi_variants: {
+ mdpi: {
+ apk: "prebuilts/apk/app_arm64_mdpi.apk",
+ },
+ xhdpi: {
+ apk: "prebuilts/apk/app_arm64_xhdpi.apk",
+ },
+ },
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "verify_uses_libraries/apk/app_arm64_xhdpi.apk",
+ artifactPath: "prebuilts/apk/app_arm64_xhdpi.apk",
+ installPath: "/system/app/foo/foo.apk",
+ },
}
for _, test := range testCases {
- ctx, _ := testJava(t, test.bp)
+ t.Run(test.name, func(t *testing.T) {
+ ctx, _ := testJava(t, test.bp)
- variant := ctx.ModuleForTests("foo", "android_common")
- if test.expected == "" {
- if variant.Module().Enabled() {
- t.Error("module should have been disabled, but wasn't")
+ variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
+ return
}
- rule := variant.MaybeRule("genProvenanceMetaData")
- android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
- continue
- }
- 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)
- }
- rule := variant.Rule("genProvenanceMetaData")
- android.AssertStringEquals(t, "Invalid input", test.artifactPath, 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", test.installPath, rule.Args["install_path"])
+ 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)
+ }
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, 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", test.installPath, rule.Args["install_path"])
+ })
+ }
+}
+
+func TestAndroidAppImport_SoongConfigVariables(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ expected string
+ artifactPath string
+ metaDataPath string
+ installPath string
+ }{
+ {
+ name: "matching arch",
+ bp: `
+ soong_config_module_type {
+ name: "my_android_app_import",
+ module_type: "android_app_import",
+ config_namespace: "my_namespace",
+ value_variables: ["my_apk_var"],
+ properties: ["apk"],
+ }
+ soong_config_value_variable {
+ name: "my_apk_var",
+ }
+ my_android_app_import {
+ name: "foo",
+ soong_config_variables: {
+ my_apk_var: {
+ apk: "prebuilts/apk/%s.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "verify_uses_libraries/apk/name_from_soong_config.apk",
+ artifactPath: "prebuilts/apk/name_from_soong_config.apk",
+ installPath: "/system/app/foo/foo.apk",
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.PrepareForTestWithSoongConfigModuleBuildComponents,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "my_namespace": {
+ "my_apk_var": "name_from_soong_config",
+ },
+ }
+ }),
+ ).RunTestWithBp(t, test.bp).TestContext
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
+ return
+ }
+ 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)
+ }
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, 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", test.installPath, rule.Args["install_path"])
+ })
}
}
@@ -500,7 +629,7 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
if !a.prebuilt.UsePrebuilt() {
t.Errorf("prebuilt foo module is not active")
}
- if !a.Enabled() {
+ if !a.Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Errorf("prebuilt foo module is disabled")
}
}
@@ -629,31 +758,49 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) {
presigned: true,
preprocessed: true,
}
+ `)
- android_test_import {
- name: "foo_cert",
+ apkName := "foo.apk"
+ variant := ctx.ModuleForTests("foo", "android_common")
+ jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
+ if jniRule != android.Cp.String() {
+ t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+ }
+
+ // Make sure signing and aligning were skipped.
+ if variant.MaybeOutput("signed/"+apkName).Rule != nil {
+ t.Errorf("signing rule shouldn't be included for preprocessed.")
+ }
+ if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
+ t.Errorf("aligning rule shouldn't be for preprocessed")
+ }
+}
+
+func TestAndroidAppImport_Preprocessed(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
apk: "prebuilts/apk/app.apk",
- certificate: "cert/new_cert",
+ presigned: true,
preprocessed: true,
}
`)
- testModules := []string{"foo", "foo_cert"}
- for _, m := range testModules {
- apkName := m + ".apk"
- variant := ctx.ModuleForTests(m, "android_common")
- jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
- if jniRule != android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
- }
+ apkName := "foo.apk"
+ variant := ctx.ModuleForTests("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())
+ }
- // Make sure signing and aligning were skipped.
- if variant.MaybeOutput("signed/"+apkName).Rule != nil {
- t.Errorf("signing rule shouldn't be included for preprocessed.")
- }
- if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
- t.Errorf("aligning rule shouldn't be for preprocessed")
- }
+ // Make sure compression and aligning were validated.
+ if outputBuildParams.Validation == nil {
+ t.Errorf("Expected validation rule, but was not found")
+ }
+
+ validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
+ if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
+ t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
}
}
diff --git a/java/app_set.go b/java/app_set.go
index d2d3b06ba..33d3adec2 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -48,6 +48,11 @@ type AndroidAppSetProperties struct {
// Names of modules to be overridden. Listed modules can only be other apps
// (in Make or Soong).
Overrides []string
+
+ // 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"`
}
type AndroidAppSet struct {
@@ -117,6 +122,27 @@ func SupportedAbis(ctx android.ModuleContext, excludeNativeBridgeAbis bool) []st
return result
}
+type prebuiltInfoProps struct {
+ baseModuleName string
+ isPrebuilt bool
+ prebuiltInfo *string
+}
+
+// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
+// with information about whether source or prebuilt of an apex was used during the build.
+func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
+ info := android.PrebuiltInfo{
+ Name: p.baseModuleName,
+ Is_prebuilt: p.isPrebuilt,
+ }
+ // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
+ if p.prebuiltInfo != nil {
+ prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo)
+ info.Prebuilt_info_file_path = prebuiltInfoFile.String()
+ }
+ android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+}
+
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
@@ -157,6 +183,15 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext)
installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
}
ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)
+
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: as.BaseModuleName(),
+ isPrebuilt: true,
+ prebuiltInfo: as.properties.Prebuilt_info,
+ },
+ )
+
}
func (as *AndroidAppSet) InstallBypassMake() bool { return true }
diff --git a/java/app_test.go b/java/app_test.go
index b154bc990..e878ccf6d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -119,10 +119,7 @@ func TestAppSplits(t *testing.T) {
foo.Output(expectedOutput)
}
- outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
- if err != nil {
- t.Fatal(err)
- }
+ outputFiles := foo.OutputFiles(t, "")
android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
}
@@ -443,9 +440,9 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
var crtbeginFound, crtendFound bool
expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
- "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+ "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
expectedCrtEnd := ctx.ModuleForTests("crtend_so",
- "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+ "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
implicits := []string{}
for _, input := range inputs {
implicits = append(implicits, input.String())
@@ -519,6 +516,49 @@ func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) {
testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp)
}
+func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ updatable: true,
+ }
+ `)
+ foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ android.AssertStringDoesContain(t,
+ "com.android.foo: expected manifest fixer to set override-placeholder-version to android.DefaultUpdatableModuleVersion",
+ foo.BuildParams.Args["args"],
+ fmt.Sprintf("--override-placeholder-version %s", android.DefaultUpdatableModuleVersion),
+ )
+}
+
+func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureMergeEnv(map[string]string{
+ "OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
+ }),
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ updatable: true,
+ }
+ `)
+ foo := result.ModuleForTests("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"],
+ "--override-placeholder-version 1234",
+ )
+}
+
func TestResourceDirs(t *testing.T) {
testCases := []struct {
name string
@@ -558,7 +598,6 @@ func TestResourceDirs(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
@@ -599,7 +638,7 @@ func TestLibraryAssets(t *testing.T) {
android_library {
name: "lib3",
sdk_version: "current",
- static_libs: ["lib4"],
+ static_libs: ["lib4", "import"],
}
android_library {
@@ -607,20 +646,38 @@ func TestLibraryAssets(t *testing.T) {
sdk_version: "current",
asset_dirs: ["assets_b"],
}
+
+ android_library {
+ name: "lib5",
+ sdk_version: "current",
+ assets: [
+ "path/to/asset_file_1",
+ "path/to/asset_file_2",
+ ],
+ }
+
+ android_library_import {
+ name: "import",
+ sdk_version: "current",
+ aars: ["import.aar"],
+ }
`
testCases := []struct {
- name string
- assetFlag string
- assetPackages []string
+ name string
+ assetFlag string
+ assetPackages []string
+ tmpAssetDirInputs []string
+ tmpAssetDirOutputs []string
}{
{
name: "foo",
- // lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
+ // lib1 has its own assets. lib3 doesn't have any, but lib4 and import have assets.
assetPackages: []string{
"out/soong/.intermediates/foo/android_common/aapt2/package-res.apk",
"out/soong/.intermediates/lib1/android_common/assets.zip",
- "out/soong/.intermediates/lib3/android_common/assets.zip",
+ "out/soong/.intermediates/lib4/android_common/assets.zip",
+ "out/soong/.intermediates/import/android_common/assets.zip",
},
},
{
@@ -632,15 +689,23 @@ func TestLibraryAssets(t *testing.T) {
},
{
name: "lib3",
- assetPackages: []string{
- "out/soong/.intermediates/lib3/android_common/aapt2/package-res.apk",
- "out/soong/.intermediates/lib4/android_common/assets.zip",
- },
},
{
name: "lib4",
assetFlag: "-A assets_b",
},
+ {
+ name: "lib5",
+ assetFlag: "-A out/soong/.intermediates/lib5/android_common/tmp_asset_dir",
+ tmpAssetDirInputs: []string{
+ "path/to/asset_file_1",
+ "path/to/asset_file_2",
+ },
+ tmpAssetDirOutputs: []string{
+ "out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_1",
+ "out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_2",
+ },
+ },
}
ctx := testApp(t, bp)
@@ -668,6 +733,14 @@ func TestLibraryAssets(t *testing.T) {
mergeAssets := m.Output("package-res.apk")
android.AssertPathsRelativeToTopEquals(t, "mergeAssets inputs", test.assetPackages, mergeAssets.Inputs)
}
+
+ if len(test.tmpAssetDirInputs) > 0 {
+ rule := m.Rule("tmp_asset_dir")
+ inputs := rule.Implicits
+ outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Paths()
+ android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir inputs", test.tmpAssetDirInputs, inputs)
+ android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir outputs", test.tmpAssetDirOutputs, outputs)
+ }
})
}
}
@@ -717,7 +790,635 @@ func TestAppJavaResources(t *testing.T) {
}
}
-func TestAndroidResources(t *testing.T) {
+func TestAndroidResourceProcessor(t *testing.T) {
+ testCases := []struct {
+ name string
+ appUsesRP bool
+ directLibUsesRP bool
+ transitiveLibUsesRP bool
+ sharedLibUsesRP bool
+ sharedTransitiveStaticLibUsesRP bool
+ sharedTransitiveSharedLibUsesRP bool
+
+ dontVerifyApp bool
+ appResources []string
+ appOverlays []string
+ appImports []string
+ appSrcJars []string
+ appClasspath []string
+ appCombined []string
+
+ dontVerifyDirect bool
+ directResources []string
+ directOverlays []string
+ directImports []string
+ directSrcJars []string
+ directClasspath []string
+ directCombined []string
+
+ dontVerifyTransitive bool
+ transitiveResources []string
+ transitiveOverlays []string
+ transitiveImports []string
+ transitiveSrcJars []string
+ transitiveClasspath []string
+ transitiveCombined []string
+
+ dontVerifyDirectImport bool
+ directImportResources []string
+ directImportOverlays []string
+ directImportImports []string
+
+ dontVerifyTransitiveImport bool
+ transitiveImportResources []string
+ transitiveImportOverlays []string
+ transitiveImportImports []string
+
+ dontVerifyShared bool
+ sharedResources []string
+ sharedOverlays []string
+ sharedImports []string
+ sharedSrcJars []string
+ sharedClasspath []string
+ sharedCombined []string
+ }{
+ {
+ // Test with all modules set to use_resource_processor: false (except android_library_import modules,
+ // which always use resource processor).
+ name: "legacy",
+ appUsesRP: false,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: false,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
+ },
+ directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: []string{"out/soong/.intermediates/transitive/android_common/gen/android/R.srcjar"},
+ transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
+ transitiveCombined: nil,
+
+ sharedResources: nil,
+ sharedOverlays: []string{
+ "out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
+ "out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat",
+ },
+ sharedImports: []string{
+ "out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ sharedSrcJars: []string{"out/soong/.intermediates/shared/android_common/gen/android/R.srcjar"},
+ sharedClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
+ },
+ sharedCombined: []string{
+ "out/soong/.intermediates/shared/android_common/javac/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
+ },
+
+ directImportResources: nil,
+ directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
+ directImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ },
+
+ transitiveImportResources: nil,
+ transitiveImportOverlays: []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
+ transitiveImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ },
+ },
+ {
+ // Test with all modules set to use_resource_processor: true.
+ name: "resource_processor",
+ appUsesRP: true,
+ directLibUsesRP: true,
+ transitiveLibUsesRP: true,
+ sharedLibUsesRP: true,
+ sharedTransitiveSharedLibUsesRP: true,
+ sharedTransitiveStaticLibUsesRP: true,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ appSrcJars: nil,
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
+ directImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ },
+ directSrcJars: nil,
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: nil,
+ transitiveClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ },
+ transitiveCombined: nil,
+
+ sharedResources: nil,
+ sharedOverlays: []string{"out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat"},
+ sharedImports: []string{
+ "out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
+ },
+ sharedSrcJars: nil,
+ sharedClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
+ },
+ sharedCombined: []string{
+ "out/soong/.intermediates/shared/android_common/javac/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
+ },
+
+ directImportResources: nil,
+ directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
+ directImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ },
+
+ transitiveImportResources: nil,
+ transitiveImportOverlays: []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
+ transitiveImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ },
+ }, {
+ // Test an app building with resource processor enabled but with dependencies built without
+ // resource processor.
+ name: "app_resource_processor",
+ appUsesRP: true,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: false,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ appSrcJars: nil,
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ // R.jar has to come before direct.jar
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
+ },
+
+ dontVerifyDirect: true,
+ dontVerifyTransitive: true,
+ dontVerifyShared: true,
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ {
+ // Test an app building without resource processor enabled but with a dependency built with
+ // resource processor.
+ name: "app_dependency_lib_resource_processor",
+ appUsesRP: false,
+ directLibUsesRP: true,
+ transitiveLibUsesRP: false,
+
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
+ directImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ },
+ directSrcJars: nil,
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
+ },
+
+ dontVerifyTransitive: true,
+ dontVerifyShared: true,
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ {
+ // Test a library building without resource processor enabled but with a dependency built with
+ // resource processor.
+ name: "lib_dependency_lib_resource_processor",
+ appUsesRP: false,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: true,
+
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
+ },
+ directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: nil,
+ transitiveClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ },
+ transitiveCombined: nil,
+
+ dontVerifyShared: true,
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "app",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ resource_dirs: ["app/res"],
+ manifest: "app/AndroidManifest.xml",
+ libs: ["shared"],
+ static_libs: ["direct", "direct_import"],
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ static_libs: ["transitive", "transitive_import"],
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "transitive",
+ sdk_version: "current",
+ srcs: ["transitive/transitive.java"],
+ resource_dirs: ["transitive/res"],
+ manifest: "transitive/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "shared",
+ sdk_version: "current",
+ srcs: ["shared/shared.java"],
+ resource_dirs: ["shared/res"],
+ manifest: "shared/AndroidManifest.xml",
+ use_resource_processor: %v,
+ libs: ["shared_transitive_shared"],
+ static_libs: ["shared_transitive_static"],
+ }
+
+ android_library {
+ name: "shared_transitive_shared",
+ sdk_version: "current",
+ srcs: ["shared_transitive_shared/shared_transitive_shared.java"],
+ resource_dirs: ["shared_transitive_shared/res"],
+ manifest: "shared_transitive_shared/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "shared_transitive_static",
+ sdk_version: "current",
+ srcs: ["shared_transitive_static/shared.java"],
+ resource_dirs: ["shared_transitive_static/res"],
+ manifest: "shared_transitive_static/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
+ android_library_import {
+ name: "direct_import",
+ sdk_version: "current",
+ aars: ["direct_import.aar"],
+ static_libs: ["direct_import_dep"],
+ }
+
+ android_library_import {
+ name: "direct_import_dep",
+ sdk_version: "current",
+ aars: ["direct_import_dep.aar"],
+ }
+
+ android_library_import {
+ name: "transitive_import",
+ sdk_version: "current",
+ aars: ["transitive_import.aar"],
+ static_libs: ["transitive_import_dep"],
+ }
+
+ android_library_import {
+ name: "transitive_import_dep",
+ sdk_version: "current",
+ aars: ["transitive_import_dep.aar"],
+ }
+ `, testCase.appUsesRP, testCase.directLibUsesRP, testCase.transitiveLibUsesRP,
+ testCase.sharedLibUsesRP, testCase.sharedTransitiveSharedLibUsesRP, testCase.sharedTransitiveStaticLibUsesRP)
+
+ fs := android.MockFS{
+ "app/res/values/strings.xml": nil,
+ "direct/res/values/strings.xml": nil,
+ "transitive/res/values/strings.xml": nil,
+ "shared/res/values/strings.xml": nil,
+ "shared_transitive_static/res/values/strings.xml": nil,
+ "shared_transitive_shared/res/values/strings.xml": nil,
+ }
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ fs.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ type aaptInfo struct {
+ resources, overlays, imports, srcJars, classpath, combined android.Paths
+ }
+
+ getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) {
+ mod := result.ModuleForTests(moduleName, "android_common")
+ resourceListRule := mod.MaybeOutput("aapt2/res.list")
+ overlayListRule := mod.MaybeOutput("aapt2/overlay.list")
+ aaptRule := mod.Rule("aapt2Link")
+ javacRule := mod.MaybeRule("javac")
+ combinedRule := mod.MaybeOutput("combined/" + moduleName + ".jar")
+
+ aaptInfo.resources = resourceListRule.Inputs
+ aaptInfo.overlays = overlayListRule.Inputs
+
+ aaptFlags := strings.Split(aaptRule.Args["flags"], " ")
+ for i, flag := range aaptFlags {
+ if flag == "-I" && i+1 < len(aaptFlags) {
+ aaptInfo.imports = append(aaptInfo.imports, android.PathForTesting(aaptFlags[i+1]))
+ }
+ }
+
+ if len(javacRule.Args["srcJars"]) > 0 {
+ aaptInfo.srcJars = android.PathsForTesting(strings.Split(javacRule.Args["srcJars"], " ")...)
+ }
+
+ if len(javacRule.Args["classpath"]) > 0 {
+ classpathArg := strings.TrimPrefix(javacRule.Args["classpath"], "-classpath ")
+ aaptInfo.classpath = android.PathsForTesting(strings.Split(classpathArg, ":")...)
+ }
+
+ aaptInfo.combined = combinedRule.Inputs
+ return
+ }
+
+ app := getAaptInfo("app")
+ direct := getAaptInfo("direct")
+ transitive := getAaptInfo("transitive")
+ shared := getAaptInfo("shared")
+ directImport := getAaptInfo("direct_import")
+ transitiveImport := getAaptInfo("transitive_import")
+
+ if !testCase.dontVerifyApp {
+ android.AssertPathsRelativeToTopEquals(t, "app resources", testCase.appResources, app.resources)
+ android.AssertPathsRelativeToTopEquals(t, "app overlays", testCase.appOverlays, app.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "app imports", testCase.appImports, app.imports)
+ android.AssertPathsRelativeToTopEquals(t, "app srcjars", testCase.appSrcJars, app.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "app classpath", testCase.appClasspath, app.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "app combined", testCase.appCombined, app.combined)
+ }
+
+ if !testCase.dontVerifyDirect {
+ android.AssertPathsRelativeToTopEquals(t, "direct resources", testCase.directResources, direct.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct overlays", testCase.directOverlays, direct.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct imports", testCase.directImports, direct.imports)
+ android.AssertPathsRelativeToTopEquals(t, "direct srcjars", testCase.directSrcJars, direct.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "direct classpath", testCase.directClasspath, direct.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "direct combined", testCase.directCombined, direct.combined)
+ }
+
+ if !testCase.dontVerifyTransitive {
+ android.AssertPathsRelativeToTopEquals(t, "transitive resources", testCase.transitiveResources, transitive.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive overlays", testCase.transitiveOverlays, transitive.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive imports", testCase.transitiveImports, transitive.imports)
+ android.AssertPathsRelativeToTopEquals(t, "transitive srcjars", testCase.transitiveSrcJars, transitive.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "transitive classpath", testCase.transitiveClasspath, transitive.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "transitive combined", testCase.transitiveCombined, transitive.combined)
+ }
+
+ if !testCase.dontVerifyShared {
+ android.AssertPathsRelativeToTopEquals(t, "shared resources", testCase.sharedResources, shared.resources)
+ android.AssertPathsRelativeToTopEquals(t, "shared overlays", testCase.sharedOverlays, shared.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "shared imports", testCase.sharedImports, shared.imports)
+ android.AssertPathsRelativeToTopEquals(t, "shared srcjars", testCase.sharedSrcJars, shared.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "shared classpath", testCase.sharedClasspath, shared.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "shared combined", testCase.sharedCombined, shared.combined)
+ }
+
+ if !testCase.dontVerifyDirectImport {
+ android.AssertPathsRelativeToTopEquals(t, "direct_import resources", testCase.directImportResources, directImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import overlays", testCase.directImportOverlays, directImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import imports", testCase.directImportImports, directImport.imports)
+ }
+
+ if !testCase.dontVerifyTransitiveImport {
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import resources", testCase.transitiveImportResources, transitiveImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import overlays", testCase.transitiveImportOverlays, transitiveImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import imports", testCase.transitiveImportImports, transitiveImport.imports)
+ }
+ })
+ }
+}
+
+func TestAndroidResourceOverlays(t *testing.T) {
testCases := []struct {
name string
enforceRROTargets []string
@@ -903,7 +1604,6 @@ func TestAndroidResources(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceResourceOverlays = deviceResourceOverlays
@@ -943,7 +1643,7 @@ func TestAndroidResources(t *testing.T) {
overlayFiles = resourceListToFiles(module, android.PathsRelativeToTop(overlayList.Inputs))
}
- for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
+ for _, d := range module.Module().(AndroidLibraryDependency).RRODirsDepSet().ToList() {
var prefix string
if d.overlayType == device {
prefix = "device:"
@@ -1232,7 +1932,7 @@ func TestJNIABI(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output(jniJarOutputPathString)
+ jniLibZip := app.Output("jnilibs.zip")
var abis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
@@ -1365,7 +2065,7 @@ func TestJNIPackaging(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.MaybeOutput(jniJarOutputPathString)
+ 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)
}
@@ -1449,14 +2149,14 @@ func TestJNISDK(t *testing.T) {
Output("libjni.so").Output.String()
sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
Output("libjni.so").Output.String()
- vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
+ vendorJNI := ctx.ModuleForTests("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")
- jniLibZip := app.MaybeOutput(jniJarOutputPathString)
+ jniLibZip := app.MaybeOutput("jnilibs.zip")
if len(jniLibZip.Implicits) != 1 {
t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
}
@@ -2476,7 +3176,7 @@ func TestStl(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output(jniJarOutputPathString)
+ jniLibZip := app.Output("jnilibs.zip")
var jnis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
@@ -2584,7 +3284,10 @@ func TestUsesLibraries(t *testing.T) {
name: "static-y",
srcs: ["a.java"],
uses_libs: ["runtime-required-y"],
- optional_uses_libs: ["runtime-optional-y"],
+ optional_uses_libs: [
+ "runtime-optional-y",
+ "missing-lib-a",
+ ],
sdk_version: "current",
}
@@ -2620,7 +3323,7 @@ func TestUsesLibraries(t *testing.T) {
sdk_version: "current",
optional_uses_libs: [
"bar",
- "baz",
+ "missing-lib-b",
],
}
@@ -2635,7 +3338,7 @@ func TestUsesLibraries(t *testing.T) {
],
optional_uses_libs: [
"bar",
- "baz",
+ "missing-lib-b",
],
}
`
@@ -2645,7 +3348,7 @@ func TestUsesLibraries(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.MissingUsesLibraries = []string{"baz"}
+ variables.BuildWarningBadOptionalUsesLibsAllowlist = []string{"app", "prebuilt"}
}),
).RunTestWithBp(t, bp)
@@ -2657,10 +3360,10 @@ func TestUsesLibraries(t *testing.T) {
// propagated from dependencies.
actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
expectManifestFixerArgs := `--extract-native-libs=true ` +
- `--uses-library qux ` +
- `--uses-library quuz ` +
`--uses-library foo ` +
`--uses-library com.non.sdk.lib ` +
+ `--uses-library qux ` +
+ `--uses-library quuz ` +
`--uses-library runtime-library ` +
`--uses-library runtime-required-x ` +
`--uses-library runtime-required-y ` +
@@ -2679,9 +3382,10 @@ func TestUsesLibraries(t *testing.T) {
`--uses-library runtime-required-x ` +
`--uses-library runtime-required-y ` +
`--optional-uses-library bar ` +
- `--optional-uses-library baz ` +
`--optional-uses-library runtime-optional-x ` +
- `--optional-uses-library runtime-optional-y `
+ `--optional-uses-library runtime-optional-y ` +
+ `--missing-optional-uses-library missing-lib-b ` +
+ `--missing-optional-uses-library missing-lib-a`
android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
// Test that all libraries are verified for an APK (library order matters).
@@ -2690,55 +3394,14 @@ func TestUsesLibraries(t *testing.T) {
`--uses-library com.non.sdk.lib ` +
`--uses-library android.test.runner ` +
`--optional-uses-library bar ` +
- `--optional-uses-library baz `
+ `--missing-optional-uses-library missing-lib-b `
android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
- // Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
+ // Test that necessary args are passed for constructing CLC in Ninja phase.
cmd := app.Rule("dexpreopt").RuleParams.Command
- w := `--target-context-for-sdk any ` +
- `PCL[/system/framework/qux.jar]#` +
- `PCL[/system/framework/quuz.jar]#` +
- `PCL[/system/framework/foo.jar]#` +
- `PCL[/system/framework/non-sdk-lib.jar]#` +
- `PCL[/system/framework/bar.jar]#` +
- `PCL[/system/framework/runtime-library.jar]#` +
- `PCL[/system/framework/runtime-required-x.jar]#` +
- `PCL[/system/framework/runtime-optional-x.jar]#` +
- `PCL[/system/framework/runtime-required-y.jar]#` +
- `PCL[/system/framework/runtime-optional-y.jar] `
- android.AssertStringDoesContain(t, "dexpreopt app cmd args", cmd, w)
-
- // Test conditional context for target SDK version 28.
- android.AssertStringDoesContain(t, "dexpreopt app cmd 28", cmd,
- `--target-context-for-sdk 28`+
- ` PCL[/system/framework/org.apache.http.legacy.jar] `)
-
- // Test conditional context for target SDK version 29.
- android.AssertStringDoesContain(t, "dexpreopt app cmd 29", cmd,
- `--target-context-for-sdk 29`+
- ` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]`+
- `#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `)
-
- // Test conditional context for target SDK version 30.
- // "android.test.mock" is absent because "android.test.runner" is not used.
- android.AssertStringDoesContain(t, "dexpreopt app cmd 30", cmd,
- `--target-context-for-sdk 30`+
- ` PCL[/system/framework/android.test.base.jar] `)
-
- cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
- android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd", cmd,
- `--target-context-for-sdk any`+
- ` PCL[/system/framework/foo.jar]`+
- `#PCL[/system/framework/non-sdk-lib.jar]`+
- `#PCL[/system/framework/android.test.runner.jar]`+
- `#PCL[/system/framework/bar.jar] `)
-
- // Test conditional context for target SDK version 30.
- // "android.test.mock" is present because "android.test.runner" is used.
- android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd 30", cmd,
- `--target-context-for-sdk 30`+
- ` PCL[/system/framework/android.test.base.jar]`+
- `#PCL[/system/framework/android.test.mock.jar] `)
+ android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=")
+ android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd,
+ "--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/app/product_packages.txt")
}
func TestDexpreoptBcp(t *testing.T) {
@@ -3006,7 +3669,10 @@ func TestExportedProguardFlagFiles(t *testing.T) {
android_app {
name: "foo",
sdk_version: "current",
- static_libs: ["lib1"],
+ static_libs: [
+ "lib1",
+ "lib3",
+ ],
}
android_library {
@@ -3014,22 +3680,49 @@ func TestExportedProguardFlagFiles(t *testing.T) {
sdk_version: "current",
optimize: {
proguard_flags_files: ["lib1proguard.cfg"],
+ },
+ static_libs: ["lib2"],
+ }
+
+ android_library {
+ name: "lib2",
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["lib2proguard.cfg"],
}
}
- `)
- m := ctx.ModuleForTests("foo", "android_common")
- hasLib1Proguard := false
- for _, s := range m.Rule("java.r8").Implicits.Strings() {
- if s == "lib1proguard.cfg" {
- hasLib1Proguard = true
- break
+ android_library_import {
+ name: "lib3",
+ sdk_version: "current",
+ aars: ["lib3.aar"],
+ static_libs: ["lib4"],
}
- }
- if !hasLib1Proguard {
- t.Errorf("App does not use library proguard config")
- }
+ android_library {
+ name: "lib4",
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["lib4proguard.cfg"],
+ }
+ }
+
+
+ `)
+
+ m := ctx.ModuleForTests("foo", "android_common")
+ r8 := m.Rule("java.r8")
+ implicits := r8.Implicits.RelativeToTop().Strings()
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib2proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib4proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
+
+ flags := r8.Args["r8Flags"]
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib1proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib2proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib4proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
}
func TestTargetSdkVersionManifestFixer(t *testing.T) {
@@ -3493,6 +4186,7 @@ func TestTargetSdkVersionMtsTests(t *testing.T) {
bpTemplate := `
%v {
name: "mytest",
+ min_sdk_version: "34",
target_sdk_version: "%v",
test_suites: ["othersuite", "%v"],
}
@@ -3547,3 +4241,399 @@ func TestTargetSdkVersionMtsTests(t *testing.T) {
android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
+
+func TestPrivappAllowlist(t *testing.T) {
+ testJavaError(t, "privileged must be set in order to use privapp_allowlist", `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "perms.xml",
+ }
+ `)
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ app := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("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")
+ expectedAllowlistInput := "privapp_allowlist_com.android.foo.xml"
+ overrideActualAllowlistInput := overrideApp.Rule("modifyAllowlist").Input.String()
+ if expectedAllowlistInput != overrideActualAllowlistInput {
+ t.Errorf("expected override allowlist to be %q; got %q", expectedAllowlistInput, overrideActualAllowlistInput)
+ }
+
+ // 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")
+}
+
+func TestPrivappAllowlistAndroidMk(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ baseApp := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("foo", "android_common_bar")
+
+ baseAndroidApp := baseApp.Module().(*AndroidApp)
+ baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk:\\S+/target/product/test_device/system/priv-app/foo/foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml",
+ )
+
+ overrideAndroidApp := overrideApp.Module().(*AndroidApp)
+ overrideEntries := android.AndroidMkEntriesForTest(t, result.TestContext, overrideAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk:\\S+/target/product/test_device/system/priv-app/bar/bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
+ )
+}
+
+func TestAppFlagsPackages(t *testing.T) {
+ ctx := testApp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ container: "com.android.foo",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ // android_app module depends on aconfig_declarations listed in flags_packages
+ android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+ CheckModuleHasDependency(t, ctx, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, ctx, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
+
+func TestAppFlagsPackagesPropagation(t *testing.T) {
+ ctx := testApp(t, `
+ aconfig_declarations {
+ name: "foo",
+ package: "com.example.package.foo",
+ container: "com.android.foo",
+ srcs: [
+ "foo.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ container: "com.android.bar",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ container: "com.android.baz",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ android_library {
+ name: "foo_lib",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "foo",
+ ],
+ }
+ android_library {
+ name: "bar_lib",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ ],
+ }
+ android_app {
+ name: "baz_app",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "baz",
+ ],
+ static_libs: [
+ "bar_lib",
+ ],
+ libs: [
+ "foo_lib",
+ ],
+ }
+ `)
+
+ bazApp := ctx.ModuleForTests("baz_app", "android_common")
+
+ // android_app module depends on aconfig_declarations listed in flags_packages
+ // and that of static libs, but not libs
+ aapt2LinkRule := bazApp.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments of flags_packages and that of its static libs",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+ android.AssertStringDoesNotContain(t,
+ "aapt2 link command expected to not pass feature flags arguments of flags_packages of its libs",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/foo/intermediate.txt",
+ )
+}
+
+// Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation.
+func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) {
+ bp := `
+ java_sdk_library_import {
+ name: "sdklib_noimpl",
+ public: {
+ jars: ["stub.jar"],
+ },
+ }
+ android_app {
+ name: "app",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ optional_uses_libs: [
+ "sdklib_noimpl",
+ ],
+ }
+ `
+ result := prepareForJavaTest.RunTestWithBp(t, bp)
+ dexpreopt := result.ModuleForTests("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)
+}
+
+func TestTestOnlyApp(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ // These should be test-only
+ android_test {
+ name: "android-test",
+ }
+ android_test_helper_app {
+ name: "helper-app",
+ }
+ override_android_test {
+ name: "override-test",
+ base: "android-app",
+ }
+ // And these should not be
+ android_app {
+ name: "android-app",
+ srcs: ["b.java"],
+ sdk_version: "current",
+ }
+ `)
+
+ expectedTestOnly := []string{
+ "android-test",
+ "helper-app",
+ "override-test",
+ }
+
+ expectedTopLevel := []string{
+ "android-test",
+ "override-test",
+ }
+
+ assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel)
+}
+
+func TestAppStem(t *testing.T) {
+ ctx := testApp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ sdk_version: "current",
+ }`)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.apk") {
+ t.Errorf("Module output does not contain expected apk %s", "foo-new.apk")
+ }
+}
+
+func TestAppMinSdkVersionOverride(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ updatable: true,
+ }
+ override_android_app {
+ name: "com.android.go.foo",
+ base: "com.android.foo",
+ 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")
+
+ android.AssertStringDoesContain(t,
+ "com.android.foo: expected manifest fixer to set minSdkVersion to T",
+ foo.BuildParams.Args["args"],
+ "--minSdkVersion 31",
+ )
+ android.AssertStringDoesContain(t,
+ "com.android.go.foo: expected manifest fixer to set minSdkVersion to T",
+ fooOverride.BuildParams.Args["args"],
+ "--minSdkVersion 33",
+ )
+
+}
+
+func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ }
+ `)
+ foo := result.ModuleForTests("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"],
+ "--override-placeholder-version",
+ )
+}
+
+func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureMergeEnv(map[string]string{
+ "OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
+ }),
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "com.android.foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ }
+ `)
+ foo := result.ModuleForTests("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"],
+ "--override-placeholder-version",
+ )
+}
diff --git a/java/base.go b/java/base.go
index 991132321..caac98abc 100644
--- a/java/base.go
+++ b/java/base.go
@@ -17,9 +17,12 @@ package java
import (
"fmt"
"path/filepath"
+ "reflect"
+ "slices"
"strconv"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
@@ -79,12 +82,18 @@ type CommonProperties struct {
// list of java libraries that will be compiled into the resulting jar
Static_libs []string `android:"arch_variant"`
+ // list of java libraries that should not be used to build this module
+ Exclude_static_libs []string `android:"arch_variant"`
+
// manifest file to be included in resulting jar
Manifest *string `android:"path"`
// if not blank, run jarjar using the specified rules file
Jarjar_rules *string `android:"path,arch_variant"`
+ // if not blank, used as prefix to generate repackage rule
+ Jarjar_prefix *string
+
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -129,7 +138,7 @@ type CommonProperties struct {
// supported at compile time. It should only be needed to compile tests in
// packages that exist in libcore and which are inconvenient to move
// elsewhere.
- Patch_module *string `android:"arch_variant"`
+ Patch_module *string
Jacoco struct {
// List of classes to include for instrumentation with jacoco to collect coverage
@@ -184,6 +193,28 @@ type CommonProperties struct {
// A list of java_library instances that provide additional hiddenapi annotations for the library.
Hiddenapi_additional_annotations []string
+
+ // Additional srcJars tacked in by GeneratedJavaLibraryModule
+ Generated_srcjars []android.Path `android:"mutated"`
+
+ // intermediate aconfig cache file tacked in by GeneratedJavaLibraryModule
+ Aconfig_Cache_files []android.Path `android:"mutated"`
+
+ // If true, then only the headers are built and not the implementation jar.
+ Headers_only *bool
+
+ // A list of files or dependencies to make available to the build sandbox. This is
+ // useful if source files are symlinks, the targets of the symlinks must be listed here.
+ // Note that currently not all actions implemented by android_apps are sandboxed, so you
+ // may only see this being necessary in lint builds.
+ Compile_data []string `android:"path"`
+
+ // Property signifying whether the module compiles stubs or not.
+ // Should be set to true when srcs of this module are stub files.
+ // This property does not need to be set to true when the module depends on
+ // the stubs via libs, but should be set to true when the module depends on
+ // the stubs via static libs.
+ Is_stubs_module *bool
}
// Properties that are specific to device modules. Host module factories should not add these when
@@ -198,10 +229,6 @@ type DeviceProperties struct {
// If the SDK kind is empty, it will be set to public.
Sdk_version *string
- // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
- // Defaults to sdk_version if not set. See sdk_version for possible values.
- Min_sdk_version *string
-
// if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
// Defaults to empty string "". See sdk_version for possible values.
Max_sdk_version *string
@@ -274,13 +301,17 @@ type DeviceProperties struct {
HiddenAPIFlagFileProperties
}
-// Device properties that can be overridden by overriding module (e.g. override_android_app)
-type OverridableDeviceProperties struct {
+// Properties that can be overridden by overriding module (e.g. override_android_app)
+type OverridableProperties struct {
// set the name of the output. If not set, `name` is used.
// To override a module with this property set, overriding module might need to set this as well.
// Otherwise, both the overridden and the overriding modules will have the same output name, which
// can cause the duplicate output error.
Stem *string
+
+ // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
+ // Defaults to sdk_version if not set. See sdk_version for possible values.
+ Min_sdk_version *string
}
// Functionality common to Module and Import
@@ -395,7 +426,6 @@ type Module struct {
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
// Functionality common to Module and Import.
embeddableInModuleAndImport
@@ -404,12 +434,15 @@ type Module struct {
protoProperties android.ProtoProperties
deviceProperties DeviceProperties
- overridableDeviceProperties OverridableDeviceProperties
+ overridableProperties OverridableProperties
+ sourceProperties android.SourceProperties
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
+ repackagedHeaderJarFile android.Path
+
// jar file containing implementation classes including static library dependencies but no
// resources
implementationJarFile android.Path
@@ -421,6 +454,9 @@ type Module struct {
srcJarArgs []string
srcJarDeps android.Paths
+ // the source files of this module and all its static dependencies
+ transitiveSrcFiles *android.DepSet[android.Path]
+
// jar file containing implementation classes and resources including static library
// dependencies
implementationAndResourcesJar android.Path
@@ -471,6 +507,9 @@ type Module struct {
// expanded Jarjar_rules
expandJarjarRules android.Path
+ // jarjar rule for inherited jarjar rules
+ repackageJarjarRules android.Path
+
// Extra files generated by the module type to be added as java resources.
extraResources android.Paths
@@ -483,9 +522,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
@@ -493,6 +529,36 @@ type Module struct {
maxSdkVersion android.ApiLevel
sourceExtensions []string
+
+ annoSrcJars android.Paths
+
+ // output file name based on Stem property.
+ // This should be set in every ModuleWithStem's GenerateAndroidBuildActions
+ // or the module should override Stem().
+ stem string
+
+ // Values that will be set in the JarJarProvider data for jarjar repackaging,
+ // and merged with our dependencies' rules.
+ jarjarRenameRules map[string]string
+
+ stubsLinkType StubsLinkType
+
+ // Paths to the aconfig intermediate cache files that are provided by the
+ // java_aconfig_library or java_library modules that are statically linked
+ // to this module. Does not contain cache files from all transitive dependencies.
+ aconfigCacheFiles android.Paths
+}
+
+var _ android.InstallableModule = (*Module)(nil)
+
+// To satisfy the InstallableModule interface
+func (j *Module) EnforceApiContainerChecks() bool {
+ return true
+}
+
+// Overrides android.ModuleBase.InstallInProduct()
+func (j *Module) InstallInProduct() bool {
+ return j.ProductSpecific()
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -551,9 +617,21 @@ func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
}
}
+func (j *Module) checkHeadersOnly(ctx android.ModuleContext) {
+ if _, ok := ctx.Module().(android.SdkContext); ok {
+ headersOnly := proptools.Bool(j.properties.Headers_only)
+ installable := proptools.Bool(j.properties.Installable)
+
+ if headersOnly && installable {
+ ctx.PropertyErrorf("headers_only", "This module has conflicting settings. headers_only is true which, which means this module doesn't generate an implementation jar. However installable is set to true.")
+ }
+ }
+}
+
func (j *Module) addHostProperties() {
j.AddProperties(
&j.properties,
+ &j.overridableProperties,
&j.protoProperties,
&j.usesLibraryProperties,
)
@@ -563,7 +641,6 @@ func (j *Module) addHostAndDeviceProperties() {
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
- &j.overridableDeviceProperties,
&j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
@@ -581,31 +658,24 @@ func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) {
// Populate with package rules from the properties.
hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties)
- ctx.SetProvider(hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
+ android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}
-func (j *Module) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
- case android.DefaultDistTag:
- return android.Paths{j.outputFile}, nil
- case ".jar":
- return android.Paths{j.implementationAndResourcesJar}, nil
- case ".hjar":
- return android.Paths{j.headerJarFile}, nil
- case ".proguard_map":
- if j.dexer.proguardDictionary.Valid() {
- return android.Paths{j.dexer.proguardDictionary.Path()}, nil
- }
- return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+// helper method for java modules to set OutputFilesProvider
+func setOutputFiles(ctx android.ModuleContext, m Module) {
+ ctx.SetOutputFiles(append(android.Paths{m.outputFile}, m.extraOutputFiles...), "")
+ ctx.SetOutputFiles(android.Paths{m.outputFile}, android.DefaultDistTag)
+ ctx.SetOutputFiles(android.Paths{m.implementationAndResourcesJar}, ".jar")
+ ctx.SetOutputFiles(android.Paths{m.headerJarFile}, ".hjar")
+ if m.dexer.proguardDictionary.Valid() {
+ ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map")
+ }
+ ctx.SetOutputFiles(m.properties.Generated_srcjars, ".generated_srcjars")
+ if m.linter.outputs.xml != nil {
+ ctx.SetOutputFiles(android.Paths{m.linter.outputs.xml}, ".lint")
}
}
-var _ android.OutputFileProducer = (*Module)(nil)
-
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
initJavaModule(module, hod, false)
}
@@ -641,8 +711,9 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
// Force enable the instrumentation for java code that is built for APEXes ...
// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
// doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+
if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
return true
@@ -666,12 +737,16 @@ func (j *Module) SystemModules() string {
}
func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- if j.deviceProperties.Min_sdk_version != nil {
- return android.ApiLevelFrom(ctx, *j.deviceProperties.Min_sdk_version)
+ if j.overridableProperties.Min_sdk_version != nil {
+ return android.ApiLevelFrom(ctx, *j.overridableProperties.Min_sdk_version)
}
return j.SdkVersion(ctx).ApiLevel
}
+func (j *Module) GetDeviceProperties() *DeviceProperties {
+ return &j.deviceProperties
+}
+
func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.deviceProperties.Max_sdk_version != nil {
return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
@@ -724,12 +799,14 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
}
libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+
+ j.properties.Static_libs = android.RemoveListFromList(j.properties.Static_libs, j.properties.Exclude_static_libs)
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
- if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
+ if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
// Require java_sdk_library at inter-partition java dependency to ensure stable
// interface between partitions. If inter-partition java_library dependency is detected,
// raise build error because java_library doesn't have a stable interface.
@@ -762,9 +839,11 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if dep != nil {
if component, ok := dep.(SdkLibraryComponentDependency); ok {
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
- // Add library as optional if it's one of the optional compatibility libs.
+ // Add library as optional if it's one of the optional compatibility libs or it's
+ // explicitly listed in the optional_uses_libs property.
tag := usesLibReqTag
- if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
+ if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
+ android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) {
tag = usesLibOptTag
}
ctx.AddVariationDependencies(nil, tag, *lib)
@@ -961,8 +1040,16 @@ func (j *Module) collectJavacFlags(
ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
// javac flags.
javacFlags := j.properties.Javacflags
+ var needsDebugInfo bool
+
+ needsDebugInfo = false
+ for _, flag := range javacFlags {
+ if strings.HasPrefix(flag, "-g") {
+ needsDebugInfo = true
+ }
+ }
- if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() && !needsDebugInfo {
// For non-host binaries, override the -g flag passed globally to remove
// local variable debug info to reduce disk and memory usage.
javacFlags = append(javacFlags, "-g:source,lines")
@@ -971,44 +1058,18 @@ func (j *Module) collectJavacFlags(
if flags.javaVersion.usesJavaModules() {
javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.javacflags", "JDK version defaults to higher than 9")
+ }
+ if flags.javaVersion.usesJavaModules() {
if j.properties.Patch_module != nil {
// Manually specify build directory in case it is not under the repo root.
// (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
// just adding a symlink under the root doesn't help.)
patchPaths := []string{".", ctx.Config().SoongOutDir()}
- // b/150878007
- //
- // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
- // execution root for --patch-module. If this javac command line is
- // invoked within Bazel's execution root working directory, the top
- // level directories (e.g. libcore/, tools/, frameworks/) are all
- // symlinks. JDK9 javac does not traverse into symlinks, which causes
- // --patch-module to fail source file lookups when invoked in the
- // execution root.
- //
- // Short of patching javac or enumerating *all* directories as possible
- // input dirs, manually add the top level dir of the source files to be
- // compiled.
- topLevelDirs := map[string]bool{}
- for _, srcFilePath := range srcFiles {
- srcFileParts := strings.Split(srcFilePath.String(), "/")
- // Ignore source files that are already in the top level directory
- // as well as generated files in the out directory. The out
- // directory may be an absolute path, which means srcFileParts[0] is the
- // empty string, so check that as well. Note that "out" in Bazel's execution
- // root is *not* a symlink, which doesn't cause problems for --patch-modules
- // anyway, so it's fine to not apply this workaround for generated
- // source files.
- if len(srcFileParts) > 1 &&
- srcFileParts[0] != "" &&
- srcFileParts[0] != "out" {
- topLevelDirs[srcFileParts[0]] = true
- }
- }
- patchPaths = append(patchPaths, android.SortedKeys(topLevelDirs)...)
-
classPath := flags.classpath.FormJavaClassPath("")
if classPath != "" {
patchPaths = append(patchPaths, classPath)
@@ -1036,7 +1097,24 @@ func (j *Module) AddJSONData(d *map[string]interface{}) {
}
-func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
+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 android.Paths) {
+
+ // Auto-propagating jarjar rules
+ jarjarProviderData := j.collectJarJarRules(ctx)
+ if jarjarProviderData != nil {
+ android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
+ text := getJarJarRuleText(jarjarProviderData)
+ if text != "" {
+ ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
+ android.WriteFileRule(ctx, ruleTextFile, text)
+ j.repackageJarjarRules = ruleTextFile
+ }
+ }
+
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
deps := j.collectDeps(ctx)
@@ -1044,6 +1122,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
if flags.javaVersion.usesJavaModules() {
j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.srcs", "JDK version defaults to higher than 9")
}
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
@@ -1074,16 +1155,15 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
srcJars := srcFiles.FilterByExt(".srcjar")
srcJars = append(srcJars, deps.srcJars...)
- if aaptSrcJar != nil {
- srcJars = append(srcJars, aaptSrcJar)
- }
+ srcJars = append(srcJars, extraSrcJars...)
+ srcJars = append(srcJars, j.properties.Generated_srcjars...)
srcFiles = srcFiles.FilterOutByExt(".srcjar")
if j.properties.Jarjar_rules != nil {
j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
}
- jarName := ctx.ModuleName() + ".jar"
+ jarName := j.Stem() + ".jar"
var uniqueJavaFiles android.Paths
set := make(map[string]bool)
@@ -1105,6 +1185,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
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
@@ -1118,6 +1199,45 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
var kotlinJars android.Paths
var kotlinHeaderJars android.Paths
+ // Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
+ // any dependencies so that it can override any non-final R classes from dependencies with the
+ // final R classes from the app.
+ flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...)
+
+ j.aconfigCacheFiles = append(deps.aconfigProtoFiles, j.properties.Aconfig_Cache_files...)
+
+ // If compiling headers then compile them and skip the rest
+ if proptools.Bool(j.properties.Headers_only) {
+ if srcFiles.HasExt(".kt") {
+ ctx.ModuleErrorf("Compiling headers_only with .kt not supported")
+ }
+ if ctx.Config().IsEnvFalse("TURBINE_ENABLED") || disableTurbine {
+ ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.")
+ }
+
+ _, j.headerJarFile, _ =
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
+ extraCombinedJars)
+ if ctx.Failed() {
+ return
+ }
+
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
+ })
+
+ j.outputFile = j.headerJarFile
+ return
+ }
+
if srcFiles.HasExt(".kt") {
// When using kotlin sources turbine is used to generate annotation processor sources,
// including for annotation processors that generate API, so we can use turbine for
@@ -1178,10 +1298,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
return
}
+ kotlinJarPath := j.repackageFlagsIfNecessary(ctx, kotlinJar.OutputPath, jarName, "kotlinc")
+
// Make javac rule depend on the kotlinc rule
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
- kotlinJars = append(kotlinJars, kotlinJar)
+ kotlinJars = append(kotlinJars, kotlinJarPath)
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
// Jar kotlin classes into the final jar after javac
@@ -1196,7 +1318,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
- jars := append(android.Paths(nil), kotlinJars...)
+ jars := slices.Clone(kotlinJars)
j.compiledSrcJars = srcJars
@@ -1211,8 +1333,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
+ extraJars := append(slices.Clone(kotlinHeaderJars), extraCombinedJars...)
+ headerJarFileWithoutDepsOrJarjar, j.headerJarFile, j.repackagedHeaderJarFile =
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
if ctx.Failed() {
return
}
@@ -1241,8 +1364,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// 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, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1259,16 +1383,26 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
jars = append(jars, classes)
}
}
+ // Assume approximately 5 sources per srcjar.
+ // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean
+ // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files.
if len(srcJars) > 0 {
- classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
- nil, srcJars, flags, extraJarDeps)
- jars = append(jars, classes)
+ startIdx := len(shardSrcs)
+ shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5)
+ for idx, shardSrcJars := range shardSrcJarsList {
+ classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
+ nil, shardSrcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
+ jars = append(jars, classes)
+ }
}
} else {
classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
jars = append(jars, classes)
}
if ctx.Failed() {
@@ -1276,6 +1410,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
+ jars = append(jars, extraCombinedJars...)
+
j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
var includeSrcJar android.WritablePath
@@ -1372,12 +1508,20 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// prebuilt dependencies until we support modules in the platform build, so there shouldn't be
// any if len(jars) == 1.
+ // moduleStubLinkType determines if the module is the TopLevelStubLibrary generated
+ // from sdk_library. The TopLevelStubLibrary contains only one static lib,
+ // either with .from-source or .from-text suffix.
+ // outputFile should be agnostic to the build configuration,
+ // thus "combine" the single static lib in order to prevent the static lib from being exposed
+ // to the copy rules.
+ stub, _ := moduleStubLinkType(ctx.ModuleName())
+
// Transform the single path to the jar into an OutputPath as that is required by the following
// code.
- if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
+ if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok && !stub {
// The path contains an embedded OutputPath so reuse that.
outputFile = moduleOutPath.OutputPath
- } else if outputPath, ok := jars[0].(android.OutputPath); ok {
+ } else if outputPath, ok := jars[0].(android.OutputPath); ok && !stub {
// The path is an OutputPath so reuse it directly.
outputFile = outputPath
} else {
@@ -1446,7 +1590,13 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.implementationJarFile = outputFile
if j.headerJarFile == nil {
- j.headerJarFile = j.implementationJarFile
+ // If this module couldn't generate a header jar (for example due to api generating annotation processors)
+ // then use the implementation jar. Run it through zip2zip first to remove any files in META-INF/services
+ // so that javac on modules that depend on this module don't pick up annotation processors (which may be
+ // missing their implementations) from META-INF/services/javax.annotation.processing.Processor.
+ headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
+ convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
+ j.headerJarFile = headerJarFile
}
// enforce syntax check to jacoco filters for any build (http://b/183622051)
@@ -1473,7 +1623,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
compileDex := j.dexProperties.Compile_dex
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
if compileDex == nil {
compileDex = proptools.BoolPtr(true)
@@ -1486,7 +1636,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) {
if j.hasCode(ctx) {
if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles,
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
@@ -1498,11 +1648,28 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
classesJar: implementationAndResourcesJar,
jarName: jarName,
}
- dexOutputFile = j.dexer.compileDex(ctx, params)
+ if j.GetProfileGuided() && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting() {
+ ctx.PropertyErrorf("enable_profile_rewriting",
+ "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.",
+ )
+ }
+ if j.EnableProfileRewriting() {
+ profile := j.GetProfile()
+ if profile == "" || !j.GetProfileGuided() {
+ ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
+ }
+ params.artProfileInput = &profile
+ }
+ dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
if ctx.Failed() {
return
}
+ // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
+ if dexArtProfileOutput != nil {
+ j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput)
+ }
+
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
@@ -1511,7 +1678,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
- TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
dexOutputFile = combinedAlignedJar
} else {
dexOutputFile = combinedJar
@@ -1528,7 +1695,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
+ libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
+ if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
+ libName = strings.TrimSuffix(libName, ".impl")
+ }
+ j.dexpreopt(ctx, libName, dexOutputFile)
outputFile = dexOutputFile
} else {
@@ -1546,30 +1717,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
if ctx.Device() {
- lintSDKVersion := func(apiLevel android.ApiLevel) int {
+ lintSDKVersion := func(apiLevel android.ApiLevel) android.ApiLevel {
if !apiLevel.IsPreview() {
- return apiLevel.FinalInt()
+ return apiLevel
} else {
- // When running metalava, we pass --version-codename. When that value
- // is not REL, metalava will add 1 to the --current-version argument.
- // On old branches, PLATFORM_SDK_VERSION is the latest version (for that
- // branch) and the codename is REL, except potentially on the most
- // recent non-master branch. On that branch, it goes through two other
- // phases before it gets to the phase previously described:
- // - PLATFORM_SDK_VERSION has not been updated yet, and the codename
- // is not rel. This happens for most of the internal branch's life
- // while the branch has been cut but is still under active development.
- // - PLATFORM_SDK_VERSION has been set, but the codename is still not
- // REL. This happens briefly during the release process. During this
- // state the code to add --current-version is commented out, and then
- // that commenting out is reverted after the codename is set to REL.
- // On the master branch, the PLATFORM_SDK_VERSION always represents a
- // prior version and the codename is always non-REL.
- //
- // We need to add one here to match metalava adding 1. Technically
- // this means that in the state described in the second bullet point
- // above, this number is 1 higher than it should be.
- return ctx.Config().PlatformSdkVersion().FinalInt() + 1
+ return ctx.Config().DefaultAppTargetSdk(ctx)
}
}
@@ -1584,28 +1736,35 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
+ j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data)
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
j.linter.buildModuleReportZip = true
}
j.linter.lint(ctx)
}
+ j.collectTransitiveSrcFiles(ctx, srcFiles)
+
ctx.CheckbuildFile(outputFile)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
- ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
- ResourceJars: android.PathsIfNonNil(j.resourceJar),
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- SrcJarArgs: j.srcJarArgs,
- SrcJarDeps: j.srcJarDeps,
- ExportedPlugins: j.exportedPluginJars,
- ExportedPluginClasses: j.exportedPluginClasses,
- ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- JacocoReportClassesFile: j.jacocoReportClassesFile,
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
+ ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
+ ResourceJars: android.PathsIfNonNil(j.resourceJar),
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ SrcJarArgs: j.srcJarArgs,
+ SrcJarDeps: j.srcJarDeps,
+ TransitiveSrcFiles: j.transitiveSrcFiles,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ JacocoReportClassesFile: j.jacocoReportClassesFile,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1616,6 +1775,52 @@ func (j *Module) useCompose() bool {
return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
}
+func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
+ depTag := ctx.OtherModuleDependencyTag(m)
+
+ if depProguardInfo.UnconditionallyExportedProguardFlags != nil {
+ transitiveUnconditionalExportedFlags = append(transitiveUnconditionalExportedFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
+ transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
+ }
+
+ if depTag == staticLibTag && depProguardInfo.ProguardFlagsFiles != nil {
+ transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.ProguardFlagsFiles)
+ }
+ })
+
+ return transitiveProguardFlags, transitiveUnconditionalExportedFlags
+}
+
+func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+
+ directUnconditionalExportedFlags := android.Paths{}
+ proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)
+ exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files)
+ if exportUnconditionally {
+ // if we explicitly export, then our unconditional exports are the same as our transitive flags
+ transitiveUnconditionalExportedFlags = transitiveProguardFlags
+ directUnconditionalExportedFlags = proguardFlagsForThisModule
+ }
+
+ return ProguardSpecInfo{
+ Export_proguard_flags_files: exportUnconditionally,
+ ProguardFlagsFiles: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ proguardFlagsForThisModule,
+ transitiveProguardFlags,
+ ),
+ UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ directUnconditionalExportedFlags,
+ transitiveUnconditionalExportedFlags,
+ ),
+ }
+
+}
+
// Returns a copy of the supplied flags, but with all the errorprone-related
// fields copied to the regular build's fields.
func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
@@ -1635,20 +1840,26 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
kzipName := pathtools.ReplaceExtension(jarName, "kzip")
+ annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
if idx >= 0 {
kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
+ annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar")
jarName += strconv.Itoa(idx)
}
classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
- TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
+ TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
- if ctx.Config().EmitXrefRules() {
+ if ctx.Config().EmitXrefRules() && ctx.Module() == ctx.PrimaryModule() {
extractionFile := android.PathForModuleOut(ctx, kzipName)
emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
j.kytheFiles = append(j.kytheFiles, extractionFile)
}
+ if len(flags.processorPath) > 0 {
+ j.annoSrcJars = append(j.annoSrcJars, annoSrcJar)
+ }
+
return classes
}
@@ -1679,7 +1890,7 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar android.Path) {
+ extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1687,7 +1898,7 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
jars = append(jars, turbineJar)
headerJar = turbineJar
@@ -1712,11 +1923,22 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules)
jarjarAndDepsHeaderJar = jarjarFile
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
}
- return headerJar, jarjarAndDepsHeaderJar
+ if j.repackageJarjarRules != nil {
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-turbine-jarjar", jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, jarjarAndDepsHeaderJar, j.repackageJarjarRules)
+ jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile
+ if ctx.Failed() {
+ return nil, nil, nil
+ }
+ } else {
+ jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar
+ }
+
+ return headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
@@ -1734,44 +1956,47 @@ func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
type providesTransitiveHeaderJars struct {
// set of header jars for all transitive libs deps
- transitiveLibsHeaderJars *android.DepSet
+ transitiveLibsHeaderJars *android.DepSet[android.Path]
// set of header jars for all transitive static libs deps
- transitiveStaticLibsHeaderJars *android.DepSet
+ transitiveStaticLibsHeaderJars *android.DepSet[android.Path]
}
-func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet {
+func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet[android.Path] {
return j.transitiveLibsHeaderJars
}
-func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet {
+func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet[android.Path] {
return j.transitiveStaticLibsHeaderJars
}
func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) {
directLibs := android.Paths{}
directStaticLibs := android.Paths{}
- transitiveLibs := []*android.DepSet{}
- transitiveStaticLibs := []*android.DepSet{}
+ transitiveLibs := []*android.DepSet[android.Path]{}
+ transitiveStaticLibs := []*android.DepSet[android.Path]{}
ctx.VisitDirectDeps(func(module android.Module) {
// don't add deps of the prebuilt version of the same library
if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
return
}
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if dep.TransitiveLibsHeaderJars != nil {
- transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
- }
- if dep.TransitiveStaticLibsHeaderJars != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
- }
-
+ dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
tag := ctx.OtherModuleDependencyTag(module)
_, isUsesLibDep := tag.(usesLibraryDependencyTag)
if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
directLibs = append(directLibs, dep.HeaderJars...)
} else if tag == staticLibTag {
directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
+ } else {
+ // Don't propagate transitive libs for other kinds of dependencies.
+ return
+ }
+
+ if dep.TransitiveLibsHeaderJars != nil {
+ transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
}
})
j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
@@ -1792,7 +2017,7 @@ func (j *Module) ImplementationJars() android.Paths {
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJarBuildPath() OptionalDexJarPath {
+func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile
}
@@ -1825,9 +2050,9 @@ 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()...)
}
func (j *Module) CompilerDeps() []string {
@@ -1865,13 +2090,31 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi
}
func (j *Module) Stem() string {
- return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name())
+ if j.stem == "" {
+ panic("Stem() called before stem property was set")
+ }
+ return j.stem
}
func (j *Module) JacocoReportClassesFile() android.Path {
return j.jacocoReportClassesFile
}
+func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
+ var fromDeps []*android.DepSet[android.Path]
+ ctx.VisitDirectDeps(func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ if tag == staticLibTag {
+ depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if depInfo.TransitiveSrcFiles != nil {
+ fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
+ }
+ }
+ })
+
+ j.transitiveSrcFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
+}
+
func (j *Module) IsInstallable() bool {
return Bool(j.properties.Installable)
}
@@ -1923,19 +2166,22 @@ type moduleWithSdkDep interface {
func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
switch name {
- case android.SdkCore.JavaLibraryName(ctx.Config()), "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ case android.SdkCore.DefaultJavaLibraryName(),
+ "legacy.core.platform.api.stubs",
+ "stable.core.platform.api.stubs",
"stub-annotations", "private-stub-annotations-jar",
- "core-lambda-stubs", "core-generated-annotation-stubs":
+ "core-lambda-stubs",
+ "core-generated-annotation-stubs":
return javaCore, true
- case android.SdkPublic.JavaLibraryName(ctx.Config()):
+ case android.SdkPublic.DefaultJavaLibraryName():
return javaSdk, true
- case android.SdkSystem.JavaLibraryName(ctx.Config()):
+ case android.SdkSystem.DefaultJavaLibraryName():
return javaSystem, true
- case android.SdkModule.JavaLibraryName(ctx.Config()):
+ case android.SdkModule.DefaultJavaLibraryName():
return javaModule, true
- case android.SdkSystemServer.JavaLibraryName(ctx.Config()):
+ case android.SdkSystemServer.DefaultJavaLibraryName():
return javaSystemServer, true
- case android.SdkTest.JavaLibraryName(ctx.Config()):
+ case android.SdkTest.DefaultJavaLibraryName():
return javaSystem, true
}
@@ -2031,15 +2277,14 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if sdkLinkType != javaPlatform &&
- ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
- // dep is a sysprop implementation library, but this module is not linking against
- // the platform, so it gets the sysprop public stubs library instead. Replace
- // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
- syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
- dep = syspropDep.JavaInfo
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if sdkLinkType != javaPlatform {
+ if syspropDep, ok := android.OtherModuleProvider(ctx, module, SyspropPublicStubInfoProvider); ok {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ dep = syspropDep.JavaInfo
+ }
}
switch tag {
case bootClasspathTag:
@@ -2050,6 +2295,10 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...)
+ if len(dep.RepackagedHeaderJars) == 1 && !slices.Contains(dep.HeaderJars, dep.RepackagedHeaderJars[0]) {
+ deps.classpath = append(deps.classpath, dep.RepackagedHeaderJars...)
+ deps.dexClasspath = append(deps.dexClasspath, dep.RepackagedHeaderJars...)
+ }
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
@@ -2069,6 +2318,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
// annotation processor that generates API is incompatible with the turbine
// optimization.
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
case pluginTag:
if plugin, ok := module.(*Plugin); ok {
if plugin.pluginProperties.Processor_class != nil {
@@ -2111,7 +2361,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case syspropPublicStubDepTag:
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
- ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ android.SetProvider(ctx, SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
JavaInfo: dep,
})
}
@@ -2127,6 +2377,11 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.staticJars = append(deps.staticJars, dep.Srcs()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
}
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
+ switch tag {
+ case staticLibTag:
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
+ }
} else {
switch tag {
case bootClasspathTag:
@@ -2149,11 +2404,320 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
addCLCFromDep(ctx, module, j.classLoaderContexts)
+ addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary)
})
return deps
}
+// Provider for jarjar renaming rules.
+//
+// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be
+// passed to all rdeps. The typical way that these renamings will NOT be inherited is when a module
+// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on
+// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
+// be renamed from that module.
+// TODO: Add another property to suppress the forwarding of
+type DependencyUse int
+
+const (
+ RenameUseInvalid DependencyUse = iota
+ RenameUseInclude
+ 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
+}
+
+func (this JarJarProviderData) GetDebugString() string {
+ result := ""
+ for _, k := range android.SortedKeys(this.Rename) {
+ v := this.Rename[k]
+ if strings.Contains(k, "android.companion.virtual.flags.FakeFeatureFlagsImpl") {
+ result += k + "--&gt;" + v + ";"
+ }
+ }
+ return result
+}
+
+var JarJarProvider = blueprint.NewProvider[JarJarProviderData]()
+
+var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"
+
+func init() {
+ android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
+}
+
+// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
+// whether they are java modules or not.
+type BaseJarJarProviderData struct {
+ JarJarProviderData JarJarProviderData
+}
+
+func (this BaseJarJarProviderData) GetDebugString() string {
+ return this.JarJarProviderData.GetDebugString()
+}
+
+var BaseJarJarProvider = blueprint.NewProvider[BaseJarJarProviderData]()
+
+// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called.
+// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have
+// either JarJarProvider or BaseJarJarProvider.
+func mergeJarJarPrefixes(ctx android.ModuleContext) {
+ mod := ctx.Module()
+ // Explicitly avoid propagating into some module types.
+ switch reflect.TypeOf(mod).String() {
+ case "*java.Droidstubs":
+ return
+ }
+ jarJarData := collectDirectDepsProviders(ctx)
+ if jarJarData != nil {
+ providerData := BaseJarJarProviderData{
+ JarJarProviderData: *jarJarData,
+ }
+ android.SetProvider(ctx, BaseJarJarProvider, providerData)
+ }
+
+}
+
+// Add a jarjar renaming rule to this module, to be inherited to all dependent modules.
+func (module *Module) addJarJarRenameRule(original string, renamed string) {
+ if module.jarjarRenameRules == nil {
+ module.jarjarRenameRules = make(map[string]string)
+ }
+ module.jarjarRenameRules[original] = renamed
+}
+
+func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) {
+ // Gather repackage information from deps
+ // If the dep jas a JarJarProvider, it is used. Otherwise, any BaseJarJarProvider is used.
+
+ module := ctx.Module()
+ moduleName := module.Name()
+
+ ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
+ 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
+ // indicate that it has been verified to be the case.
+ //
+ // Note well: there are probably cases that are getting to the unconditional return
+ // and are therefore wrong.
+ shouldIncludeRenames := func() (DependencyUse, string) {
+ if moduleName == m.Name() {
+ return RenameUseInclude, "name" // 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"
+ }
+ }
+ }
+ if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
+ return RenameUseExclude, "tags"
+ }
+ if _, ok := m.(SdkLibraryDependency); ok {
+ switch tag {
+ case sdkLibTag, libTag:
+ return RenameUseExclude, "sdklibdep" // matches collectDeps()
+ }
+ return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps()
+ } else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ switch ji.StubsLinkType {
+ case Stubs:
+ return RenameUseExclude, "info"
+ case Implementation:
+ return RenameUseInclude, "info"
+ 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":
+ // Probably a java_aconfig_library module.
+ // TODO: make this check better.
+ return RenameUseInclude, "reflect"
+ }
+ switch tag {
+ case bootClasspathTag:
+ return RenameUseExclude, "tagswitch"
+ case sdkLibTag, libTag, instrumentationForTag:
+ return RenameUseInclude, "tagswitch"
+ case java9LibTag:
+ return RenameUseExclude, "tagswitch"
+ case staticLibTag:
+ return RenameUseInclude, "tagswitch"
+ case pluginTag:
+ return RenameUseInclude, "tagswitch"
+ case errorpronePluginTag:
+ return RenameUseInclude, "tagswitch"
+ case exportedPluginTag:
+ return RenameUseInclude, "tagswitch"
+ case kotlinStdlibTag, kotlinAnnotationsTag:
+ return RenameUseExclude, "tagswitch"
+ case kotlinPluginTag:
+ return RenameUseInclude, "tagswitch"
+ default:
+ return RenameUseExclude, "tagswitch"
+ }
+ } else if _, ok := m.(android.SourceFileProducer); ok {
+ switch tag {
+ case sdkLibTag, libTag, staticLibTag:
+ return RenameUseInclude, "srcfile"
+ default:
+ return RenameUseExclude, "srcfile"
+ }
+ } else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
+ return RenameUseInclude, "aconfig_declarations_group"
+ } else {
+ switch tag {
+ case bootClasspathTag:
+ return RenameUseExclude, "else"
+ case systemModulesTag:
+ return RenameUseInclude, "else"
+ }
+ }
+ // 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"
+ }
+
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ RenameUse: make([]RenameUseElement, 0),
+ }
+ }
+ how, why := shouldIncludeRenames()
+ result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why})
+ if how != RenameUseInclude {
+ // Nothing to merge.
+ return
+ }
+
+ merge := func(theirs *JarJarProviderData) {
+ for orig, renamed := range theirs.Rename {
+ if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" {
+ result.Rename[orig] = renamed
+ } else if preexisting != "" && renamed != "" && preexisting != renamed {
+ if strings.HasPrefix(preexisting, overridableJarJarPrefix) {
+ result.Rename[orig] = renamed
+ } else if !strings.HasPrefix(renamed, overridableJarJarPrefix) {
+ ctx.ModuleErrorf("1. Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting, ctx.ModuleName(), m.Name())
+ continue
+ }
+ }
+ }
+ }
+ if theirs, ok := android.OtherModuleProvider(ctx, m, JarJarProvider); ok {
+ merge(&theirs)
+ } else if theirs, ok := android.OtherModuleProvider(ctx, m, BaseJarJarProvider); ok {
+ // TODO: if every java.Module should have a JarJarProvider, and we find only the
+ // BaseJarJarProvider, then there is a bug. Consider seeing if m can be cast
+ // to java.Module.
+ merge(&theirs.JarJarProviderData)
+ }
+ })
+ return
+}
+
+func (this Module) GetDebugString() string {
+ return "sdk_version=" + proptools.String(this.deviceProperties.Sdk_version)
+}
+
+// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
+// us, and if it's been set, apply the jarjar_prefix property to rename them.
+func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData {
+ // Gather repackage information from deps
+ result := collectDirectDepsProviders(ctx)
+
+ // Update that with entries we've stored for ourself
+ for orig, renamed := range module.jarjarRenameRules {
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ }
+ }
+ if renamed != "" {
+ if preexisting, exists := (*result).Rename[orig]; exists && preexisting != renamed {
+ ctx.ModuleErrorf("Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting)
+ continue
+ }
+ }
+ (*result).Rename[orig] = renamed
+ }
+
+ // If there are no renamings, then jarjar_prefix does nothing, so skip the extra work.
+ if result == nil {
+ return nil
+ }
+
+ // If they've given us a jarjar_prefix property, then we will use that to rename any classes
+ // that have not yet been renamed.
+ prefix := proptools.String(module.properties.Jarjar_prefix)
+ if prefix != "" {
+ if prefix[0] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not start with '.'")
+ return nil
+ }
+ if prefix[len(prefix)-1] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not end with '.'")
+ return nil
+ }
+
+ var updated map[string]string
+ for orig, renamed := range (*result).Rename {
+ if renamed == "" {
+ if updated == nil {
+ updated = make(map[string]string)
+ }
+ updated[orig] = prefix + "." + orig
+ }
+ }
+ for orig, renamed := range updated {
+ (*result).Rename[orig] = renamed
+ }
+ }
+
+ return result
+}
+
+// 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 := ""
+ for _, orig := range android.SortedKeys(provider.Rename) {
+ renamed := provider.Rename[orig]
+ if renamed != "" {
+ result += "rule " + orig + " " + renamed + "\n"
+ }
+ }
+ return result
+}
+
+// Repackage the flags if the jarjar rule txt for the flags is generated
+func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.WritablePath, jarName, info string) android.WritablePath {
+ if j.repackageJarjarRules == nil {
+ return infile
+ }
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info+jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules)
+ return repackagedJarjarFile
+}
+
func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
deps.processorPath = append(deps.processorPath, pluginJars...)
deps.processorClasses = append(deps.processorClasses, pluginClasses...)
@@ -2175,15 +2739,12 @@ type ModuleWithStem interface {
var _ ModuleWithStem = (*Module)(nil)
-func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- switch ctx.ModuleType() {
- case "java_library", "java_library_host", "java_library_static":
- if lib, ok := ctx.Module().(*Library); ok {
- javaLibraryBp2Build(ctx, lib)
- }
- case "java_binary_host":
- if binary, ok := ctx.Module().(*Binary); ok {
- javaBinaryHostBp2Build(ctx, binary)
- }
- }
+type ModuleWithUsesLibrary interface {
+ UsesLibrary() *usesLibrary
}
+
+func (j *Module) UsesLibrary() *usesLibrary {
+ return &j.usesLibrary
+}
+
+var _ ModuleWithUsesLibrary = (*Module)(nil)
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 5d40ec389..6223dede8 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -21,8 +21,8 @@ import (
// isActiveModule returns true if the given module should be considered for boot
// jars, i.e. if it's enabled and the preferred one in case of source and
// prebuilt alternatives.
-func isActiveModule(module android.Module) bool {
- if !module.Enabled() {
+func isActiveModule(ctx android.ConfigAndErrorContext, module android.Module) bool {
+ if !module.Enabled(ctx) {
return false
}
return android.IsModulePreferred(module)
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index f4cef7fa6..77ddf5c05 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -77,7 +77,7 @@ func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyN
// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
var variations []blueprint.Variation
- if apex != "platform" && apex != "system_ext" {
+ if !android.IsConfiguredJarForPlatform(apex) {
// Pick the correct apex variant.
variations = []blueprint.Variation{
{Mutator: "apex", Variation: apex},
@@ -127,7 +127,10 @@ func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variat
// added by addDependencyOntoApexModulePair.
func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
var modules []android.Module
- ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ isActiveModulePred := func(module android.Module) bool {
+ return isActiveModule(ctx, module)
+ }
+ ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) {
t := ctx.OtherModuleDependencyTag(module)
if t == tag {
modules = append(modules, module)
@@ -185,6 +188,9 @@ 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 108fdd483..16209b72e 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"
@@ -76,7 +77,7 @@ func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(child android.M
return javaSdkLibrarySdkMemberType
}
- return javaBootLibsSdkMemberType
+ return JavaBootLibsSdkMemberType
}
func (b bootclasspathFragmentContentDependencyTag) ExportMember() bool {
@@ -228,6 +229,7 @@ type SourceOnlyBootclasspathProperties struct {
type BootclasspathFragmentModule struct {
android.ModuleBase
+ android.DefaultableModuleBase
android.ApexModuleBase
ClasspathFragmentBase
@@ -238,11 +240,9 @@ 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.Path
+ profilePath android.WritablePath
+ profilePathErr error
}
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -256,16 +256,6 @@ type commonBootclasspathFragment interface {
// versioned sdk.
produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
- // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
- // predefined in the bootImageConfig.
- //
- // If it could not create the files then it will return nil. Otherwise, it will return a map from
- // android.ArchType to the predefined paths of the boot image files.
- produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs
-
- // getImageName returns the `image_name` property of this fragment.
- getImageName() *string
-
// getProfilePath returns the path to the boot image profile.
getProfilePath() android.Path
}
@@ -278,6 +268,7 @@ func bootclasspathFragmentFactory() android.Module {
android.InitApexModule(m)
initClasspathFragment(m, BOOTCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(m)
android.AddLoadHook(m, func(ctx android.LoadHookContext) {
// If code coverage has been enabled for the framework then append the properties with
@@ -295,9 +286,6 @@ func bootclasspathFragmentFactory() android.Module {
return
}
}
-
- // Initialize the contents property from the image_name.
- bootclasspathFragmentInitContentsFromImage(ctx, m)
})
return m
}
@@ -308,9 +296,7 @@ func testBootclasspathFragmentFactory() android.Module {
return m
}
-// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if
-// necessary.
-func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) {
+func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.EarlyModuleContext) {
contents := m.properties.Contents
if len(contents) == 0 {
ctx.PropertyErrorf("contents", "required property is missing")
@@ -332,6 +318,18 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext,
// too early in the Soong processing for that to work.
global := dexpreopt.GetGlobalConfig(ctx)
modules := global.ArtApexJars
+ configuredJars := modules.CopyOfJars()
+
+ // Skip the check if the configured jars list is empty as that is a common configuration when
+ // building targets that do not result in a system image.
+ if len(configuredJars) == 0 {
+ return
+ }
+
+ if !reflect.DeepEqual(configuredJars, contents) {
+ ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
+ configuredJars, contents)
+ }
// Make sure that the apex specified in the configuration is consistent and is one for which
// this boot image is available.
@@ -357,42 +355,11 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext,
}
}
-// bootclasspathImageNameContentsConsistencyCheck checks that the configuration that applies to this
-// module (if any) matches the contents.
-//
-// This should be a noop as if image_name="art" then the contents will be set from the ArtApexJars
-// config by bootclasspathFragmentInitContentsFromImage so it will be guaranteed to match. However,
-// in future this will not be the case.
-func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) {
- imageName := proptools.String(b.properties.Image_name)
- if imageName == "art" {
- // Get the configuration for the art apex jars.
- modules := b.getImageConfig(ctx).modules
- configuredJars := modules.CopyOfJars()
-
- // Skip the check if the configured jars list is empty as that is a common configuration when
- // building targets that do not result in a system image.
- if len(configuredJars) == 0 {
- return
- }
-
- contents := b.properties.Contents
- if !reflect.DeepEqual(configuredJars, contents) {
- ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
- configuredJars, contents)
- }
- }
-}
-
-var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{})
+var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider[BootclasspathFragmentApexContentInfo]()
// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
// apex contents.
type BootclasspathFragmentApexContentInfo struct {
- // The configured modules, will be empty if this is from a bootclasspath_fragment that does not
- // set image_name: "art".
- modules android.ConfiguredJarList
-
// Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the
// hidden API encoded dex jar path.
contentModuleDexJarPaths bootDexJarByModule
@@ -405,10 +372,6 @@ type BootclasspathFragmentApexContentInfo struct {
profileInstallPathInApex string
}
-func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList {
- return i.modules
-}
-
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
@@ -424,6 +387,10 @@ func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(mod
}
}
+func (i BootclasspathFragmentApexContentInfo) DexBootJarPathMap() bootDexJarByModule {
+ return i.contentModuleDexJarPaths
+}
+
func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path {
return i.profilePathOnHost
}
@@ -434,6 +401,11 @@ func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string
func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
+
+ // If the module is a default module, do not check the tag
+ if _, ok := dep.(*Defaults); ok {
+ return true
+ }
if IsBootclasspathFragmentContentDepTag(tag) {
// Boot image contents are automatically added to apex.
return true
@@ -479,8 +451,6 @@ func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorCon
for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
// Add a dependency onto a possibly scope specific stub library.
scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule)
- // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable
- scopeSpecificDependency = android.JavaApiLibraryName(ctx.Config(), scopeSpecificDependency)
tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true}
ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency)
}
@@ -504,16 +474,13 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// Only perform a consistency check if this module is the active module. That will prevent an
// unused prebuilt that was created without instrumentation from breaking an instrumentation
// build.
- if isActiveModule(ctx.Module()) {
- b.bootclasspathImageNameContentsConsistencyCheck(ctx)
+ if isActiveModule(ctx, ctx.Module()) {
+ b.bootclasspathFragmentPropertyCheck(ctx)
}
// 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) {
@@ -525,34 +492,15 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
- // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a
- // prebuilt which will not use the image config.
- imageConfig := b.getImageConfig(ctx)
-
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
- var bootImageFiles bootImageOutputs
- if imageConfig != nil {
- // Delegate the production of the boot image files to a module type specific method.
- common := ctx.Module().(commonBootclasspathFragment)
- bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
- b.profilePath = bootImageFiles.profile
-
- if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
- // Zip the boot image files up, if available. This will generate the zip file in a
- // predefined location.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
-
- // Copy the dex jars of this fragment's content modules to their predefined locations.
- copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
- }
- }
-
- // A prebuilt fragment cannot contribute to an apex.
- if !android.IsModulePrebuilt(ctx.Module()) {
- // Provide the apex content info.
- b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
+ if android.IsModulePrebuilt(ctx.Module()) {
+ b.profilePath = ctx.Module().(*PrebuiltBootclasspathFragmentModule).produceBootImageProfile(ctx)
+ } else {
+ b.profilePath = b.produceBootImageProfileFromSource(ctx, contents, hiddenAPIOutput.EncodedBootDexFilesByModule)
+ // Provide the apex content info. A prebuilt fragment cannot contribute to an apex.
+ b.provideApexContentInfo(ctx, hiddenAPIOutput, b.profilePath)
}
// In order for information about bootclasspath_fragment modules to be added to module-info.json
@@ -564,51 +512,50 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
if ctx.Module() != ctx.FinalModule() {
b.HideFromMake()
}
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
-// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
-// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest
-// of the build.
-//
-// This ensures that only a single module will copy its files to the image configuration.
-func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool {
+// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
+// empty string if this module should not provide a boot image profile.
+func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string {
+ // Only use the profile from the module that is preferred.
+ if !isActiveModule(ctx, ctx.Module()) {
+ return ""
+ }
+
// Bootclasspath fragment modules that are for the platform do not produce boot related files.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if apexInfo.IsForPlatform() {
- return false
+ apexInfos, _ := android.ModuleProvider(ctx, android.AllApexInfoProvider)
+ if apexInfos == nil {
+ return ""
}
- // If the image configuration has no modules specified then it means that the build has been
- // configured to build something other than a boot image, e.g. an sdk, so do not try and copy the
- // files.
- if imageConfig.modules.Len() == 0 {
- return false
+ for _, apexInfo := range apexInfos.ApexInfos {
+ for _, apex := range apexInfo.InApexVariants {
+ if isProfileProviderApex(ctx, apex) {
+ return apex
+ }
+ }
}
- // Only copy files from the module that is preferred.
- return isActiveModule(ctx.Module())
+ return ""
}
// provideApexContentInfo creates, initializes and stores the apex content info for use by other
// modules.
-func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) {
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, hiddenAPIOutput *HiddenAPIOutput, profile android.WritablePath) {
// Construct the apex content info from the config.
info := BootclasspathFragmentApexContentInfo{
// Populate the apex content info with paths to the dex jars.
contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule,
}
- if imageConfig != nil {
- info.modules = imageConfig.modules
- global := dexpreopt.GetGlobalConfig(ctx)
- if !global.DisableGenerateProfile {
- info.profilePathOnHost = bootImageFiles.profile
- info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
- }
+ if profile != nil {
+ info.profilePathOnHost = profile
+ info.profileInstallPathInApex = ProfileInstallPathInApex
}
// Make the apex content info available for other modules.
- ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
+ android.SetProvider(ctx, BootclasspathFragmentApexContentInfoProvider, info)
}
// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config
@@ -625,12 +572,12 @@ func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx and
}
func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
+ global := dexpreopt.GetGlobalConfig(ctx)
+
if "art" == proptools.String(b.properties.Image_name) {
- return b.getImageConfig(ctx).modules
+ return global.ArtApexJars
}
- global := dexpreopt.GetGlobalConfig(ctx)
-
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
@@ -649,30 +596,34 @@ 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 {
- ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ if isApexVariant(ctx) && len(unknown) > 0 {
+ 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) {
+ // source bcpf, and prebuilt apex are not selected.
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ }
}
}
return jars
}
-func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
- // Get a map of the image configs that are supported.
- imageConfigs := genBootImageConfigs(ctx)
+var ClasspathFragmentValidationInfoProvider = blueprint.NewProvider[ClasspathFragmentValidationInfo]()
- // Retrieve the config for this image.
- imageNamePtr := b.properties.Image_name
- if imageNamePtr == nil {
- return nil
- }
+type ClasspathFragmentValidationInfo struct {
+ ClasspathFragmentModuleName string
+ UnknownJars []string
+}
- imageName := *imageNamePtr
- imageConfig := imageConfigs[imageName]
- if imageConfig == nil {
- ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedKeys(imageConfigs), ", "))
- return nil
+// Set a provider with the list of jars that have not been added to PRODUCT_APEX_BOOT_JARS
+// The validation will be done in the ctx of the top-level _selected_ apex
+func providerClasspathFragmentValidationInfoProvider(ctx android.ModuleContext, unknown []string) {
+ info := ClasspathFragmentValidationInfo{
+ ClasspathFragmentModuleName: ctx.ModuleName(),
+ UnknownJars: unknown,
}
- return imageConfig
+ android.SetProvider(ctx, ClasspathFragmentValidationInfoProvider, info)
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
@@ -713,26 +664,11 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
hiddenAPIInfo.HiddenAPIFlagOutput = output.HiddenAPIFlagOutput
// Provide it for use by other modules.
- ctx.SetProvider(HiddenAPIInfoProvider, hiddenAPIInfo)
+ android.SetProvider(ctx, HiddenAPIInfoProvider, hiddenAPIInfo)
return output
}
-// retrieveLegacyEncodedBootDexFiles attempts to retrieve the legacy encoded boot dex jar files.
-func retrieveLegacyEncodedBootDexFiles(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
- // If the current bootclasspath_fragment is the active module or a source module then retrieve the
- // encoded dex files, otherwise return an empty map.
- //
- // An inactive (i.e. not preferred) bootclasspath_fragment needs to retrieve the encoded dex jars
- // as they are still needed by an apex. An inactive prebuilt_bootclasspath_fragment does not need
- // to do so and may not yet have access to dex boot jars from a prebuilt_apex/apex_set.
- if isActiveModule(ctx.Module()) || !android.IsModulePrebuilt(ctx.Module()) {
- return extractEncodedDexJarsFromModules(ctx, contents)
- } else {
- return nil
- }
-}
-
// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
// from the properties on this module and its dependencies.
func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) HiddenAPIFlagInput {
@@ -849,7 +785,7 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
}
// Make the information available for the sdk snapshot.
- ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
+ android.SetProvider(ctx, HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
FlagFilesByCategory: flagFilesByCategory,
HiddenAPIFlagOutput: flagOutput,
})
@@ -857,48 +793,22 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
return output
}
-// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- // Only generate the boot image if the configuration does not skip it.
- return b.generateBootImageBuildActions(ctx, imageConfig)
-}
-
-// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
-// module.
-//
-// If it could not create the files then it will return nil. Otherwise, it will return a map from
-// android.ArchType to the predefined paths of the boot image files.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return bootImageOutputs{}
- }
-
- // Bootclasspath fragment modules that are for the platform do not produce a boot image.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if apexInfo.IsForPlatform() {
- return bootImageOutputs{}
+// produceBootImageProfileFromSource builds the boot image profile from the source if it is required.
+func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext, contents []android.Module, modules bootDexJarByModule) android.WritablePath {
+ apex := b.getProfileProviderApex(ctx)
+ if apex == "" {
+ return nil
}
- // Build a profile for the image config and then use that to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
-
- // If dexpreopt of boot image jars should be skipped, generate only a profile.
- if SkipDexpreoptBootJars(ctx) {
- return bootImageOutputs{
- profile: profile,
- }
+ dexPaths := make(android.Paths, 0, len(contents))
+ dexLocations := make([]string, 0, len(contents))
+ for _, module := range contents {
+ dexPaths = append(dexPaths, modules[module.Name()])
+ dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name()+".jar"))
}
- // Build boot image files for the host variants.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
- // Build boot image files for the android variants.
- bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
- // Return the boot image files for the android variants for inclusion in an APEX and to be zipped
- // up for the dist.
- return bootImageFiles
+ // Build a profile for the modules in this fragment.
+ return bootImageProfileRuleCommon(ctx, b.Name(), dexPaths, dexLocations)
}
func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -921,10 +831,6 @@ func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntr
return entriesList
}
-func (b *BootclasspathFragmentModule) getImageName() *string {
- return b.properties.Image_name
-}
-
func (b *BootclasspathFragmentModule) getProfilePath() android.Path {
return b.profilePath
}
@@ -932,7 +838,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 {
@@ -1012,7 +917,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro
// Get the hidden API information from the module.
mctx := ctx.SdkModuleContext()
- hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk)
+ hiddenAPIInfo, _ := android.OtherModuleProvider(mctx, module, HiddenAPIInfoForSdkProvider)
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
// Copy all the generated file paths.
@@ -1073,7 +978,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.
builder.CopyToSnapshot(p, dest)
dests = append(dests, dest)
}
- hiddenAPISet.AddProperty(category.PropertyName, dests)
+ hiddenAPISet.AddProperty(category.PropertyName(), dests)
}
}
}
@@ -1169,10 +1074,6 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
return android.PathForModuleSrc(ctx, *src)
}
- // Retrieve the dex files directly from the content modules. They in turn should retrieve the
- // encoded dex jars from the prebuilt .apex files.
- encodedBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, contents)
-
output := HiddenAPIOutput{
HiddenAPIFlagOutput: HiddenAPIFlagOutput{
AnnotationFlagsPath: pathForSrc("hidden_api.annotation_flags", module.prebuiltProperties.Hidden_api.Annotation_flags),
@@ -1183,8 +1084,6 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags, nil),
AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags, nil),
},
-
- EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
}
// TODO: Temporarily fallback to stub_flags/all_flags properties until prebuilts have been updated.
@@ -1194,42 +1093,28 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
return &output
}
-// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
- return bootImageOutputs{}
- }
-
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
- return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule.
- }
-
- profile := (android.WritablePath)(nil)
- if imageConfig.profileInstallPathInApex != "" {
- profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex)
+// produceBootImageProfile extracts the boot image profile from the APEX if available.
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath {
+ // This module does not provide a boot image profile.
+ if module.getProfileProviderApex(ctx) == "" {
+ return nil
}
- // Build the boot image files for the host variants. These are always built from the dex files
- // provided by the contents of this module as prebuilt versions of the host boot image files are
- // not available, i.e. there is no host specific prebuilt apex containing them. This has to be
- // built without a profile as the prebuilt modules do not provide a profile.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
- if profile == nil && imageConfig.isProfileGuided() {
- ctx.ModuleErrorf("Unable to produce boot image files: profiles not found in the prebuilt apex")
- return bootImageOutputs{}
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call getProfilePath
+ module.profilePathErr = err
+ return nil // An error has been reported by FindDeapexerProviderForModule.
}
- // Build boot image files for the android variants from the dex files provided by the contents
- // of this module.
- return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-}
-func (b *PrebuiltBootclasspathFragmentModule) getImageName() *string {
- return b.properties.Image_name
+ return di.PrebuiltExportPath(ProfileInstallPathInApex)
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
+ if b.profilePathErr != nil {
+ panic(b.profilePathErr.Error())
+ }
return b.profilePath
}
@@ -1241,18 +1126,18 @@ var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
// If there is no image config associated with this fragment then it returns nil. Otherwise, it
// returns the files that are listed in the image config.
func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
- imageConfig := module.getImageConfig(ctx)
- if imageConfig != nil {
- files := []string{}
- if imageConfig.profileInstallPathInApex != "" {
- // Add the boot image profile.
- files = append(files, imageConfig.profileInstallPathInApex)
+ for _, apex := range module.ApexProperties.Apex_available {
+ if isProfileProviderApex(ctx, apex) {
+ return []string{ProfileInstallPathInApex}
}
- return files
}
return nil
}
+func (module *PrebuiltBootclasspathFragmentModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module {
@@ -1264,9 +1149,5 @@ func prebuiltBootclasspathFragmentFactory() android.Module {
android.InitApexModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
- // Initialize the contents property from the image_name.
- android.AddLoadHook(m, func(ctx android.LoadHookContext) {
- bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule)
- })
return m
}
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 2541f14ff..8bc0a7ef6 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -40,6 +40,12 @@ func TestBootclasspathFragment_UnknownImageName(t *testing.T) {
image_name: "unknown",
contents: ["foo"],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
`)
}
@@ -53,6 +59,11 @@ func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) {
image_name: "unknown",
contents: ["foo"],
}
+
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ }
`)
}
@@ -72,6 +83,18 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T
"apex",
],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ installable: true,
+ }
`)
}
@@ -92,6 +115,18 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin
"apex2",
],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ installable: true,
+ }
`)
}
@@ -187,6 +222,11 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
FixtureConfigureApexBootJars("someapex:mysdklibrary"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
bootclasspath_fragment {
name: "myfragment",
@@ -237,16 +277,16 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
`)
fragment := result.Module("myfragment", "android_common")
- info := result.ModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ info, _ := android.SingletonModuleProvider(result, fragment, HiddenAPIInfoProvider)
stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
// Stubs jars for mysdklibrary
- publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
- systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
+ publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar"
+ systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.exportable.system/android_common/dex/mysdklibrary.stubs.exportable.system.jar"
// Stubs jars for myothersdklibrary
- otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
+ otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs.exportable/android_common/dex/myothersdklibrary.stubs.exportable.jar"
// Check that SdkPublic uses public stubs for all sdk libraries.
android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
@@ -281,6 +321,60 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
}
+func TestFromTextWidestApiScope(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetBuildFromTextStub(true)
+ }),
+ FixtureWithLastReleaseApis("mysdklibrary", "android-non-updatable"),
+ FixtureConfigureApexBootJars("someapex:mysdklibrary"),
+ ).RunTestWithBp(t, `
+ bootclasspath_fragment {
+ name: "myfragment",
+ contents: ["mysdklibrary"],
+ additional_stubs: [
+ "android-non-updatable",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+ java_sdk_library {
+ name: "mysdklibrary",
+ srcs: ["a.java"],
+ shared_library: false,
+ public: {enabled: true},
+ system: {enabled: true},
+ }
+ java_sdk_library {
+ name: "android-non-updatable",
+ srcs: ["b.java"],
+ compile_dex: true,
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+ `)
+
+ fragment := result.ModuleForTests("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,
+ "Stub flags generating command does not include the expected dependency stub dex file",
+ stubFlagsCommand, dependencyStubDexFlag)
+}
+
func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
@@ -367,16 +461,16 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
// Make sure that the library exports hidden API properties for use by the bootclasspath_fragment.
library := result.Module("mynewlibrary", "android_common")
- info := result.ModuleProvider(library, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
+ info, _ := android.SingletonModuleProvider(result, library, hiddenAPIPropertyInfoProvider)
android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages)
android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes)
android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages)
for _, c := range HiddenAPIFlagFileCategories {
expectedMaxTargetQPaths := []string(nil)
- if c.PropertyName == "max_target_q" {
+ if c.PropertyName() == "max_target_q" {
expectedMaxTargetQPaths = []string{"my-new-max-target-q.txt"}
}
- android.AssertPathsRelativeToTopEquals(t, c.PropertyName, expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
+ android.AssertPathsRelativeToTopEquals(t, c.PropertyName(), expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
}
// Make sure that the signature-patterns.csv is passed all the appropriate package properties
diff --git a/java/builder.go b/java/builder.go
index 462626712..5d84d0b43 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -42,7 +42,8 @@ var (
// TODO(b/143658984): goma can't handle the --system argument to javac.
javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
blueprint.RuleParams{
- Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" "$out" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
+ Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar.tmp" "$srcJarDir" "$out.tmp" && ` +
+ `mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
`${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
@@ -50,14 +51,18 @@ var (
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
- `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
- `rm -rf "$srcJarDir"`,
+ `$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar.tmp -C $annoDir -D $annoDir && ` +
+ `$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 && ` +
+ `rm -rf "$srcJarDir" "$outDir"`,
CommandDeps: []string{
"${config.JavacCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Restat: true,
Rspfile: "$out.rsp",
RspfileContent: "$in",
}, map[string]*remoteexec.REParams{
@@ -69,12 +74,19 @@ var (
"$zipTemplate": &remoteexec.REParams{
Labels: map[string]string{"type": "tool", "name": "soong_zip"},
Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
- OutputFiles: []string{"$out"},
+ OutputFiles: []string{"$out.tmp"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$annoSrcJarTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$annoDir"},
+ OutputFiles: []string{"$annoSrcJar.tmp"},
ExecStrategy: "${config.REJavacExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
- "outDir", "annoDir", "javaVersion"}, nil)
+ "outDir", "annoDir", "annoSrcJar", "javaVersion"}, nil)
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
@@ -108,6 +120,8 @@ var (
`--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ` +
`--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ` +
`--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED ` +
+ `--add-exports=jdk.internal.opt/jdk.internal.opt=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
`${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
@@ -200,6 +214,14 @@ var (
CommandDeps: []string{"${config.MergeZipsCmd}"},
},
"jarArgs")
+ combineJarRsp = pctx.AndroidStaticRule("combineJarRsp",
+ blueprint.RuleParams{
+ Command: `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out @$out.rsp`,
+ CommandDeps: []string{"${config.MergeZipsCmd}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ },
+ "jarArgs")
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
@@ -246,11 +268,46 @@ var (
CommandDeps: []string{"${config.ZipAlign}"},
},
)
+
+ convertImplementationJarToHeaderJarRule = pctx.AndroidStaticRule("convertImplementationJarToHeaderJar",
+ blueprint.RuleParams{
+ Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
+ CommandDeps: []string{"${config.Zip2ZipCmd}"},
+ })
+
+ writeCombinedProguardFlagsFileRule = pctx.AndroidStaticRule("writeCombinedProguardFlagsFileRule",
+ blueprint.RuleParams{
+ Command: `rm -f $out && ` +
+ `for f in $in; do ` +
+ ` echo && ` +
+ ` echo "# including $$f" && ` +
+ ` cat $$f; ` +
+ `done > $out`,
+ })
+
+ gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
+ blueprint.RuleParams{
+ Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}={state:bool}' ` +
+ `--out ${out} ` +
+ `${flags_path} ` +
+ `${filter_args} `,
+ CommandDeps: []string{"${aconfig}"},
+ Description: "aconfig_bool",
+ }, "flags_path", "filter_args")
+
+ generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule",
+ blueprint.RuleParams{
+ Command: `${keep-flagged-apis} ${in} > ${out}`,
+ CommandDeps: []string{"${keep-flagged-apis}"},
+ })
)
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
+
+ pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
}
type javaBuilderFlags struct {
@@ -292,8 +349,14 @@ type javaBuilderFlags struct {
proto android.ProtoFlags
}
+func DefaultJavaBuilderFlags() javaBuilderFlags {
+ return javaBuilderFlags{
+ javaVersion: JAVA_VERSION_8,
+ }
+}
+
func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
+ srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths) {
// Compile java sources into .class files
desc := "javac"
@@ -301,7 +364,7 @@ func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
desc += strconv.Itoa(shardIdx)
}
- transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc)
+ transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, flags, deps, "javac", desc)
}
// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
@@ -365,7 +428,7 @@ func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx
})
}
-func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, android.Paths) {
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string) (string, android.Paths) {
var deps android.Paths
classpath := flags.classpath
@@ -390,13 +453,21 @@ func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, an
deps = append(deps, classpath...)
turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
+ const flagsLimit = 32 * 1024
+ if len(turbineFlags) > flagsLimit {
+ flagsRspFile := android.PathForModuleOut(ctx, dir, "turbine-flags.rsp")
+ android.WriteFileRule(ctx, flagsRspFile, turbineFlags)
+ turbineFlags = "@" + flagsRspFile.String()
+ deps = append(deps, flagsRspFile)
+ }
+
return turbineFlags, deps
}
func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
- turbineFlags, deps := turbineFlags(ctx, flags)
+ turbineFlags, deps := turbineFlags(ctx, flags, "turbine")
deps = append(deps, srcJars...)
@@ -428,7 +499,7 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
- turbineFlags, deps := turbineFlags(ctx, flags)
+ turbineFlags, deps := turbineFlags(ctx, flags, "kapt")
deps = append(deps, srcJars...)
@@ -475,20 +546,20 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
// suffix will be appended to various intermediate files and directories to avoid collisions when
// this function is called twice in the same module directory.
func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- shardIdx int, srcFiles, srcJars android.Paths,
+ shardIdx int, srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath,
flags javaBuilderFlags, deps android.Paths,
intermediatesDir, desc string) {
deps = append(deps, srcJars...)
- classpath := flags.classpath
+ javacClasspath := flags.classpath
var bootClasspath string
if flags.javaVersion.usesJavaModules() {
var systemModuleDeps android.Paths
bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device())
deps = append(deps, systemModuleDeps...)
- classpath = append(flags.java9Classpath, classpath...)
+ javacClasspath = append(flags.java9Classpath, javacClasspath...)
} else {
deps = append(deps, flags.bootClasspath...)
if len(flags.bootClasspath) == 0 && ctx.Device() {
@@ -500,7 +571,19 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
}
}
- deps = append(deps, classpath...)
+ classpathArg := javacClasspath.FormJavaClassPath("-classpath")
+
+ // Keep the command line under the MAX_ARG_STRLEN limit by putting the classpath argument into an rsp file
+ // if it is too long.
+ const classpathLimit = 64 * 1024
+ if len(classpathArg) > classpathLimit {
+ classpathRspFile := outputFile.ReplaceExtension(ctx, "classpath")
+ android.WriteFileRule(ctx, classpathRspFile, classpathArg)
+ deps = append(deps, classpathRspFile)
+ classpathArg = "@" + classpathRspFile.String()
+ }
+
+ deps = append(deps, javacClasspath...)
deps = append(deps, flags.processorPath...)
processor := "-proc:none"
@@ -522,21 +605,23 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
rule = javacRE
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: desc,
- Output: outputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: rule,
+ Description: desc,
+ Output: outputFile,
+ ImplicitOutput: annoSrcJar,
+ Inputs: srcFiles,
+ Implicits: deps,
Args: map[string]string{
"javacFlags": flags.javacFlags,
"bootClasspath": bootClasspath,
- "classpath": classpath.FormJavaClassPath("-classpath"),
+ "classpath": classpathArg,
"processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
"processor": processor,
"srcJars": strings.Join(srcJars.Strings(), " "),
"srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
"outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
"annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+ "annoSrcJar": annoSrcJar.String(),
"javaVersion": flags.javaVersion.String(),
},
})
@@ -588,8 +673,23 @@ func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePa
jarArgs = append(jarArgs, "-D")
}
+ rule := combineJar
+ // Keep the command line under the MAX_ARG_STRLEN limit by putting the list of jars into an rsp file
+ // if it is too long.
+ const jarsLengthLimit = 64 * 1024
+ jarsLength := 0
+ for i, jar := range jars {
+ if i != 0 {
+ jarsLength += 1
+ }
+ jarsLength += len(jar.String())
+ }
+ if jarsLength > jarsLengthLimit {
+ rule = combineJarRsp
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: combineJar,
+ Rule: rule,
Description: desc,
Output: outputFile,
Inputs: jars,
@@ -600,6 +700,15 @@ func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePa
})
}
+func convertImplementationJarToHeaderJar(ctx android.ModuleContext, implementationJarFile android.Path,
+ headerJarFile android.WritablePath) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: convertImplementationJarToHeaderJarRule,
+ Input: implementationJarFile,
+ Output: headerJarFile,
+ })
+}
+
func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
classesJar android.Path, rulesFile android.Path) {
ctx.Build(pctx, android.BuildParams{
@@ -641,12 +750,22 @@ func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.Wri
android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
}
-func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) {
+func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path, validations android.Paths) {
ctx.Build(pctx, android.BuildParams{
Rule: zipalign,
Description: "align",
Input: inputFile,
Output: outputFile,
+ Validations: validations,
+ })
+}
+
+func writeCombinedProguardFlagsFile(ctx android.ModuleContext, outputFile android.WritablePath, files android.Paths) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: writeCombinedProguardFlagsFileRule,
+ Description: "write combined proguard flags file",
+ Inputs: files,
+ Output: outputFile,
})
}
diff --git a/java/classpath_element.go b/java/classpath_element.go
index 496291678..abbcae7a3 100644
--- a/java/classpath_element.go
+++ b/java/classpath_element.go
@@ -21,7 +21,6 @@ import (
"strings"
"android/soong/android"
- "github.com/google/blueprint"
)
// Supports constructing a list of ClasspathElement from a set of fragments and modules.
@@ -72,8 +71,7 @@ var _ ClasspathElement = (*ClasspathLibraryElement)(nil)
// ClasspathElementContext defines the context methods needed by CreateClasspathElements
type ClasspathElementContext interface {
- OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
- OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
+ android.OtherModuleProviderContext
ModuleErrorf(fmt string, args ...interface{})
}
@@ -123,12 +121,12 @@ func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Mo
// associated with a particular apex.
apexToFragment := map[string]android.Module{}
for _, fragment := range fragments {
- if !ctx.OtherModuleHasProvider(fragment, android.ApexInfoProvider) {
+ apexInfo, ok := android.OtherModuleProvider(ctx, fragment, android.ApexInfoProvider)
+ if !ok {
ctx.ModuleErrorf("fragment %s is not part of an apex", fragment)
continue
}
- apexInfo := ctx.OtherModuleProvider(fragment, android.ApexInfoProvider).(android.ApexInfo)
for _, apex := range apexInfo.InApexVariants {
if existing, ok := apexToFragment[apex]; ok {
ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", apex, fragment, existing)
@@ -146,8 +144,7 @@ skipLibrary:
// Iterate over the libraries to construct the ClasspathElements list.
for _, library := range libraries {
var element ClasspathElement
- if ctx.OtherModuleHasProvider(library, android.ApexInfoProvider) {
- apexInfo := ctx.OtherModuleProvider(library, android.ApexInfoProvider).(android.ApexInfo)
+ if apexInfo, ok := android.OtherModuleProvider(ctx, library, android.ApexInfoProvider); ok {
var fragment android.Module
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index bc9de5043..18a5dae6c 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -103,8 +103,8 @@ type classpathJar struct {
func gatherPossibleApexModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
set := map[string]struct{}{}
for _, name := range contents {
- dep := ctx.GetDirectDepWithTag(name, tag)
- set[name] = struct{}{}
+ dep, _ := ctx.GetDirectDepWithTag(name, tag).(android.Module)
+ set[ModuleStemForDeapexing(dep)] = struct{}{}
if m, ok := dep.(ModuleWithStem); ok {
set[m.Stem()] = struct{}{}
} else {
@@ -128,19 +128,21 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
return m.Name() == configuredJars.Jar(i)
}, func(m android.Module) {
if s, ok := m.(*SdkLibrary); ok {
+ minSdkVersion := s.MinSdkVersion(ctx)
+ maxSdkVersion := s.MaxSdkVersion(ctx)
// TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
- if s.minSdkVersion.Specified() {
- if s.minSdkVersion.IsCurrent() {
+ if minSdkVersion.Specified() {
+ if minSdkVersion.IsCurrent() {
jar.minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
} else {
- jar.minSdkVersion = s.minSdkVersion.String()
+ jar.minSdkVersion = minSdkVersion.String()
}
}
- if s.maxSdkVersion.Specified() {
- if s.maxSdkVersion.IsCurrent() {
+ if maxSdkVersion.Specified() {
+ if maxSdkVersion.IsCurrent() {
jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
} else {
- jar.maxSdkVersion = s.maxSdkVersion.String()
+ jar.maxSdkVersion = maxSdkVersion.String()
}
}
}
@@ -151,10 +153,14 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
return jars
}
+func (c *ClasspathFragmentBase) outputFilename() string {
+ return strings.ToLower(c.classpathType.String()) + ".pb"
+}
+
func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) {
generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true)
if generateProto {
- outputFilename := strings.ToLower(c.classpathType.String()) + ".pb"
+ outputFilename := c.outputFilename()
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
@@ -178,7 +184,11 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
ClasspathFragmentProtoInstallDir: c.installDirPath,
ClasspathFragmentProtoOutput: c.outputFilepath,
}
- ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
+ android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
+}
+
+func (c *ClasspathFragmentBase) installClasspathProto(ctx android.ModuleContext) android.InstallPath {
+ return ctx.InstallFile(c.installDirPath, c.outputFilename(), c.outputFilepath)
}
func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
@@ -211,7 +221,7 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
}}
}
-var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{})
+var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider[ClasspathFragmentProtoContentInfo]()
type ClasspathFragmentProtoContentInfo struct {
// Whether the classpaths.proto config is generated for the fragment.
diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go
new file mode 100644
index 000000000..99b1f5226
--- /dev/null
+++ b/java/code_metadata_test.go
@@ -0,0 +1,115 @@
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ soongTesting "android/soong/testing"
+ "android/soong/testing/code_metadata_internal_proto"
+
+ "google.golang.org/protobuf/proto"
+)
+
+func TestCodeMetadata(t *testing.T) {
+ bp := `code_metadata {
+ name: "module-name",
+ teamId: "12345",
+ code: [
+ "foo",
+ ]
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }`
+ result := runCodeMetadataTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module-name", "")
+
+ // Check that the provider has the right contents
+ data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.CodeMetadataProviderKey)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateCodeMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ metadata := android.ContentFromFileRuleForTests(t, result.TestContext,
+ module.Output(data.IntermediatePath.String()))
+
+ metadataList := make([]*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, 2)
+ teamId := "12345"
+ bpFilePath := "Android.bp"
+ targetName := "foo"
+ srcFile := []string{"a.java"}
+ expectedMetadataProto := code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TrendyTeamId: &teamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ SourceFiles: srcFile,
+ }
+ metadataList = append(metadataList, &expectedMetadataProto)
+
+ CodeMetadataMetadata := code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList}
+ protoData, _ := proto.Marshal(&CodeMetadataMetadata)
+ expectedMetadata := string(protoData)
+
+ 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_code_metadata")
+ rule := singleton.Rule("all_code_metadata_rule")
+ prebuiltOs := result.Config.PrebuiltOS()
+ expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule code_metadata -inputFile out/soong/all_code_metadata_paths.rsp -outputFile out/soong/ownership/all_code_metadata.pb"
+ expectedOutputFile := "out/soong/ownership/all_code_metadata.pb"
+ expectedInputFile := "out/soong/.intermediates/module-name/intermediateCodeMetadata.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 doesn't contain expectedCmd: %s",
+ rule.RuleParams.Command, expectedCmd,
+ )
+ }
+}
+func runCodeMetadataTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents, prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/config/Android.bp b/java/config/Android.bp
index 194e2c6ed..bfe83ab8c 100644
--- a/java/config/Android.bp
+++ b/java/config/Android.bp
@@ -12,6 +12,7 @@ bootstrap_go_package {
],
srcs: [
"config.go",
+ "droidstubs.go",
"error_prone.go",
"kotlin.go",
"makevars.go",
diff --git a/java/config/config.go b/java/config/config.go
index b82a137e7..0d30fbdf4 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -26,8 +26,7 @@ import (
)
var (
- pctx = android.NewPackageContext("android/soong/java/config")
- exportedVars = android.NewExportedVariables(pctx)
+ pctx = android.NewPackageContext("android/soong/java/config")
LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
LegacyCorePlatformSystemModules = "legacy-core-platform-api-stubs-system-modules"
@@ -52,6 +51,7 @@ var (
"core-icu4j",
"core-oj",
"core-libart",
+ "wear-sdk.impl",
}
)
@@ -79,32 +79,30 @@ var (
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
- exportedVars.ExportStringStaticVariable("JavacHeapSize", "4096M")
- exportedVars.ExportStringStaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
+ pctx.StaticVariable("JavacHeapSize", "4096M")
+ pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
// ErrorProne can use significantly more memory than javac alone, give it a higher heap
// size (b/221480398).
- exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "8192M")
- exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
+ pctx.StaticVariable("ErrorProneHeapSize", "8192M")
+ pctx.StaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
// D8 invocations are shorter lived, so we restrict their JIT tiering relative to R8.
// Note that the `-JXX` prefix syntax is specific to the R8/D8 invocation wrappers.
- exportedVars.ExportStringListStaticVariable("D8Flags", append([]string{
+ pctx.StaticVariable("D8Flags", strings.Join(append([]string{
"-JXmx4096M",
"-JXX:+TieredCompilation",
"-JXX:TieredStopAtLevel=1",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
- "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
- }, dexerJavaVmFlagsList...))
- exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{
- "-JXmx2048M",
+ }, dexerJavaVmFlagsList...), " "))
+ pctx.StaticVariable("R8Flags", strings.Join(append([]string{
+ "-JXmx4096M",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
- "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
- }, dexerJavaVmFlagsList...))
+ }, dexerJavaVmFlagsList...), " "))
- exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
+ pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
`-Xmaxerrs 9999999`,
`-encoding UTF-8`,
`-sourcepath ""`,
@@ -118,10 +116,10 @@ func init() {
// b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
`-XDstringConcat=inline`,
- })
+ }, " "))
- exportedVars.ExportStringListStaticVariable("JavaVmFlags", javaVmFlagsList)
- exportedVars.ExportStringListStaticVariable("JavacVmFlags", javacVmFlagsList)
+ pctx.StaticVariable("JavaVmFlags", strings.Join(javaVmFlagsList, " "))
+ pctx.StaticVariable("JavacVmFlags", strings.Join(javacVmFlagsList, " "))
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
@@ -133,7 +131,7 @@ func init() {
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
}
- return "17"
+ return "21"
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
@@ -148,6 +146,8 @@ func init() {
pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
+ pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
+
pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
@@ -214,10 +214,6 @@ func init() {
hostJNIToolVariableWithSdkToolsPrebuilt("SignapkJniLibrary", "libconscrypt_openjdk_jni")
}
-func BazelJavaToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
-}
-
func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
if ctx.Config().AlwaysUsePrebuiltSdks() {
diff --git a/java/config/droidstubs.go b/java/config/droidstubs.go
new file mode 100644
index 000000000..04a3f96b9
--- /dev/null
+++ b/java/config/droidstubs.go
@@ -0,0 +1,64 @@
+// Copyright 2023 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 config
+
+import "strings"
+
+var (
+ metalavaFlags = []string{
+ "--color",
+ "--quiet",
+ "--format=v2",
+ "--repeat-errors-max 10",
+ "--hide UnresolvedImport",
+
+ // Force metalava to ignore classes on the classpath when an API file contains missing classes.
+ // See b/285140653 for more information.
+ "--api-class-resolution api",
+
+ // Force metalava to sort overloaded methods by their order in the source code.
+ // See b/285312164 for more information.
+ // And add concrete overrides of abstract methods, see b/299366704 for more
+ // information.
+ "--format-defaults overloaded-method-order=source,add-additional-overrides=yes",
+ }
+
+ MetalavaFlags = strings.Join(metalavaFlags, " ")
+
+ metalavaAnnotationsFlags = []string{
+ "--include-annotations",
+ "--exclude-annotation androidx.annotation.RequiresApi",
+ }
+
+ MetalavaAnnotationsFlags = strings.Join(metalavaAnnotationsFlags, " ")
+
+ metalavaAnnotationsWarningsFlags = []string{
+ // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
+ "--hide HiddenTypedefConstant",
+ "--hide SuperfluousPrefix",
+ }
+
+ MetalavaAnnotationsWarningsFlags = strings.Join(metalavaAnnotationsWarningsFlags, " ")
+)
+
+const (
+ MetalavaAddOpens = "-J--add-opens=java.base/java.util=ALL-UNNAMED"
+)
+
+func init() {
+ pctx.StaticVariable("MetalavaAnnotationsFlags", strings.Join(metalavaAnnotationsFlags, " "))
+
+ pctx.StaticVariable("MetalavaAnnotationWarningsFlags", strings.Join(metalavaAnnotationsWarningsFlags, " "))
+}
diff --git a/java/config/error_prone.go b/java/config/error_prone.go
index 5f853c812..767164f70 100644
--- a/java/config/error_prone.go
+++ b/java/config/error_prone.go
@@ -15,6 +15,7 @@
package config
import (
+ "android/soong/android"
"strings"
)
@@ -29,23 +30,23 @@ var (
)
// Wrapper that grabs value of val late so it can be initialized by a later module's init function
-func errorProneVar(val *[]string, sep string) func() string {
- return func() string {
+func errorProneVar(val *[]string, sep string) func(android.PackageVarContext) string {
+ return func(android.PackageVarContext) string {
return strings.Join(*val, sep)
}
}
func init() {
- exportedVars.ExportVariableFuncVariable("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
- exportedVars.ExportVariableFuncVariable("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
- exportedVars.ExportVariableFuncVariable("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
- exportedVars.ExportVariableFuncVariable("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
- exportedVars.ExportVariableFuncVariable("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
- exportedVars.ExportVariableFuncVariable("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
- exportedVars.ExportStringListStaticVariable("ErrorProneChecks", []string{
+ pctx.VariableFunc("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
+ pctx.VariableFunc("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
+ pctx.VariableFunc("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
+ pctx.VariableFunc("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
+ pctx.VariableFunc("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
+ pctx.VariableFunc("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
+ pctx.StaticVariable("ErrorProneChecks", strings.Join([]string{
"${ErrorProneChecksOff}",
"${ErrorProneChecksError}",
"${ErrorProneChecksWarning}",
"${ErrorProneChecksDefaultDisabled}",
- })
+ }, " "))
}
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index fc63f4dfb..e5e187cad 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -49,8 +49,5 @@ func init() {
"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
}, " "))
- pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{
- // b/222162908: prevent kotlinc from reading /tmp/build.txt
- "-Didea.plugins.compatible.build=999.SNAPSHOT",
- }, " "))
+ pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
}
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 273aca0b4..649b6c58f 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -28,13 +28,12 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("FRAMEWORK_LIBRARIES", strings.Join(FrameworkLibraries, " "))
// These are used by make when LOCAL_PRIVATE_PLATFORM_APIS is set (equivalent to platform_apis in blueprint):
- ctx.Strict("LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES", strings.Join(LegacyCorePlatformBootclasspathLibraries, " "))
+ ctx.Strict("LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES",
+ strings.Join(LegacyCorePlatformBootclasspathLibraries, " "))
ctx.Strict("LEGACY_CORE_PLATFORM_SYSTEM_MODULES", LegacyCorePlatformSystemModules)
ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
- ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}")
- ctx.Strict("ANDROID_JAVA11_HOME", "prebuilts/jdk/jdk11/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}")
ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}")
diff --git a/java/container_test.go b/java/container_test.go
new file mode 100644
index 000000000..344185553
--- /dev/null
+++ b/java/container_test.go
@@ -0,0 +1,129 @@
+// Copyright 2024 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 (
+ "android/soong/android"
+ "fmt"
+ "testing"
+)
+
+var checkContainerMatch = func(t *testing.T, name string, container string, expected bool, actual bool) {
+ errorMessage := fmt.Sprintf("module %s container %s value differ", name, container)
+ android.AssertBoolEquals(t, errorMessage, expected, actual)
+}
+
+func TestJavaContainersModuleProperties(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["A.java"],
+ }
+ java_library {
+ name: "foo_vendor",
+ srcs: ["A.java"],
+ vendor: true,
+ sdk_version: "current",
+ }
+ java_library {
+ name: "foo_soc_specific",
+ srcs: ["A.java"],
+ soc_specific: true,
+ sdk_version: "current",
+ }
+ java_library {
+ name: "foo_product_specific",
+ srcs: ["A.java"],
+ product_specific: true,
+ sdk_version: "current",
+ }
+ java_test {
+ name: "foo_cts_test",
+ srcs: ["A.java"],
+ test_suites: [
+ "cts",
+ ],
+ }
+ java_test {
+ name: "foo_non_cts_test",
+ srcs: ["A.java"],
+ test_suites: [
+ "general-tests",
+ ],
+ }
+ `)
+
+ testcases := []struct {
+ moduleName string
+ isSystemContainer bool
+ isVendorContainer bool
+ isProductContainer bool
+ isCts bool
+ }{
+ {
+ moduleName: "foo",
+ isSystemContainer: true,
+ isVendorContainer: false,
+ isProductContainer: false,
+ isCts: false,
+ },
+ {
+ moduleName: "foo_vendor",
+ isSystemContainer: false,
+ isVendorContainer: true,
+ isProductContainer: false,
+ isCts: false,
+ },
+ {
+ moduleName: "foo_soc_specific",
+ isSystemContainer: false,
+ isVendorContainer: true,
+ isProductContainer: false,
+ isCts: false,
+ },
+ {
+ moduleName: "foo_product_specific",
+ isSystemContainer: false,
+ isVendorContainer: false,
+ isProductContainer: true,
+ isCts: false,
+ },
+ {
+ moduleName: "foo_cts_test",
+ isSystemContainer: false,
+ isVendorContainer: false,
+ isProductContainer: false,
+ isCts: true,
+ },
+ {
+ moduleName: "foo_non_cts_test",
+ isSystemContainer: false,
+ isVendorContainer: false,
+ isProductContainer: false,
+ isCts: false,
+ },
+ }
+
+ for _, c := range testcases {
+ m := result.ModuleForTests(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))
+ checkContainerMatch(t, c.moduleName, "vendor", c.isVendorContainer, android.InList(android.VendorContainer, belongingContainers))
+ checkContainerMatch(t, c.moduleName, "product", c.isProductContainer, android.InList(android.ProductContainer, belongingContainers))
+ }
+}
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 958f4cead..ab72e8b6d 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -33,22 +33,86 @@ dist_targets = [
"win_sdk",
]
-java_library {
- name: "core.current.stubs",
+java_defaults {
+ name: "core.current.stubs.defaults",
visibility: ["//visibility:public"],
+ sdk_version: "none",
+ system_modules: "none",
+}
+
+java_library {
+ name: "core.current.stubs.from-source",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
static_libs: [
"art.module.public.api.stubs",
"conscrypt.module.public.api.stubs",
"i18n.module.public.api.stubs",
],
- sdk_version: "none",
- system_modules: "none",
+}
+java_api_library {
+ name: "core.current.stubs.from-text",
+ api_surface: "core",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "conscrypt.module.public.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ enable_validation: false,
+ stubs_type: "everything",
+}
+
+java_library {
+ name: "core.current.stubs",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
+ static_libs: [
+ "core.current.stubs.from-source",
+ ],
+ product_variables: {
+ build_from_text_stub: {
+ static_libs: [
+ "core.current.stubs.from-text",
+ ],
+ exclude_static_libs: [
+ "core.current.stubs.from-source",
+ ],
+ },
+ },
+}
+
+java_library {
+ name: "core.current.stubs.exportable.from-source",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
+ static_libs: [
+ "art.module.public.api.stubs.exportable",
+ "conscrypt.module.public.api.stubs.exportable",
+ "i18n.module.public.api.stubs.exportable",
+ ],
dist: {
targets: dist_targets,
+ dest: "core.current.stubs.jar",
},
}
+java_library {
+ name: "core.current.stubs.exportable",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
+ static_libs: [
+ "core.current.stubs.exportable.from-source",
+ ],
+}
+
// Distributed with the SDK for turning into system modules to compile apps
// against.
//
@@ -120,12 +184,42 @@ java_system_modules {
],
}
+java_defaults {
+ name: "core.module_lib.stubs.defaults",
+ visibility: ["//visibility:private"],
+ sdk_version: "none",
+ system_modules: "none",
+}
+
// A stubs target containing the parts of the public SDK & @SystemApi(MODULE_LIBRARIES) API
// provided by the core libraries.
//
// Don't use this directly, use "sdk_version: module_current".
java_library {
name: "core.module_lib.stubs",
+ defaults: [
+ "core.module_lib.stubs.defaults",
+ ],
+ static_libs: [
+ "core.module_lib.stubs.from-source",
+ ],
+ product_variables: {
+ build_from_text_stub: {
+ static_libs: [
+ "core.module_lib.stubs.from-text",
+ ],
+ exclude_static_libs: [
+ "core.module_lib.stubs.from-source",
+ ],
+ },
+ },
+}
+
+java_library {
+ name: "core.module_lib.stubs.from-source",
+ defaults: [
+ "core.module_lib.stubs.defaults",
+ ],
static_libs: [
"art.module.public.api.stubs.module_lib",
@@ -135,9 +229,27 @@ java_library {
"conscrypt.module.public.api.stubs",
"i18n.module.public.api.stubs",
],
- sdk_version: "none",
- system_modules: "none",
+}
+
+java_api_library {
+ name: "core.module_lib.stubs.from-text",
+ api_surface: "module-lib",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "art.module.public.api.stubs.source.system.api.contribution",
+ "art.module.public.api.stubs.source.module_lib.api.contribution",
+
+ // Add the module-lib correspondence when Conscrypt or i18N module
+ // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
+ // @SystemApi(MODULE_LIBRARIES).
+ "conscrypt.module.public.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
visibility: ["//visibility:private"],
+ stubs_type: "everything",
}
// Produces a dist file that is used by the
@@ -199,18 +311,97 @@ core_platform_visibility = ["//visibility:public"]
// API annotations are available to the dex tools that enable enforcement of runtime
// accessibility. b/119068555
java_library {
+ name: "legacy.core.platform.api.stubs.from-source",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "art.module.public.api.stubs.module_lib",
+ "conscrypt.module.platform.api.stubs",
+ "legacy.i18n.module.platform.api.stubs",
+ ],
+}
+
+java_library {
+ name: "legacy.core.platform.api.stubs.exportable.from-source",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "art.module.public.api.stubs.exportable.module_lib",
+ "conscrypt.module.platform.api.stubs.exportable",
+ "legacy.i18n.module.platform.api.stubs.exportable",
+ ],
+}
+
+java_defaults {
+ name: "android_core_platform_stubs_current_contributions",
+ api_surface: "core_platform",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "art.module.public.api.stubs.source.system.api.contribution",
+ "art.module.public.api.stubs.source.module_lib.api.contribution",
+ "conscrypt.module.platform.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+}
+
+java_api_library {
+ name: "legacy.core.platform.api.stubs.from-text",
+ api_surface: "core_platform",
+ defaults: [
+ "android_core_platform_stubs_current_contributions",
+ ],
+ api_contributions: [
+ "legacy.i18n.module.platform.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ stubs_type: "everything",
+}
+
+java_library {
name: "legacy.core.platform.api.stubs",
visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "legacy.core.platform.api.stubs.from-source",
+ ],
+ product_variables: {
+ build_from_text_stub: {
+ static_libs: [
+ "legacy.core.platform.api.stubs.from-text",
+ ],
+ exclude_static_libs: [
+ "legacy.core.platform.api.stubs.from-source",
+ ],
+ },
+ },
+}
+
+java_library {
+ name: "legacy.core.platform.api.stubs.exportable",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "legacy.core.platform.api.stubs.exportable.from-source",
+ ],
+}
+
+java_defaults {
+ name: "core.platform.api.stubs.defaults",
hostdex: true,
compile_dex: true,
sdk_version: "none",
system_modules: "none",
- static_libs: [
- "art.module.public.api.stubs.module_lib",
- "conscrypt.module.platform.api.stubs",
- "legacy.i18n.module.platform.api.stubs",
- ],
patch_module: "java.base",
}
@@ -233,20 +424,53 @@ java_library {
}
java_library {
- name: "stable.core.platform.api.stubs",
+ name: "stable.core.platform.api.stubs.from-source",
visibility: core_platform_visibility,
- hostdex: true,
- compile_dex: true,
-
- sdk_version: "none",
- system_modules: "none",
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
static_libs: [
"art.module.public.api.stubs.module_lib",
// conscrypt only has a stable version, so it is okay to depend on it here:
"conscrypt.module.platform.api.stubs",
"stable.i18n.module.platform.api.stubs",
],
- patch_module: "java.base",
+}
+
+java_api_library {
+ name: "stable.core.platform.api.stubs.from-text",
+ api_surface: "core_platform",
+ defaults: [
+ "android_core_platform_stubs_current_contributions",
+ ],
+ api_contributions: [
+ "stable.i18n.module.platform.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ stubs_type: "everything",
+}
+
+java_library {
+ name: "stable.core.platform.api.stubs",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "stable.core.platform.api.stubs.from-source",
+ ],
+ product_variables: {
+ build_from_text_stub: {
+ static_libs: [
+ "stable.core.platform.api.stubs.from-text",
+ ],
+ exclude_static_libs: [
+ "stable.core.platform.api.stubs.from-source",
+ ],
+ },
+ },
}
// Same as stable.core.platform.api.stubs, but android annotations are
@@ -351,7 +575,3 @@ java_system_modules {
"art-module-intra-core-api-stubs-system-modules-lib",
],
}
-
-build = [
- "TxtStubLibraries.bp",
-]
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
deleted file mode 100644
index 813187e54..000000000
--- a/java/core-libraries/TxtStubLibraries.bp
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// 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.
-
-// This file contains java_system_modules provided by the SDK.
-// These system modules transitively depend on core stub libraries generated from .txt files.
-
-// Same as core-public-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "core-public-stubs-system-modules.from-text",
- visibility: ["//visibility:public"],
- libs: [
- "core-current-stubs-for-system-modules-no-annotations.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_library {
- name: "core-current-stubs-for-system-modules-no-annotations.from-text",
- visibility: ["//visibility:private"],
- defaults: [
- "system-modules-no-annotations",
- ],
- static_libs: [
- "core.current.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-// Same as core-module-lib-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "core-module-lib-stubs-system-modules.from-text",
- visibility: ["//visibility:public"],
- libs: [
- "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_library {
- name: "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
- visibility: ["//visibility:private"],
- defaults: [
- "system-modules-no-annotations",
- ],
- static_libs: [
- "core.module_lib.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_library {
- name: "core.module_lib.stubs.from-text",
- static_libs: [
- "art.module.public.api.stubs.module_lib.from-text",
-
- // Replace the following with the module-lib correspondence when Conscrypt or i18N module
- // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
- // @SystemApi(MODULE_LIBRARIES).
- "conscrypt.module.public.api.stubs.from-text",
- "i18n.module.public.api.stubs.from-text",
- ],
- sdk_version: "none",
- system_modules: "none",
- visibility: ["//visibility:private"],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-// Same as legacy-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "legacy-core-platform-api-stubs-system-modules.from-text",
- visibility: core_platform_visibility,
- libs: [
- "legacy.core.platform.api.no.annotations.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_library {
- name: "legacy.core.platform.api.no.annotations.stubs.from-text",
- visibility: core_platform_visibility,
- defaults: [
- "system-modules-no-annotations",
- ],
- hostdex: true,
- compile_dex: true,
-
- static_libs: [
- "legacy.core.platform.api.stubs.from-text",
- ],
- patch_module: "java.base",
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-// Same as stable-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "stable-core-platform-api-stubs-system-modules.from-text",
- visibility: core_platform_visibility,
- libs: [
- "stable.core.platform.api.no.annotations.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_library {
- name: "stable.core.platform.api.no.annotations.stubs.from-text",
- visibility: core_platform_visibility,
- defaults: [
- "system-modules-no-annotations",
- ],
- hostdex: true,
- compile_dex: true,
-
- static_libs: [
- "stable.core.platform.api.stubs.from-text",
- ],
- patch_module: "java.base",
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
-
-java_api_library {
- name: "core-lambda-stubs.from-text",
- api_surface: "toolchain",
- api_contributions: [
- "art.module.toolchain.api.api.contribution",
- ],
- libs: [
- // LambdaMetaFactory depends on CallSite etc. which is part of the Core API surface
- "core.current.stubs.from-text",
- ],
- // TODO: Enable after stub generation from .txt file is available
- enabled: false,
-}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 3581040f8..3f8735c0c 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -19,16 +19,12 @@ import (
"io"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
-
- "github.com/google/blueprint/proptools"
)
type DeviceHostConverter struct {
android.ModuleBase
android.DefaultableModuleBase
- android.BazelModuleBase
properties DeviceHostConverterProperties
@@ -80,7 +76,6 @@ func HostForDeviceFactory() android.Module {
module.AddProperties(&module.properties)
InitJavaModule(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
@@ -102,8 +97,7 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont
}
ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
- if ctx.OtherModuleHasProvider(m, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
d.headerJars = append(d.headerJars, dep.HeaderJars...)
d.implementationJars = append(d.implementationJars, dep.ImplementationJars...)
d.implementationAndResourceJars = append(d.implementationAndResourceJars, dep.ImplementationAndResourcesJars...)
@@ -136,13 +130,16 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont
d.combinedHeaderJar = d.headerJars[0]
}
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: d.headerJars,
ImplementationAndResourcesJars: d.implementationAndResourceJars,
ImplementationJars: d.implementationJars,
ResourceJars: d.resourceJars,
SrcJarArgs: d.srcJarArgs,
SrcJarDeps: d.srcJarDeps,
+ StubsLinkType: Implementation,
+ // TODO: Not sure if aconfig flags that have been moved between device and host variants
+ // make sense.
})
}
@@ -155,7 +152,7 @@ func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
return d.implementationAndResourceJars
}
-func (d *DeviceHostConverter) DexJarBuildPath() android.Path {
+func (d *DeviceHostConverter) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
return nil
}
@@ -191,32 +188,3 @@ func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData {
},
}
}
-
-type bazelDeviceHostConverterAttributes struct {
- Exports bazel.LabelListAttribute
-}
-
-func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "java_host_for_device",
- Bzl_load_location: "//build/bazel/rules/java:host_for_device.bzl",
- },
- android.CommonAttributes{Name: d.Name()},
- &bazelDeviceHostConverterAttributes{
- Exports: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
- },
- )
- neverLinkAttrs := &javaLibraryAttributes{
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + d.Name()}),
- Neverlink: bazel.BoolAttribute{Value: proptools.BoolPtr(true)},
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
- },
- }
- ctx.CreateBazelTargetModule(
- javaLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: d.Name() + "-neverlink"},
- neverLinkAttrs)
-
-}
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
index 3c9a0f3f1..6ccc5c1b1 100644
--- a/java/device_host_converter_test.go
+++ b/java/device_host_converter_test.go
@@ -16,7 +16,7 @@ package java
import (
"android/soong/android"
- "reflect"
+ "slices"
"strings"
"testing"
)
@@ -84,7 +84,7 @@ func TestDeviceForHost(t *testing.T) {
deviceImportCombined.Output,
}
- if !reflect.DeepEqual(combined.Inputs, expectedInputs) {
+ if !slices.Equal(combined.Inputs.Strings(), expectedInputs.Strings()) {
t.Errorf("expected host_module combined inputs:\n%q\ngot:\n%q",
expectedInputs, combined.Inputs)
}
@@ -95,7 +95,7 @@ func TestDeviceForHost(t *testing.T) {
deviceRes.Output,
}
- if !reflect.DeepEqual(resCombined.Inputs, expectedInputs) {
+ if !slices.Equal(resCombined.Inputs.Strings(), expectedInputs.Strings()) {
t.Errorf("expected host_module res combined inputs:\n%q\ngot:\n%q",
expectedInputs, resCombined.Inputs)
}
@@ -135,6 +135,7 @@ func TestHostForDevice(t *testing.T) {
hostModule := ctx.ModuleForTests("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())
@@ -148,7 +149,7 @@ func TestHostForDevice(t *testing.T) {
// check classpath of device module with dependency on host_for_device_module
expectedClasspath := "-classpath " + strings.Join(android.Paths{
- hostJavac.Output,
+ hostJavacHeader.Output,
hostImportCombined.Output,
}.Strings(), ":")
@@ -164,7 +165,7 @@ func TestHostForDevice(t *testing.T) {
hostImportCombined.Output,
}
- if !reflect.DeepEqual(combined.Inputs, expectedInputs) {
+ if !slices.Equal(combined.Inputs.Strings(), expectedInputs.Strings()) {
t.Errorf("expected device_module combined inputs:\n%q\ngot:\n%q",
expectedInputs, combined.Inputs)
}
@@ -175,7 +176,7 @@ func TestHostForDevice(t *testing.T) {
hostRes.Output,
}
- if !reflect.DeepEqual(resCombined.Inputs, expectedInputs) {
+ if !slices.Equal(resCombined.Inputs.Strings(), expectedInputs.Strings()) {
t.Errorf("expected device_module res combined inputs:\n%q\ngot:\n%q",
expectedInputs, resCombined.Inputs)
}
diff --git a/java/dex.go b/java/dex.go
index 4d6aa3456..7bb69257c 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -45,8 +45,8 @@ type DexProperties struct {
// Whether to continue building even if warnings are emitted. Defaults to true.
Ignore_warnings *bool
- // If true, runs R8 in Proguard compatibility mode (default).
- // Otherwise, runs R8 in full mode.
+ // If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
+ // Defaults to false for apps, true for libraries and tests.
Proguard_compatibility *bool
// If true, optimize for size by removing unused code. Defaults to true for apps,
@@ -66,11 +66,21 @@ type DexProperties struct {
// If true, optimize for size by removing unused resources. Defaults to false.
Shrink_resources *bool
+ // If true, use optimized resource shrinking in R8, overriding the
+ // Shrink_resources setting. Defaults to false.
+ // Optimized shrinking means that R8 will trace and treeshake resources together with code
+ // and apply additional optimizations. This implies non final fields in the R classes.
+ Optimized_shrink_resources *bool
+
// Flags to pass to proguard.
Proguard_flags []string
// Specifies the locations of files containing proguard flags.
Proguard_flags_files []string `android:"path"`
+
+ // If true, transitive reverse dependencies of this module will have this
+ // module's proguard spec appended to their optimization action
+ Export_proguard_flags_files *bool
}
// Keep the data uncompressed. We always need uncompressed dex for execution,
@@ -81,16 +91,22 @@ type DexProperties struct {
// Exclude kotlinc generate files: *.kotlin_module, *.kotlin_builtins. Defaults to false.
Exclude_kotlinc_generated_files *bool
+
+ // Disable dex container (also known as "multi-dex").
+ // This may be necessary as a temporary workaround to mask toolchain bugs (see b/341652226).
+ No_dex_container *bool
}
type dexer struct {
dexProperties DexProperties
// list of extra proguard flag files
- extraProguardFlagFiles android.Paths
- proguardDictionary android.OptionalPath
- proguardConfiguration android.OptionalPath
- proguardUsageZip android.OptionalPath
+ extraProguardFlagsFiles android.Paths
+ proguardDictionary android.OptionalPath
+ proguardConfiguration android.OptionalPath
+ proguardUsageZip android.OptionalPath
+ resourcesInput android.OptionalPath
+ resourcesOutput android.OptionalPath
providesTransitiveHeaderJars
}
@@ -99,17 +115,27 @@ func (d *dexer) effectiveOptimizeEnabled() bool {
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
+func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool {
+ return !ctx.Config().Eng() && BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+}
+
+func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
+ return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources)
+}
+
+func (d *dexer) optimizeOrObfuscateEnabled() bool {
+ return d.effectiveOptimizeEnabled() && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
+}
+
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `mkdir -p $$(dirname $tmpJar) && ` +
- `${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$d8Template${config.D8Cmd} ${config.D8Flags} --output $outDir $d8Flags $tmpJar && ` +
+ `$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`,
CommandDeps: []string{
"${config.D8Cmd}",
- "${config.Zip2ZipCmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -128,32 +154,29 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
ExecStrategy: "${config.RED8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "d8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, nil)
+ }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
`mkdir -p $$(dirname ${outUsage}) && ` +
- `mkdir -p $$(dirname $tmpJar) && ` +
- `${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` +
+ `$r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
- `--pg-conf-output ${outConfig} ` +
+ `-printconfiguration ${outConfig} ` +
`-printusage ${outUsage} ` +
- `--deps-file ${out}.d ` +
- `$r8Flags && ` +
+ `--deps-file ${out}.d && ` +
`touch "${outDict}" "${outConfig}" "${outUsage}" && ` +
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`,
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
CommandDeps: []string{
"${config.R8Cmd}",
- "${config.Zip2ZipCmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -161,7 +184,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
"$r8Template": &remoteexec.REParams{
Labels: map[string]string{"type": "compile", "compiler": "r8"},
Inputs: []string{"$implicits", "${config.R8Jar}"},
- OutputFiles: []string{"${outUsage}"},
+ OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}", "${outR8ArtProfile}"},
ExecStrategy: "${config.RER8ExecStrategy}",
ToolchainInputs: []string{"${config.JavaCmd}"},
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
@@ -181,7 +204,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
- "r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"})
+ "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
dexParams *compileDexParams) (flags []string, deps android.Paths) {
@@ -213,8 +236,9 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
// Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
// services.jar), are not classified as stable, which is WAI.
// TODO(b/232073181): Expand to additional min SDK cases after validation.
+ var addAndroidPlatformBuildFlag = false
if !dexParams.sdkVersion.Stable() {
- flags = append(flags, "--android-platform-build")
+ addAndroidPlatformBuildFlag = true
}
effectiveVersion, err := dexParams.minSdkVersion.EffectiveVersion(ctx)
@@ -222,21 +246,40 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
- flags = append(flags, "--min-api "+strconv.Itoa(effectiveVersion.FinalOrFutureInt()))
+ // If the specified SDK level is 10000, then configure the compiler to use the
+ // current platform SDK level and to compile the build as a platform build.
+ var minApiFlagValue = effectiveVersion.FinalOrFutureInt()
+ if minApiFlagValue == 10000 {
+ minApiFlagValue = ctx.Config().PlatformSdkVersion().FinalInt()
+ addAndroidPlatformBuildFlag = true
+ }
+ flags = append(flags, "--min-api "+strconv.Itoa(minApiFlagValue))
+
+ if addAndroidPlatformBuildFlag {
+ flags = append(flags, "--android-platform-build")
+ }
return flags, deps
}
-func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
+func (d *dexer) d8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (d8Flags []string, d8Deps android.Paths, artProfileOutput *android.OutputPath) {
+ flags := dexParams.flags
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...)
d8Deps = append(d8Deps, flags.bootClasspath...)
d8Deps = append(d8Deps, flags.dexClasspath...)
- return d8Flags, d8Deps
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ d8Flags = append(d8Flags, flags...)
+ d8Deps = append(d8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
+
+ return d8Flags, d8Deps, artProfileOutput
}
-func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams) (r8Flags []string, r8Deps android.Paths, artProfileOutput *android.OutputPath) {
+ flags := dexParams.flags
opt := d.dexProperties.Optimize
// When an app contains references to APIs that are not in the SDK specified by
@@ -248,8 +291,8 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
// See b/20667396
var proguardRaiseDeps classpath
ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
- proguardRaiseDeps = append(proguardRaiseDeps, dep.HeaderJars...)
+ dep, _ := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
+ proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
})
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
@@ -283,11 +326,13 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
- flagFiles = append(flagFiles, d.extraProguardFlagFiles...)
+ flagFiles = append(flagFiles, d.extraProguardFlagsFiles...)
// TODO(ccross): static android library proguard files
flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
+ flagFiles = android.FirstUniquePaths(flagFiles)
+
r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
r8Deps = append(r8Deps, flagFiles...)
@@ -299,15 +344,14 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
if BoolDefault(opt.Proguard_compatibility, true) {
r8Flags = append(r8Flags, "--force-proguard-compatibility")
- } else {
+ }
+
+ if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
// TODO(b/213833843): Allow configuration of the prefix via a build variable.
var sourceFilePrefix = "go/retraceme "
var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
- // TODO(b/200967150): Also tag the source file in compat builds.
- if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
- r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
- r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
- }
+ r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
+ r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
}
// TODO(ccross): Don't shrink app instrumentation tests by default.
@@ -337,23 +381,58 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
r8Flags = append(r8Flags, "-ignorewarnings")
}
- return r8Flags, r8Deps
+ // resourcesInput is empty when we don't use resource shrinking, if on, pass these to R8
+ if d.resourcesInput.Valid() {
+ r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
+ r8Deps = append(r8Deps, d.resourcesInput.Path())
+ r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
+ if Bool(opt.Optimized_shrink_resources) {
+ r8Flags = append(r8Flags, "--optimized-resource-shrinking")
+ }
+ }
+
+ if flags, deps, profileOutput := d.addArtProfile(ctx, dexParams); profileOutput != nil {
+ r8Flags = append(r8Flags, flags...)
+ r8Deps = append(r8Deps, deps...)
+ artProfileOutput = profileOutput
+ }
+
+ return r8Flags, r8Deps, artProfileOutput
}
type compileDexParams struct {
- flags javaBuilderFlags
- sdkVersion android.SdkSpec
- minSdkVersion android.ApiLevel
- classesJar android.Path
- jarName string
+ flags javaBuilderFlags
+ sdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
+ classesJar android.Path
+ jarName string
+ artProfileInput *string
}
-func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) android.OutputPath {
+// Adds --art-profile to r8/d8 command.
+// r8/d8 will output a generated profile file to match the optimized dex code.
+func (d *dexer) addArtProfile(ctx android.ModuleContext, dexParams *compileDexParams) (flags []string, deps android.Paths, artProfileOutputPath *android.OutputPath) {
+ if dexParams.artProfileInput != nil {
+ artProfileInputPath := android.PathForModuleSrc(ctx, *dexParams.artProfileInput)
+ artProfileOutputPathValue := android.PathForModuleOut(ctx, "profile.prof.txt").OutputPath
+ artProfileOutputPath = &artProfileOutputPathValue
+ flags = []string{
+ "--art-profile",
+ artProfileInputPath.String(),
+ artProfileOutputPath.String(),
+ }
+ deps = append(deps, artProfileInputPath)
+ }
+ return flags, deps, artProfileOutputPath
+
+}
+
+// Return the compiled dex jar and (optional) profile _after_ r8 optimization
+func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.OutputPath, *android.OutputPath) {
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
- tmpJar := android.PathForModuleOut(ctx, "withres-withoutdex", dexParams.jarName)
zipFlags := "--ignore_missing_files"
if proptools.Bool(d.dexProperties.Uncompress_dex) {
@@ -369,6 +448,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
}
useR8 := d.effectiveOptimizeEnabled()
+ var artProfileOutputPath *android.OutputPath
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
@@ -379,8 +459,14 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
- r8Flags, r8Deps := d.r8Flags(ctx, dexParams.flags)
- r8Deps = append(r8Deps, commonDeps...)
+ resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
+ d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
+ implicitOutputs := android.WritablePaths{
+ proguardDictionary,
+ proguardUsageZip,
+ proguardConfiguration,
+ }
+ r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams)
rule := r8
args := map[string]string{
"r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
@@ -391,49 +477,71 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam
"outUsage": proguardUsage.String(),
"outUsageZip": proguardUsageZip.String(),
"outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
"mergeZipsFlags": mergeZipsFlags,
}
+ if r8ArtProfileOutputPath != nil {
+ artProfileOutputPath = r8ArtProfileOutputPath
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ // Add the implicit r8 Art profile output to args so that r8RE knows
+ // about this implicit output
+ args["outR8ArtProfile"] = artProfileOutputPath.String()
+ }
+
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
args["implicits"] = strings.Join(r8Deps.Strings(), ",")
}
+ if d.resourcesInput.Valid() {
+ implicitOutputs = append(implicitOutputs, resourcesOutput)
+ args["resourcesOutput"] = resourcesOutput.String()
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "r8",
Output: javalibJar,
- ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip},
+ ImplicitOutputs: implicitOutputs,
Input: dexParams.classesJar,
Implicits: r8Deps,
Args: args,
})
} else {
- d8Flags, d8Deps := d8Flags(dexParams.flags)
+ implicitOutputs := android.WritablePaths{}
+ d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+ if d8ArtProfileOutputPath != nil {
+ artProfileOutputPath = d8ArtProfileOutputPath
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ }
d8Deps = append(d8Deps, commonDeps...)
rule := d8
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
rule = d8RE
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "d8",
- Output: javalibJar,
- Input: dexParams.classesJar,
- Implicits: d8Deps,
+ Rule: rule,
+ Description: "d8",
+ Output: javalibJar,
+ Input: dexParams.classesJar,
+ ImplicitOutputs: implicitOutputs,
+ Implicits: d8Deps,
Args: map[string]string{
"d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
"zipFlags": zipFlags,
"outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
"mergeZipsFlags": mergeZipsFlags,
},
})
}
if proptools.Bool(d.dexProperties.Uncompress_dex) {
alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
- TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
+ TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
javalibJar = alignedJavalibJar
}
- return javalibJar
+ return javalibJar, artProfileOutputPath
}
diff --git a/java/dex_test.go b/java/dex_test.go
index 2ba3831f4..4862d06c9 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -327,7 +328,7 @@ func TestD8(t *testing.T) {
fooD8.Args["d8Flags"], staticLibHeader.String())
}
-func TestProguardFlagsInheritance(t *testing.T) {
+func TestProguardFlagsInheritanceStatic(t *testing.T) {
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app {
name: "app",
@@ -380,3 +381,335 @@ func TestProguardFlagsInheritance(t *testing.T) {
android.AssertStringDoesContain(t, "expected tertiary_lib's proguard flags from inherited dep",
appR8.Args["r8Flags"], "tertiary.flags")
}
+
+func TestProguardFlagsInheritance(t *testing.T) {
+ directDepFlagsFileName := "direct_dep.flags"
+ transitiveDepFlagsFileName := "transitive_dep.flags"
+
+ topLevelModules := []struct {
+ name string
+ definition string
+ }{
+ {
+ name: "android_app",
+ definition: `
+ android_app {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ platform_apis: true,
+ }
+ `,
+ },
+ {
+ name: "android_library",
+ definition: `
+ android_library {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ installable: true,
+ optimize: {
+ enabled: true,
+ shrink: true,
+ },
+ }
+ `,
+ },
+ {
+ name: "java_library",
+ definition: `
+ java_library {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ srcs: ["Foo.java"],
+ installable: true,
+ optimize: {
+ enabled: true,
+ shrink: true,
+ },
+ }
+ `,
+ },
+ }
+
+ bp := `
+ android_library {
+ name: "androidlib",
+ static_libs: ["app_dep"],
+ }
+
+ java_library {
+ name: "app_dep",
+ %s: ["dep"],
+ }
+
+ java_library {
+ name: "dep",
+ %s: ["transitive_dep"],
+ optimize: {
+ proguard_flags_files: ["direct_dep.flags"],
+ export_proguard_flags_files: %v,
+ },
+ }
+
+ java_library {
+ name: "transitive_dep",
+ optimize: {
+ proguard_flags_files: ["transitive_dep.flags"],
+ export_proguard_flags_files: %v,
+ },
+ }
+ `
+
+ testcases := []struct {
+ name string
+ depType string
+ depExportsFlagsFiles bool
+ transitiveDepType string
+ transitiveDepExportsFlagsFiles bool
+ expectedFlagsFiles []string
+ }{
+ {
+ name: "libs_export_libs_export",
+ depType: "libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "static_export_libs_export",
+ depType: "static_libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "libs_no-export_static_export",
+ depType: "libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{transitiveDepFlagsFileName},
+ },
+ {
+ name: "static_no-export_static_export",
+ depType: "static_libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "libs_export_libs_no-export",
+ depType: "libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName},
+ },
+ {
+ name: "static_export_libs_no-export",
+ depType: "static_libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName},
+ },
+ {
+ name: "libs_no-export_static_no-export",
+ depType: "libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{},
+ },
+ {
+ name: "static_no-export_static_no-export",
+ depType: "static_libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "libs_no-export_libs_export",
+ depType: "libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{transitiveDepFlagsFileName},
+ },
+ {
+ name: "static_no-export_libs_export",
+ depType: "static_libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "libs_export_static_export",
+ depType: "libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "static_export_static_export",
+ depType: "static_libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: true,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "libs_no-export_libs_no-export",
+ depType: "libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{},
+ },
+ {
+ name: "static_no-export_libs_no-export",
+ depType: "static_libs",
+ depExportsFlagsFiles: false,
+ transitiveDepType: "libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName},
+ },
+ {
+ name: "libs_export_static_no-export",
+ depType: "libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ {
+ name: "static_export_static_no-export",
+ depType: "static_libs",
+ depExportsFlagsFiles: true,
+ transitiveDepType: "static_libs",
+ transitiveDepExportsFlagsFiles: false,
+ expectedFlagsFiles: []string{directDepFlagsFileName, transitiveDepFlagsFileName},
+ },
+ }
+
+ for _, topLevelModuleDef := range topLevelModules {
+ for _, tc := range testcases {
+ t.Run(topLevelModuleDef.name+"-"+tc.name, func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureMergeMockFs(android.MockFS{
+ directDepFlagsFileName: nil,
+ transitiveDepFlagsFileName: nil,
+ }),
+ ).RunTestWithBp(t,
+ topLevelModuleDef.definition+
+ fmt.Sprintf(
+ bp,
+ tc.depType,
+ tc.transitiveDepType,
+ tc.depExportsFlagsFiles,
+ tc.transitiveDepExportsFlagsFiles,
+ ),
+ )
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+
+ shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles)
+ if shouldHaveDepFlags {
+ android.AssertStringDoesContain(t, "expected deps's proguard flags",
+ appR8.Args["r8Flags"], directDepFlagsFileName)
+ } else {
+ android.AssertStringDoesNotContain(t, "app did not expect deps's proguard flags",
+ appR8.Args["r8Flags"], directDepFlagsFileName)
+ }
+
+ shouldHaveTransitiveDepFlags := android.InList(transitiveDepFlagsFileName, tc.expectedFlagsFiles)
+ if shouldHaveTransitiveDepFlags {
+ android.AssertStringDoesContain(t, "expected transitive deps's proguard flags",
+ appR8.Args["r8Flags"], transitiveDepFlagsFileName)
+ } else {
+ android.AssertStringDoesNotContain(t, "app did not expect transitive deps's proguard flags",
+ appR8.Args["r8Flags"], transitiveDepFlagsFileName)
+ }
+ })
+ }
+ }
+}
+
+func TestProguardFlagsInheritanceAppImport(t *testing.T) {
+ bp := `
+ android_app {
+ name: "app",
+ static_libs: ["aarimport"], // this must be static_libs to initate dexing
+ platform_apis: true,
+ }
+
+ android_library_import {
+ name: "aarimport",
+ aars: ["import.aar"],
+ }
+ `
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ android.AssertStringDoesContain(t, "expected aarimports's proguard flags",
+ appR8.Args["r8Flags"], "proguard.txt")
+}
+
+func TestR8FlagsArtProfile(t *testing.T) {
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ dex_preopt: {
+ profile_guided: true,
+ profile: "profile.txt.prof",
+ enable_profile_rewriting: true,
+ },
+ }
+ `)
+
+ app := result.ModuleForTests("app", "android_common")
+ appR8 := app.Rule("r8")
+ android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags",
+ appR8.Args["r8Flags"], "--art-profile")
+
+ appDexpreopt := app.Rule("dexpreopt")
+ android.AssertStringDoesContain(t,
+ "expected --art-profile output to be used to create .prof binary",
+ appDexpreopt.RuleParams.Command,
+ "--create-profile-from=out/soong/.intermediates/app/android_common/profile.prof.txt --output-profile-type=app",
+ )
+}
+
+// This test checks that users explicitly set `enable_profile_rewriting` to true when the following are true
+// 1. optimize or obfuscate is enabled AND
+// 2. dex_preopt.profile_guided is enabled
+//
+// 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) {
+ testJavaError(t,
+ "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on",
+ `
+android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ dex_preopt: {
+ profile_guided: true,
+ profile: "profile.txt.prof",
+ // enable_profile_rewriting is not set, this is an error
+ },
+ optimize: {
+ optimize: true,
+ }
+}`)
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index a96b31281..794924401 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -16,8 +16,11 @@ package java
import (
"path/filepath"
+ "sort"
"strings"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/dexpreopt"
)
@@ -28,7 +31,7 @@ type DexpreopterInterface interface {
IsInstallable() bool
// True if dexpreopt is disabled for the java module.
- dexpreoptDisabled(ctx android.BaseModuleContext) bool
+ dexpreoptDisabled(ctx android.BaseModuleContext, libraryName string) bool
// 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
@@ -78,22 +81,38 @@ func (install *dexpreopterInstall) SubModuleName() string {
func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
return android.AndroidMkEntries{
Class: "ETC",
- SubName: install.SubModuleName(),
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")
+ // Unset LOCAL_SOONG_INSTALLED_MODULE so that this does not default to the primary .apex file
+ // Without this, installation of the dexpreopt artifacts get skipped
+ entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", "")
},
},
}
}
+func (install dexpreopterInstall) PackageFile(ctx android.ModuleContext) android.PackagingSpec {
+ return ctx.PackageFile(install.installDirOnDevice, install.installFileOnDevice, install.outputPathOnHost)
+}
+
+type Dexpreopter struct {
+ dexpreopter
+}
+
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
importDexpreoptProperties ImportDexpreoptProperties
+ // If true, the dexpreopt rules will not be generated
+ // Unlike Dex_preopt.Enabled which is user-facing,
+ // shouldDisableDexpreopt is a mutated propery.
+ shouldDisableDexpreopt bool
+
installPath android.InstallPath
uncompressedDex bool
isSDKLibrary bool
@@ -126,6 +145,10 @@ type dexpreopter struct {
// The path to the profile that dexpreopter accepts. It must be in the binary format. If this is
// set, it overrides the profile settings in `dexpreoptProperties`.
inputProfilePathOnHost android.Path
+
+ // The path to the profile that matches the dex optimized by r8/d8. It is in text format. If this is
+ // set, it will be converted to a binary profile which will be subsequently used for dexpreopt.
+ rewrittenProfile android.Path
}
type DexpreoptProperties struct {
@@ -145,6 +168,11 @@ type DexpreoptProperties struct {
// defaults to searching for a file that matches the name of this module in the default
// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
Profile *string `android:"path"`
+
+ // If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
+ // the optimized dex.
+ // The new profile will be subsequently used as the profile to dexpreopt the dex file.
+ Enable_profile_rewriting *bool
}
Dex_preopt_result struct {
@@ -165,24 +193,47 @@ func init() {
}
func isApexVariant(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return !apexInfo.IsForPlatform()
}
func forPrebuiltApex(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return apexInfo.ForPrebuiltApex
}
-func moduleName(ctx android.BaseModuleContext) string {
- // Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not
- // expected by dexpreopter.
- return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
+// For apex variant of modules, this returns true on the source variant if the prebuilt apex
+// has been selected using apex_contributions.
+// The prebuilt apex will be responsible for generating the dexpreopt rules of the deapexed java lib.
+func disableSourceApexVariant(ctx android.BaseModuleContext) bool {
+ if !isApexVariant(ctx) {
+ return false // platform variant
+ }
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ psi := android.PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDeps(func(am android.Module) {
+ if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok {
+ psi = prebuiltSelectionInfo
+ }
+ })
+ // Find the apex variant for this module
+ _, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
+ disableSource := false
+ // find the selected apexes
+ for _, apexVariant := range apexVariantsWithoutTestApexes {
+ for _, selected := range psi.GetSelectedModulesForApiDomain(apexVariant) {
+ // If the apex_contribution for this api domain contains a prebuilt apex, disable the source variant
+ if strings.HasPrefix(selected, "prebuilt_com.google.android") {
+ disableSource = true
+ }
+ }
+ }
+ return disableSource
}
// Returns whether dexpreopt is applicable to the module.
// When it returns true, neither profile nor dexpreopt artifacts will be generated.
-func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
+func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName string) bool {
if !ctx.Device() {
return true
}
@@ -195,6 +246,10 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
return true
}
+ if d.shouldDisableDexpreopt {
+ return true
+ }
+
// If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be
// dexpreopted.
if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) {
@@ -205,14 +260,37 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
return true
}
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex {
+ // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
+ return false
+ }
+
global := dexpreopt.GetGlobalConfig(ctx)
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
- if isApexVariant(ctx) {
- // Don't preopt APEX variant module unless the module is an APEX system server jar.
+ // Use the libName argument to determine if the library being dexpreopt'd is a system server jar
+ // ctx.ModuleName() is not safe. In case of prebuilt apexes, the dexpreopt rules of system server jars
+ // are created in the ctx object of the top-level prebuilt apex.
+ isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(libName)
+
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex || isApexVariant(ctx) {
+ // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
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 {
@@ -226,16 +304,18 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
}
func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
- if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) || !dexpreopt.IsDex2oatNeeded(ctx) {
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex && dexpreopt.IsDex2oatNeeded(ctx) {
+ // prebuilt apexes can genererate rules to dexpreopt deapexed jars
+ // Add a dex2oat dep aggressively on _every_ apex module
+ dexpreopt.RegisterToolDeps(ctx)
+ return
+ }
+ if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())) || !dexpreopt.IsDex2oatNeeded(ctx) {
return
}
dexpreopt.RegisterToolDeps(ctx)
}
-func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
- return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
-}
-
// Returns the install path of the dex jar of a module.
//
// Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather
@@ -244,20 +324,42 @@ func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath a
// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a
// system server jar, which is fine because we currently only preopt system server jars for APEXes.
func (d *dexpreopter) getInstallPath(
- ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath {
+ ctx android.ModuleContext, libName string, defaultInstallPath android.InstallPath) android.InstallPath {
global := dexpreopt.GetGlobalConfig(ctx)
- if global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) {
- dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, moduleName(ctx))
+ if global.AllApexSystemServerJars(ctx).ContainsJar(libName) {
+ dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, libName)
return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/"))
}
- if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) &&
+ if !d.dexpreoptDisabled(ctx, libName) && isApexVariant(ctx) &&
filepath.Base(defaultInstallPath.PartitionDir()) != "apex" {
ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt")
}
return defaultInstallPath
}
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
+// DexpreoptPrebuiltApexSystemServerJars generates the dexpreopt artifacts from a jar file that has been deapexed from a prebuilt apex
+func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleContext, libraryName string, di *android.DeapexerInfo) {
+ // A single prebuilt apex can have multiple apex system jars
+ // initialize the output path for this dex jar
+ dc := dexpreopt.GetGlobalConfig(ctx)
+ 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))
+
+ d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
+ if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
+ // Set the profile path to guide optimization
+ prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof")
+ if prof == nil {
+ ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex")
+ }
+ d.inputProfilePathOnHost = prof
+ }
+
+ d.dexpreopt(ctx, libraryName, dexJarFile)
+}
+
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.WritablePath) {
global := dexpreopt.GetGlobalConfig(ctx)
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
@@ -270,7 +372,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
- providesUsesLib := moduleName(ctx)
+ providesUsesLib := libName
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
name := ulib.ProvidesUsesLib()
if name != nil {
@@ -280,11 +382,11 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
// If it is test, make config files regardless of its dexpreopt setting.
// The config files are required for apps defined in make which depend on the lib.
- if d.isTest && d.dexpreoptDisabled(ctx) {
+ if d.isTest && d.dexpreoptDisabled(ctx, libName) {
return
}
- isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx))
+ isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(libName)
bootImage := defaultBootImageConfig(ctx)
// When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline
@@ -303,7 +405,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
targets = append(targets, target)
}
}
- if isSystemServerJar && moduleName(ctx) != "com.android.location.provider" {
+ if isSystemServerJar && libName != "com.android.location.provider" {
// If the module is a system server jar, only preopt for the primary arch because the jar can
// only be loaded by system server. "com.android.location.provider" is a special case because
// it's also used by apps as a shared library.
@@ -326,30 +428,39 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
profileIsTextListing := false
+
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
- // If dex_preopt.profile_guided is not set, default it based on the existence of the
- // dexprepot.profile option or the profile class listing.
- if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
+ // If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
+ if d.EnableProfileRewriting() {
+ profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
+ profileIsTextListing = true
+ } else if profile := d.GetProfile(); profile != "" {
+ // If dex_preopt.profile_guided is not set, default it based on the existence of the
+ // dexprepot.profile option or the profile class listing.
profileClassListing = android.OptionalPathForPath(
- android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile)))
+ android.PathForModuleSrc(ctx, profile))
profileBootListing = android.ExistentPathForSource(ctx,
- ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
+ ctx.ModuleDir(), profile+"-boot")
profileIsTextListing = true
} else if global.ProfileDir != "" {
profileClassListing = android.ExistentPathForSource(ctx,
- global.ProfileDir, moduleName(ctx)+".prof")
+ global.ProfileDir, libName+".prof")
}
}
d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid()
+ // A single apex can have multiple system server jars
+ // Use the dexJar to create a unique scope for each
+ dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
+
// Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{
- Name: moduleName(ctx),
+ Name: libName,
DexLocation: dexLocation,
- BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath,
+ BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, libName+".jar").OutputPath,
DexPath: dexJarFile,
ManifestPath: android.OptionalPathForPath(d.manifestFile),
UncompressedDex: d.uncompressedDex,
@@ -373,39 +484,90 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
PreoptBootClassPathDexFiles: dexFiles.Paths(),
PreoptBootClassPathDexLocations: dexLocations,
- PreoptExtractedApk: false,
-
NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
PresignedPrebuilt: d.isPresignedPrebuilt,
}
- d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
+ d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config")
dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
- if d.dexpreoptDisabled(ctx) {
+ if d.dexpreoptDisabled(ctx, libName) {
return
}
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
+ // The root "product_packages.txt" is generated by `build/make/core/Makefile`. It contains a list
+ // of all packages that are installed on the device. We use `grep` to filter the list by the app's
+ // dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
+ // from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
+ productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt")
+ appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "product_packages.txt")
+ appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp")
+ clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts)
+ sort.Strings(clcNames) // The order needs to be deterministic.
+ productPackagesRule := android.NewRuleBuilder(pctx, ctx)
+ if len(clcNames) > 0 {
+ productPackagesRule.Command().
+ Text("grep -F -x").
+ FlagForEachArg("-e ", clcNames).
+ Input(productPackages).
+ FlagWithOutput("> ", appProductPackagesStaging).
+ Text("|| true")
+ } else {
+ productPackagesRule.Command().
+ Text("rm -f").Output(appProductPackagesStaging).
+ Text("&&").
+ Text("touch").Output(appProductPackagesStaging)
+ }
+ productPackagesRule.Command().
+ Text("rsync --checksum").
+ Input(appProductPackagesStaging).
+ 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)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return
}
- dexpreoptRule.Build("dexpreopt", "dexpreopt")
+ dexpreoptRule.Build("dexpreopt"+"."+dexJarStem, "dexpreopt")
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
+ // The current ctx might be of a deapexer module created by a prebuilt apex
+ // Use the path of the dex file to determine the library name
+ isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(dexJarStem)
+ dexpreoptPartition := d.installPath.Partition()
+ // dexpreoptPartition is set to empty for dexpreopts of system APEX and system_other.
+ // In case of system APEX, however, we can set it to "system" manually.
+ // TODO(b/346662300): Let dexpreopter generate the installPath for dexpreopt files instead of
+ // using the dex location to generate the installPath.
+ if isApexSystemServerJar {
+ dexpreoptPartition = "system"
+ }
for _, install := range dexpreoptRule.Installs() {
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
+ partition := dexpreoptPartition
+ if strings.HasPrefix(installDir, partition+"/") {
+ installDir = strings.TrimPrefix(installDir, partition+"/")
+ } else {
+ // If the partition for the installDir is different from the install partition, set the
+ // partition empty to install the dexpreopt files to the desired partition.
+ // TODO(b/346439786): Define and use the dexpreopt module type to avoid this mismatch.
+ partition = ""
+ }
installBase := filepath.Base(install.To)
arch := filepath.Base(installDir)
- installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+ installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir)
isProfile := strings.HasSuffix(installBase, ".prof")
if isProfile {
@@ -423,7 +585,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
// The installs will be handled by Make as sub-modules of the java library.
d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
name: arch + "-" + installBase,
- moduleName: moduleName(ctx),
+ moduleName: libName,
outputPathOnHost: install.From,
installDirOnDevice: installPath,
installFileOnDevice: installBase,
@@ -439,6 +601,37 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
}
}
+func getModuleInstallPathInfo(ctx android.ModuleContext, fullInstallPath string) (android.InstallPath, string, string) {
+ installPath := android.PathForModuleInstall(ctx)
+ installDir, installBase := filepath.Split(strings.TrimPrefix(fullInstallPath, "/"))
+
+ if !strings.HasPrefix(installDir, installPath.Partition()+"/") {
+ // Return empty filename if the install partition is not for the target image.
+ return installPath, "", ""
+ }
+ relDir, err := filepath.Rel(installPath.Partition(), installDir)
+ if err != nil {
+ panic(err)
+ }
+ return installPath, relDir, installBase
+}
+
+// RuleBuilder.Install() adds output-to-install copy pairs to a list for Make. To share this
+// information with PackagingSpec in soong, call PackageFile for them.
+// The install path and the target install partition of the module must be the same.
+func packageFile(ctx android.ModuleContext, install android.RuleBuilderInstall) {
+ installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
+ // Empty name means the install partition is not for the target image.
+ // For the system image, files for "apex" and "system_other" are skipped here.
+ // The skipped "apex" files are for testing only, for example,
+ // "/apex/art_boot_images/javalib/x86/boot.vdex".
+ // TODO(b/320196894): Files for "system_other" are skipped because soong creates the system
+ // image only for now.
+ if name != "" {
+ ctx.PackageFile(installPath.Join(ctx, relDir), name, install.From)
+ }
+}
+
func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall {
return d.builtInstalledForApex
}
@@ -454,3 +647,27 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
func (d *dexpreopter) OutputProfilePathOnHost() android.Path {
return d.outputProfilePathOnHost
}
+
+func (d *dexpreopter) disableDexpreopt() {
+ d.shouldDisableDexpreopt = true
+}
+
+func (d *dexpreopter) EnableProfileRewriting() bool {
+ return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting)
+}
+
+func (d *dexpreopter) GetProfile() string {
+ return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile)
+}
+
+func (d *dexpreopter) GetProfileGuided() bool {
+ return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
+func (d *dexpreopter) GetRewrittenProfile() android.Path {
+ return d.rewrittenProfile
+}
+
+func (d *dexpreopter) SetRewrittenProfile(p android.Path) {
+ d.rewrittenProfile = p
+}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index f477f404e..defa82c0c 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,12 +16,12 @@ package java
import (
"path/filepath"
- "sort"
"strings"
"android/soong/android"
"android/soong/dexpreopt"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -224,6 +224,12 @@ var artApexNames = []string{
"com.google.android.art.testing",
}
+var (
+ dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
+ dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+ apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"}
+)
+
func init() {
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
@@ -232,8 +238,7 @@ func init() {
//
// WARNING: All fields in this struct should be initialized in the genBootImageConfigs function.
// Failure to do so can lead to data races if there is no synchronization enforced ordering between
-// the writer and the reader. Fields which break this rule are marked as deprecated and should be
-// removed and replaced with something else, e.g. providers.
+// the writer and the reader.
type bootImageConfig struct {
// If this image is an extension, the image that it extends.
extends *bootImageConfig
@@ -241,6 +246,9 @@ type bootImageConfig struct {
// Image name (used in directory names and ninja rule names).
name string
+ // If the module with the given name exists, this config is enabled.
+ enabledIfExists string
+
// Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
stem string
@@ -257,10 +265,6 @@ type bootImageConfig struct {
// the location is relative to "/".
installDir string
- // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
- // needed.
- profileInstallPathInApex string
-
// A list of (location, jar) pairs for the Java modules in this image.
modules android.ConfiguredJarList
@@ -274,16 +278,6 @@ type bootImageConfig struct {
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
- // Rules which should be used in make to install the outputs.
- //
- // Deprecated: Not initialized correctly, see struct comment.
- profileInstalls android.RuleBuilderInstalls
-
- // Path to the license metadata file for the module that built the profile.
- //
- // Deprecated: Not initialized correctly, see struct comment.
- profileLicenseMetadataFile android.OptionalPath
-
// Target-dependent fields.
variants []*bootImageVariant
@@ -296,10 +290,9 @@ type bootImageConfig struct {
// The "--single-image" argument.
singleImage bool
- // Profiles imported from other boot image configs. Each element must represent a
- // `bootclasspath_fragment` of an APEX (i.e., the `name` field of each element must refer to the
- // `image_name` property of a `bootclasspath_fragment`).
- profileImports []*bootImageConfig
+ // 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
}
// Target-dependent description of a boot image.
@@ -384,7 +377,7 @@ func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string
m := image.modules.Jar(idx)
name := image.stem
if idx != 0 || image.extends != nil {
- name += "-" + android.ModuleStem(m)
+ name += "-" + android.ModuleStem(ctx.Config(), image.modules.Apex(idx), m)
}
return name
}
@@ -458,18 +451,26 @@ func (image *bootImageConfig) isProfileGuided() bool {
return image.compilerFilter == "speed-profile"
}
+func (image *bootImageConfig) isEnabled(ctx android.BaseModuleContext) bool {
+ return ctx.OtherModuleExists(image.enabledIfExists)
+}
+
func dexpreoptBootJarsFactory() android.SingletonModule {
m := &dexpreoptBootJars{}
- android.InitAndroidModule(m)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
+ ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
+ ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel()
+ })
}
func SkipDexpreoptBootJars(ctx android.PathContext) bool {
- return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages
+ global := dexpreopt.GetGlobalConfig(ctx)
+ return global.DisablePreoptBootImages || !shouldBuildBootImages(ctx.Config(), global)
}
// Singleton module for generating boot image build rules.
@@ -492,37 +493,136 @@ type dexpreoptBootJars struct {
dexpreoptConfigForMake android.WritablePath
}
-// Provide paths to boot images for use by modules that depend upon them.
-//
-// The build rules are created in GenerateSingletonBuildActions().
-func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Placeholder for now.
+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")
}
-// Generate build rules for boot images.
-func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
- // No module has enabled dexpreopting, so we assume there will be no boot image to make.
+func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
+ if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
return
}
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- d.dexpreoptConfigForMake = android.PathForOutput(ctx, toDexpreoptDirName(archType), "dexpreopt.config")
- writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- 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)
}
- defaultImageConfig := defaultBootImageConfig(ctx)
- d.defaultBootImage = defaultImageConfig
imageConfigs := genBootImageConfigs(ctx)
- d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
for _, config := range imageConfigs {
- if config != defaultImageConfig {
+ if !config.isEnabled(ctx) {
+ continue
+ }
+ // For accessing the boot jars.
+ addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ // 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_*
+ apexes := []string{}
+ for i := 0; i < config.modules.Len(); i++ {
+ apexes = append(apexes, config.modules.Apex(i))
+ }
+ addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
+ }
+
+ if ctx.OtherModuleExists("platform-bootclasspath") {
+ // For accessing all bootclasspath fragments.
+ addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag)
+ } 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)
+ }
+}
+
+// Create a dependency from dex_bootjars to the specific apexes selected using all_apex_contributions
+// This dependency will be used to get the path to the deapexed dex boot jars and profile (via a provider)
+func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorContext, apexes ...string) {
+ psi := android.PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(apexContributionsMetadataDepTag, func(am android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists {
+ psi = info
+ }
+ })
+ for _, apex := range apexes {
+ for _, selected := range psi.GetSelectedModulesForApiDomain(apex) {
+ // 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)
+ }
+ }
+ }
+}
+
+func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
+ return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
+ fragments := make(map[string]android.Module)
+ 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
+ }
+ return false
+ }
+ return false
+ })
+ return fragments
+ }).(map[string]android.Module)
+}
+
+func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.Module {
+ return gatherBootclasspathFragments(ctx)[apexName]
+}
+
+// GenerateAndroidBuildActions generates the build rules for boot images.
+func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ imageConfigs := genBootImageConfigs(ctx)
+ d.defaultBootImage = defaultBootImageConfig(ctx)
+ d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
+ var profileInstalls android.RuleBuilderInstalls
+ for _, name := range getImageNames() {
+ config := imageConfigs[name]
+ if config != d.defaultBootImage {
d.otherImages = append(d.otherImages, config)
}
+ if !config.isEnabled(ctx) {
+ continue
+ }
+ installs := generateBootImage(ctx, config)
+ profileInstalls = append(profileInstalls, installs...)
+ if config == d.defaultBootImage {
+ _, installs := bootFrameworkProfileRule(ctx, config)
+ profileInstalls = append(profileInstalls, installs...)
+ }
}
+ if len(profileInstalls) > 0 {
+ android.SetProvider(ctx, profileInstallInfoProvider, profileInstallInfo{
+ profileInstalls: profileInstalls,
+ profileLicenseMetadataFile: android.OptionalPathForPath(ctx.LicenseMetadataFile()),
+ })
+ for _, install := range profileInstalls {
+ packageFile(ctx, install)
+ }
+ }
+}
+
+// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
+func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+ d.dexpreoptConfigForMake =
+ android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx), "dexpreopt.config")
+ writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
}
// shouldBuildBootImages determines whether boot images should be built.
@@ -537,6 +637,141 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig
return true
}
+func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) android.RuleBuilderInstalls {
+ apexJarModulePairs := getModulesForImage(ctx, imageConfig)
+
+ // Copy module dex jars to their predefined locations.
+ bootDexJarsByModule := extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx, apexJarModulePairs)
+ copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
+
+ // Build a profile for the image config from the profile at the default path. The profile will
+ // then be used along with profiles imported from APEXes to build the boot image.
+ profile, profileInstalls := bootImageProfileRule(ctx, imageConfig)
+
+ // If dexpreopt of boot image jars should be skipped, stop after generating a profile.
+ global := dexpreopt.GetGlobalConfig(ctx)
+ if SkipDexpreoptBootJars(ctx) || (global.OnlyPreoptArtBootImage && imageConfig.name != "art") {
+ return profileInstalls
+ }
+
+ // Build boot image files for the android variants.
+ androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+
+ // Zip the android variant boot image files up.
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
+
+ // Build boot image files for the host variants. There are use directly by ART host side tests.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
+
+ // Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes.
+ dumpOatRules(ctx, imageConfig)
+
+ return profileInstalls
+}
+
+type apexJarModulePair struct {
+ apex string
+ jarModule android.Module
+}
+
+func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []apexJarModulePair {
+ modules := make([]apexJarModulePair, 0, imageConfig.modules.Len())
+ for i := 0; i < imageConfig.modules.Len(); i++ {
+ found := false
+ for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) {
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ if name == imageConfig.modules.Jar(i) {
+ modules = append(modules, apexJarModulePair{
+ apex: imageConfig.modules.Apex(i),
+ jarModule: module,
+ })
+ found = true
+ break
+ }
+ }
+ if !found && !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf(
+ "Boot image '%s' module '%s' not added as a dependency of dex_bootjars",
+ imageConfig.name,
+ imageConfig.modules.Jar(i))
+ return []apexJarModulePair{}
+ }
+ }
+ return modules
+}
+
+// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for
+// the given modules.
+func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule {
+ apexNameToApexExportInfoMap := getApexNameToApexExportsInfoMap(ctx)
+ encodedDexJarsByModuleName := bootDexJarByModule{}
+ for _, pair := range apexJarModulePairs {
+ dexJarPath := getDexJarForApex(ctx, pair, apexNameToApexExportInfoMap)
+ encodedDexJarsByModuleName.addPath(pair.jarModule, dexJarPath)
+ }
+ return encodedDexJarsByModuleName
+}
+
+type apexNameToApexExportsInfoMap map[string]android.ApexExportsInfo
+
+// javaLibraryPathOnHost returns the path to the java library which is exported by the apex for hiddenapi and dexpreopt and a boolean indicating whether the java library exists
+// For prebuilt apexes, this is created by deapexing the prebuilt apex
+func (m *apexNameToApexExportsInfoMap) javaLibraryDexPathOnHost(ctx android.ModuleContext, apex string, javalib string) (android.Path, bool) {
+ if info, exists := (*m)[apex]; exists {
+ if dex, exists := info.LibraryNameToDexJarPathOnHost[javalib]; exists {
+ return dex, true
+ } else {
+ ctx.ModuleErrorf("Apex %s does not provide a dex boot jar for library %s\n", apex, javalib)
+ }
+ }
+ // An apex entry could not be found. Return false.
+ // TODO: b/308174306 - When all the mainline modules have been flagged, make this a hard error
+ return nil, false
+}
+
+// Returns the stem of an artifact inside a prebuilt apex
+func ModuleStemForDeapexing(m android.Module) string {
+ bmn, _ := m.(interface{ BaseModuleName() string })
+ return bmn.BaseModuleName()
+}
+
+// Returns the java libraries exported by the apex for hiddenapi and dexpreopt
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes return a ApexExportsInfo
+// 2. Legacy: An edge to java_library or java_import (java_sdk_library) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
+func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNameToApexExportsInfoMap apexNameToApexExportsInfoMap) android.Path {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, ModuleStemForDeapexing(pair.jarModule)); found {
+ return dex
+ }
+ // TODO: b/308174306 - Remove the legacy mechanism
+ if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
+ // This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
+ // files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
+ // a source APEX because there is no guarantee that it is the same as the jar packed into the
+ // APEX. In practice, they are the same when we are building from a full source tree, but they
+ // are different when we are building from a thin manifest (e.g., master-art), where there is
+ // no monolithic hidden API files at all.
+ return retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
+ } else {
+ // Use exactly the same jar that is packed into the APEX.
+ fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
+ "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
+ pair.jarModule.Name(),
+ pair.apex)
+ }
+ bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
+ jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+ return jar
+ }
+ return nil
+}
+
// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
// paths in the global config.
func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
@@ -666,6 +901,66 @@ type bootImageVariantOutputs struct {
config *bootImageVariant
}
+// Returns the profile file for an apex
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes return a BootclasspathFragmentApexContentInfo
+// 2. Legacy: An edge to bootclasspath_fragment module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
+func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameToBcpInfoMap map[string]android.ApexExportsInfo) android.Path {
+ if info, exists := apexNameToBcpInfoMap[apexName]; exists {
+ return info.ProfilePathOnHost
+ }
+ // TODO: b/308174306 - Remove the legacy mechanism
+ fragment := getBootclasspathFragmentByApex(ctx, apexName)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot image config imports profile from '%[2]s', but a "+
+ "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
+ "dependency of dex_bootjars",
+ apexName)
+ return nil
+ }
+ return fragment.(commonBootclasspathFragment).getProfilePath()
+}
+
+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
+ }
+ })
+ return apexNameToApexExportsInfoMap
+}
+
+func packageFileForTargetImage(ctx android.ModuleContext, image *bootImageVariant) {
+ if image.target.Os != ctx.Os() {
+ // This is not for the target device.
+ return
+ }
+
+ for _, install := range image.installs {
+ packageFile(ctx, install)
+ }
+
+ for _, install := range image.vdexInstalls {
+ if image.target.Arch.ArchType.Name != ctx.DeviceConfig().DeviceArch() {
+ // Note that the vdex files are identical between architectures. If the target image is
+ // not for the primary architecture create symlinks to share the vdex of the primary
+ // architecture with the other architectures.
+ //
+ // Assuming that the install path has the architecture name with it, replace the
+ // architecture name with the primary architecture name to find the source vdex file.
+ installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
+ if name != "" {
+ srcRelDir := strings.Replace(relDir, image.target.Arch.ArchType.Name, ctx.DeviceConfig().DeviceArch(), 1)
+ ctx.InstallSymlink(installPath.Join(ctx, relDir), name, installPath.Join(ctx, srcRelDir, name))
+ }
+ } else {
+ packageFile(ctx, install)
+ }
+ }
+}
+
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -687,10 +982,12 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
rule.Command().Text("rm").Flag("-f").
Flag(symbolsDir.Join(ctx, "*.art").String()).
Flag(symbolsDir.Join(ctx, "*.oat").String()).
+ Flag(symbolsDir.Join(ctx, "*.vdex").String()).
Flag(symbolsDir.Join(ctx, "*.invocation").String())
rule.Command().Text("rm").Flag("-f").
Flag(outputDir.Join(ctx, "*.art").String()).
Flag(outputDir.Join(ctx, "*.oat").String()).
+ Flag(outputDir.Join(ctx, "*.vdex").String()).
Flag(outputDir.Join(ctx, "*.invocation").String())
cmd := rule.Command()
@@ -706,42 +1003,30 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
+ apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
+
cmd.Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
- if profile != nil {
- cmd.FlagWithInput("--profile-file=", profile)
- }
-
- fragments := make(map[string]commonBootclasspathFragment)
- ctx.VisitDirectDepsWithTag(bootclasspathFragmentDepTag, func(child android.Module) {
- fragment := child.(commonBootclasspathFragment)
- if fragment.getImageName() != nil && android.IsModulePreferred(child) {
- fragments[*fragment.getImageName()] = fragment
+ if image.isProfileGuided() && !global.DisableGenerateProfile {
+ if profile != nil {
+ cmd.FlagWithInput("--profile-file=", profile)
}
- })
- for _, profileImport := range image.profileImports {
- fragment := fragments[profileImport.name]
- if fragment == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
- "bootclasspath_fragment with image name '%[2]s' doesn't exist or is not added as a "+
- "dependency of '%[1]s'",
- image.name,
- profileImport.name)
- return bootImageVariantOutputs{}
- }
- if fragment.getProfilePath() == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
- "doesn't provide a profile",
- image.name,
- profileImport.name)
- return bootImageVariantOutputs{}
+ for _, apex := range image.profileImports {
+ importedProfile := getProfilePathForApex(ctx, apex, apexNameToApexExportsInfoMap)
+ if importedProfile == nil {
+ ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
+ "doesn't provide a profile",
+ image.name,
+ apex)
+ return bootImageVariantOutputs{}
+ }
+ cmd.FlagWithInput("--profile-file=", importedProfile)
}
- cmd.FlagWithInput("--profile-file=", fragment.getProfilePath())
}
dirtyImageFile := "frameworks/base/config/dirty-image-objects"
@@ -789,7 +1074,6 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
Flag("--generate-build-id").
Flag("--image-format=lz4hc").
FlagWithArg("--oat-symbols=", symbolsFile.String()).
- Flag("--strip").
FlagWithArg("--oat-file=", outputPath.String()).
FlagWithArg("--oat-location=", oatLocation).
FlagWithArg("--image=", imagePath.String()).
@@ -799,6 +1083,11 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
Flag("--force-determinism").
Flag("--abort-on-hard-verifier-error")
+ // We don't strip on host to make perf tools work.
+ if image.target.Os == android.Android {
+ cmd.Flag("--strip")
+ }
+
// If the image is profile-guided but the profile is disabled, we omit "--compiler-filter" to
// leave the decision to dex2oat to pick the compiler filter.
if !(image.isProfileGuided() && global.DisableGenerateProfile) {
@@ -816,8 +1105,8 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
}
- if global.EnableUffdGc {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
}
if global.BootFlags != "" {
@@ -866,9 +1155,10 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
image.installs = rule.Installs()
image.vdexInstalls = vdexInstalls
image.unstrippedInstalls = unstrippedInstalls
+ packageFileForTargetImage(ctx, image)
// Only set the licenseMetadataFile from the active module.
- if isActiveModule(ctx.Module()) {
+ if isActiveModule(ctx, ctx.Module()) {
image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
}
@@ -881,11 +1171,7 @@ const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
-func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
- if !image.isProfileGuided() {
- return nil
- }
-
+func bootImageProfileRuleCommon(ctx android.ModuleContext, name string, dexFiles android.Paths, dexLocations []string) android.WritablePath {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -912,39 +1198,58 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and
if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() {
profiles = append(profiles, path.Path())
}
- bootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
+ bootImageProfile := android.PathForModuleOut(ctx, name, "boot-image-profile.txt")
rule.Command().Text("cat").Inputs(profiles).Text(">").Output(bootImageProfile)
- profile := image.dir.Join(ctx, "boot.prof")
+ profile := android.PathForModuleOut(ctx, name, "boot.prof")
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
Tool(globalSoong.Profman).
Flag("--output-profile-type=boot").
FlagWithInput("--create-profile-from=", bootImageProfile).
- FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
+ FlagForEachInput("--apk=", dexFiles).
+ FlagForEachArg("--dex-location=", dexLocations).
FlagWithOutput("--reference-profile-file=", profile)
- if image == defaultBootImageConfig(ctx) {
- rule.Install(profile, "/system/etc/boot-image.prof")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
+ rule.Build("bootJarsProfile_"+name, "profile boot jars "+name)
+
+ return profile
+}
+
+type profileInstallInfo struct {
+ // Rules which should be used in make to install the outputs.
+ profileInstalls android.RuleBuilderInstalls
+
+ // Path to the license metadata file for the module that built the profile.
+ profileLicenseMetadataFile android.OptionalPath
+}
+
+var profileInstallInfoProvider = blueprint.NewProvider[profileInstallInfo]()
+
+func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) {
+ if !image.isProfileGuided() {
+ return nil, nil
}
- rule.Build("bootJarsProfile", "profile boot jars")
+ profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps)
- return profile
+ if image == defaultBootImageConfig(ctx) {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Install(profile, "/system/etc/boot-image.prof")
+ return profile, rule.Installs()
+ }
+ return profile, nil
}
// bootFrameworkProfileRule generates the rule to create the boot framework profile and
// returns a path to the generated file.
-func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
- return nil
+ return nil, nil
}
defaultProfile := "frameworks/base/config/boot-profile.txt"
@@ -964,14 +1269,13 @@ func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig)
rule.Install(profile, "/system/etc/boot-image.bprof")
rule.Build("bootFrameworkProfile", "profile boot framework jars")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
-
- return profile
+ return profile, rule.Installs()
}
func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
var allPhonies android.Paths
+ name := image.name
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
for _, image := range image.variants {
arch := image.target.Arch.ArchType
suffix := arch.String()
@@ -980,36 +1284,40 @@ func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
suffix = "host-" + suffix
}
// Create a rule to call oatdump.
- output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
+ output := android.PathForOutput(ctx, name+"."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder(pctx, ctx)
imageLocationsOnHost, _ := image.imageLocations()
- rule.Command().
+
+ cmd := rule.Command().
BuiltTool("oatdump").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
- rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
+ }
+ rule.Build("dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
// Create a phony rule that depends on the output file and prints the path.
- phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
+ phony := android.PathForPhony(ctx, "dump-oat-"+name+"-"+suffix)
rule = android.NewRuleBuilder(pctx, ctx)
rule.Command().
Implicit(output).
ImplicitOutput(phony).
Text("echo").FlagWithArg("Output in ", output.String())
- rule.Build("phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
+ rule.Build("phony-dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
allPhonies = append(allPhonies, phony)
}
- phony := android.PathForPhony(ctx, "dump-oat-boot")
+ phony := android.PathForPhony(ctx, "dump-oat-"+name)
ctx.Build(pctx, android.BuildParams{
Rule: android.Phony,
Output: phony,
Inputs: allPhonies,
- Description: "dump-oat-boot",
+ Description: "dump-oat-" + name,
})
}
@@ -1030,9 +1338,11 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
image := d.defaultBootImage
if image != nil {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
- if image.profileLicenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", image.profileLicenseMetadataFile.String())
+ if profileInstallInfo, ok := android.SingletonModuleProvider(ctx, d, profileInstallInfoProvider); ok {
+ ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", profileInstallInfo.profileInstalls.String())
+ if profileInstallInfo.profileLicenseMetadataFile.Valid() {
+ ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", profileInstallInfo.profileLicenseMetadataFile.String())
+ }
}
if SkipDexpreoptBootJars(ctx) {
@@ -1044,11 +1354,9 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
- var imageNames []string
// The primary ART boot image is exposed to Make for testing (gtests) and benchmarking
// (golem) purposes.
for _, current := range append(d.otherImages, image) {
- imageNames = append(imageNames, current.name)
for _, variant := range current.variants {
suffix := ""
if variant.target.Os.Class == android.Host {
@@ -1069,8 +1377,6 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
- // Ensure determinism.
- sort.Strings(imageNames)
- ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
+ ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(getImageNames(), " "))
}
}
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
index 83c088cd4..33be60352 100644
--- a/java/dexpreopt_check.go
+++ b/java/dexpreopt_check.go
@@ -28,7 +28,7 @@ func init() {
}
func RegisterDexpreoptCheckBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonModuleType("dexpreopt_systemserver_check", dexpreoptSystemserverCheckFactory)
+ ctx.RegisterParallelSingletonModuleType("dexpreopt_systemserver_check", dexpreoptSystemserverCheckFactory)
}
// A build-time check to verify if all compilation artifacts of system server jars are installed
@@ -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/dexpreopt_config.go b/java/dexpreopt_config.go
index 9100e87c6..dc0973cdf 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -40,57 +40,67 @@ func dexpreoptTargets(ctx android.PathContext) []android.Target {
}
var (
- bootImageConfigKey = android.NewOnceKey("bootImageConfig")
- bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
- artBootImageName = "art"
- frameworkBootImageName = "boot"
- mainlineBootImageName = "mainline"
- bootImageStem = "boot"
+ bootImageConfigKey = android.NewOnceKey("bootImageConfig")
+ bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
+ frameworkBootImageName = "boot"
+ mainlineBootImageName = "mainline"
+ bootImageStem = "boot"
+ ProfileInstallPathInApex = "etc/boot-image.prof"
)
+// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be
+// deterministic. The names listed here must match the map keys returned by genBootImageConfigs.
+func getImageNames() []string {
+ return []string{"art", "boot", "mainline"}
+}
+
func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigRawKey, func() interface{} {
global := dexpreopt.GetGlobalConfig(ctx)
- artModules := global.ArtApexJars
- frameworkModules := global.BootJars // This includes `artModules`.
+ artBootImageName := "art" // Keep this local to avoid accidental references.
+ frameworkModules := global.BootJars // This includes `global.ArtApexJars`.
mainlineBcpModules := global.ApexBootJars
frameworkSubdir := "system/framework"
- // ART config for the primary boot image in the ART apex.
- // It includes the Core Libraries.
+ profileImports := []string{"com.android.art"}
+
+ // ART boot image for testing only. Do not rely on it to make any build-time decision.
artCfg := bootImageConfig{
- name: artBootImageName,
- stem: bootImageStem,
- installDir: "apex/art_boot_images/javalib",
- profileInstallPathInApex: "etc/boot-image.prof",
- modules: artModules,
- preloadedClassesFile: "art/build/boot/preloaded-classes",
- compilerFilter: "speed-profile",
- singleImage: false,
+ 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,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
name: frameworkBootImageName,
+ enabledIfExists: "platform-bootclasspath",
stem: bootImageStem,
installDir: frameworkSubdir,
modules: frameworkModules,
preloadedClassesFile: "frameworks/base/config/preloaded-classes",
compilerFilter: "speed-profile",
singleImage: false,
- profileImports: []*bootImageConfig{&artCfg},
+ profileImports: profileImports,
}
mainlineCfg := bootImageConfig{
- extends: &frameworkCfg,
- name: mainlineBootImageName,
- stem: bootImageStem,
- installDir: frameworkSubdir,
- modules: mainlineBcpModules,
- compilerFilter: "verify",
- singleImage: true,
+ extends: &frameworkCfg,
+ name: mainlineBootImageName,
+ enabledIfExists: "platform-bootclasspath",
+ stem: bootImageStem,
+ installDir: frameworkSubdir,
+ modules: mainlineBcpModules,
+ compilerFilter: "verify",
+ singleImage: true,
}
return map[string]*bootImageConfig{
@@ -105,8 +115,7 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
targets := dexpreoptTargets(ctx)
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- deviceDir := android.PathForOutput(ctx, toDexpreoptDirName(archType))
+ deviceDir := android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx))
configs := genBootImageConfigRaw(ctx)
@@ -181,10 +190,6 @@ func calculateDepsRecursive(c *bootImageConfig, targets []android.Target, visite
}
}
-func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
- return genBootImageConfigs(ctx)[artBootImageName]
-}
-
func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
return genBootImageConfigs(ctx)[frameworkBootImageName]
}
@@ -193,65 +198,35 @@ func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig {
return genBootImageConfigs(ctx)[mainlineBootImageName]
}
-// Apex boot config allows to access build/install paths of apex boot jars without going
-// through the usual trouble of registering dependencies on those modules and extracting build paths
-// from those dependencies.
-type apexBootConfig struct {
- // A list of apex boot jars.
- modules android.ConfiguredJarList
-
- // A list of predefined build paths to apex boot jars. They are configured very early,
- // before the modules for these jars are processed and the actual paths are generated, and
- // later on a singleton adds commands to copy actual jars to the predefined paths.
- dexPaths android.WritablePaths
-
- // Map from module name (without prebuilt_ prefix) to the predefined build path.
- dexPathsByModule map[string]android.WritablePath
-
- // A list of dex locations (a.k.a. on-device paths) to the boot jars.
- dexLocations []string
-}
-
-var updatableBootConfigKey = android.NewOnceKey("apexBootConfig")
-
-// Returns apex boot config.
-func GetApexBootConfig(ctx android.PathContext) apexBootConfig {
- return ctx.Config().Once(updatableBootConfigKey, func() interface{} {
- apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- dir := android.PathForOutput(ctx, toDexpreoptDirName(archType), "apex_bootjars")
- dexPaths := apexBootJars.BuildPaths(ctx, dir)
- dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir)
-
- dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android)
-
- return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations}
- }).(apexBootConfig)
+// isProfileProviderApex returns true if this apex provides a boot image profile.
+func isProfileProviderApex(ctx android.PathContext, apexName string) bool {
+ for _, config := range genBootImageConfigs(ctx) {
+ for _, profileImport := range config.profileImports {
+ if profileImport == apexName {
+ return true
+ }
+ }
+ }
+ return false
}
// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be
// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat).
func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) {
- // Non-updatable boot jars (they are used both in the boot image and in dexpreopt).
bootImage := defaultBootImageConfig(ctx)
+ if withUpdatable {
+ bootImage = mainlineBootImageConfig(ctx)
+ }
+
dexPaths := bootImage.dexPathsDeps
// The dex locations for all Android variants are identical.
dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
- if withUpdatable {
- // Apex boot jars (they are used only in dexpreopt, but not in the boot image).
- apexBootConfig := GetApexBootConfig(ctx)
- dexPaths = append(dexPaths, apexBootConfig.dexPaths...)
- dexLocations = append(dexLocations, apexBootConfig.dexLocations...)
- }
-
return dexPaths, dexLocations
}
var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
-var copyOf = android.CopyOf
-
func init() {
android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars)
}
@@ -259,7 +234,3 @@ func init() {
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
}
-
-func toDexpreoptDirName(arch android.ArchType) string {
- return "dexpreopt_" + arch.String()
-}
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index cd7f295c8..44d2127fd 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -16,6 +16,7 @@ package java
import (
"runtime"
+ "sort"
"testing"
"android/soong/android"
@@ -35,3 +36,22 @@ func TestBootImageConfig(t *testing.T) {
CheckFrameworkBootImageConfig(t, result)
CheckMainlineBootImageConfig(t, result)
}
+
+func TestImageNames(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForBootImageConfigTest,
+ ).RunTest(t)
+
+ names := getImageNames()
+ sort.Strings(names)
+
+ ctx := &android.TestPathContext{TestResult: result}
+ configs := genBootImageConfigs(ctx)
+ namesFromConfigs := make([]string, 0, len(configs))
+ for name, _ := range configs {
+ namesFromConfigs = append(namesFromConfigs, name)
+ }
+ sort.Strings(namesFromConfigs)
+
+ android.AssertArrayString(t, "getImageNames vs genBootImageConfigs", names, namesFromConfigs)
+}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 6f3aa2be8..104829f5f 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -29,6 +29,7 @@ import (
"testing"
"android/soong/android"
+ "android/soong/dexpreopt"
)
// PrepareForBootImageConfigTest is the minimal set of preparers that are needed to be able to use
@@ -36,7 +37,17 @@ import (
var PrepareForBootImageConfigTest = android.GroupFixturePreparers(
android.PrepareForTestWithArchMutator,
android.PrepareForTestAccessingMakeVars,
+ PrepareForTestWithDexpreopt,
FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"),
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:core1", "com.android.art:core2", "platform:extra1"),
+ android.FixtureAddTextFile("extra1/Android.bp", `
+ java_library {
+ name: "extra1",
+ srcs: ["extra1.java"],
+ installable: true,
+ }
+ `),
+ android.FixtureAddFile("extra1/extra1.java", nil),
)
var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
@@ -44,18 +55,18 @@ var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
var PrepareApexBootJarConfigsAndModules = android.GroupFixturePreparers(
PrepareApexBootJarConfigs,
- prepareApexBootJarModule("com.android.foo", "framework-foo"),
- prepareApexBootJarModule("com.android.bar", "framework-bar"),
+ PrepareApexBootJarModule("com.android.foo", "framework-foo"),
+ PrepareApexBootJarModule("com.android.bar", "framework-bar"),
)
var ApexBootJarFragmentsForPlatformBootclasspath = fmt.Sprintf(`
{
apex: "%[1]s",
- module: "%[1]s-bootclasspathfragment",
+ module: "%[1]s-bootclasspath-fragment",
},
{
apex: "%[2]s",
- module: "%[2]s-bootclasspathfragment",
+ module: "%[2]s-bootclasspath-fragment",
},
`, "com.android.foo", "com.android.bar")
@@ -64,15 +75,22 @@ var ApexBootJarDexJarPaths = []string{
"out/soong/.intermediates/packages/modules/com.android.foo/framework-foo/android_common_apex10000/aligned/framework-foo.jar",
}
-func prepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
+func PrepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
moduleSourceDir := fmt.Sprintf("packages/modules/%s", apexName)
+ fragmentName := apexName + "-bootclasspath-fragment"
+ imageNameProp := ""
+ if apexName == "com.android.art" {
+ fragmentName = "art-bootclasspath-fragment"
+ imageNameProp = `image_name: "art",`
+ }
+
return android.GroupFixturePreparers(
android.FixtureAddTextFile(moduleSourceDir+"/Android.bp", fmt.Sprintf(`
apex {
name: "%[1]s",
key: "%[1]s.key",
bootclasspath_fragments: [
- "%[1]s-bootclasspathfragment",
+ "%[3]s",
],
updatable: false,
}
@@ -84,7 +102,8 @@ func prepareApexBootJarModule(apexName string, moduleName string) android.Fixtur
}
bootclasspath_fragment {
- name: "%[1]s-bootclasspathfragment",
+ name: "%[3]s",
+ %[4]s
contents: ["%[2]s"],
apex_available: ["%[1]s"],
hidden_api: {
@@ -100,7 +119,7 @@ func prepareApexBootJarModule(apexName string, moduleName string) android.Fixtur
compile_dex: true,
apex_available: ["%[1]s"],
}
- `, apexName, moduleName)),
+ `, apexName, moduleName, fragmentName, imageNameProp)),
android.FixtureMergeMockFs(android.MockFS{
fmt.Sprintf("%s/apex_manifest.json", moduleSourceDir): nil,
fmt.Sprintf("%s/%s.avbpubkey", moduleSourceDir, apexName): nil,
@@ -192,7 +211,7 @@ func CheckArtBootImageConfig(t *testing.T, result *android.TestResult) {
// getArtImageConfig gets the ART bootImageConfig that was created during the test.
func getArtImageConfig(result *android.TestResult) *bootImageConfig {
pathCtx := &android.TestPathContext{TestResult: result}
- imageConfig := artBootImageConfig(pathCtx)
+ imageConfig := genBootImageConfigs(pathCtx)["art"]
return imageConfig
}
@@ -210,15 +229,15 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
symbolsDir: "out/soong/dexpreopt_arm64/dex_artjars_unstripped",
installDir: "apex/art_boot_images/javalib",
profileInstallPathInApex: "etc/boot-image.prof",
- modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2"}),
- dexPaths: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
- dexPathsDeps: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
+ modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2", "platform:extra1"}),
+ dexPaths: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
+ dexPathsDeps: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
zip: "out/soong/dexpreopt_arm64/dex_artjars/art.zip",
variants: []*expectedVariant{
{
archType: android.Arm64,
- dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/arm64/boot.art",
imagesDeps: []string{
@@ -228,6 +247,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -246,6 +268,14 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ },
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -256,6 +286,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -266,13 +300,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.Arm,
- dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/arm/boot.art",
imagesDeps: []string{
@@ -282,6 +320,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -300,6 +341,14 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ },
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -310,6 +359,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/arm/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -320,13 +373,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.X86_64,
- dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/x86_64/boot.art",
imagesDeps: []string{
@@ -336,6 +393,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -352,6 +412,13 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ }, {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -362,6 +429,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -372,13 +443,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.X86,
- dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/x86/boot.art",
imagesDeps: []string{
@@ -388,6 +463,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -404,6 +482,13 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ }, {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -414,6 +499,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/x86/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -424,13 +513,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
},
}
- checkBootImageConfig(t, imageConfig, mutated, expected)
+ checkBootImageConfig(t, result, imageConfig, mutated, expected)
}
// getFrameworkImageConfig gets the framework bootImageConfig that was created during the test.
@@ -805,13 +898,13 @@ func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mut
},
},
profileInstalls: []normalizedInstall{
+ {from: "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"},
{from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"},
- {from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.prof", to: "/system/etc/boot-image.prof"},
},
profileLicenseMetadataFile: expectedLicenseMetadataFile,
}
- checkBootImageConfig(t, imageConfig, mutated, expected)
+ checkBootImageConfig(t, result, imageConfig, mutated, expected)
}
// getMainlineImageConfig gets the framework bootImageConfig that was created during the test.
@@ -1090,7 +1183,7 @@ func CheckMainlineBootImageConfig(t *testing.T, result *android.TestResult) {
profileLicenseMetadataFile: expectedLicenseMetadataFile,
}
- checkBootImageConfig(t, imageConfig, false, expected)
+ checkBootImageConfig(t, result, imageConfig, false, expected)
}
// clearMutatedFields clears fields in the expectedConfig that correspond to fields in the
@@ -1118,32 +1211,36 @@ func clearMutatedFields(expected *expectedConfig) {
// zero value so that they will match the unmodified values in the boot image.
//
// It runs the checks in an image specific subtest of the current test.
-func checkBootImageConfig(t *testing.T, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
+func checkBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
if !mutated {
clearMutatedFields(expected)
}
t.Run(imageConfig.name, func(t *testing.T) {
- nestedCheckBootImageConfig(t, imageConfig, expected)
+ nestedCheckBootImageConfig(t, result, imageConfig, mutated, expected)
})
}
// nestedCheckBootImageConfig does the work of comparing the image against the expected values and
// is run in an image specific subtest.
-func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expected *expectedConfig) {
+func nestedCheckBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
android.AssertStringEquals(t, "name", expected.name, imageConfig.name)
android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem)
android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir)
android.AssertPathRelativeToTopEquals(t, "symbolsDir", expected.symbolsDir, imageConfig.symbolsDir)
android.AssertStringEquals(t, "installDir", expected.installDir, imageConfig.installDir)
- android.AssertStringEquals(t, "profileInstallPathInApex", expected.profileInstallPathInApex, imageConfig.profileInstallPathInApex)
android.AssertDeepEquals(t, "modules", expected.modules, imageConfig.modules)
android.AssertPathsRelativeToTopEquals(t, "dexPaths", expected.dexPaths, imageConfig.dexPaths.Paths())
android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths())
// dexPathsByModule is just a different representation of the other information in the config.
android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip)
- assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, imageConfig.profileInstalls)
- android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, imageConfig.profileLicenseMetadataFile.RelativeToTop().String())
+
+ if !mutated {
+ dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common")
+ profileInstallInfo, _ := android.SingletonModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider)
+ assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls)
+ android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String())
+ }
android.AssertIntEquals(t, "variant count", 4, len(imageConfig.variants))
for i, variant := range imageConfig.variants {
@@ -1195,10 +1292,10 @@ DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/dexpreopt_arm64/dex_bootjars_input/c
DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS=/apex/com.android.art/javalib/core1.jar /apex/com.android.art/javalib/core2.jar /system/framework/framework.jar
DEXPREOPT_BOOT_JARS_MODULES=com.android.art:core1:com.android.art:core2:platform:framework
DEXPREOPT_GEN=out/host/linux-x86/bin/dexpreopt_gen
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art:/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art:/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art:/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art:/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art:/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art:/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art:/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art:/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art:/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art:/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art:/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1207,10 +1304,10 @@ DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm64/dex_mainl
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art:/system/framework/arm64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art:/system/framework/x86/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art:/system/framework/x86_64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
DEXPREOPT_IMAGE_DEPS_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex
@@ -1223,14 +1320,14 @@ DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/apex/art_boot_images/javalib/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework-foo.art
@@ -1238,12 +1335,12 @@ DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/dexpreopt_arm64/dex_artjars/andro
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
DEXPREOPT_IMAGE_NAMES=art boot mainline
-DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/dexpreopt_arm64/dex_bootjars/boot.prof:/system/etc/boot-image.prof
-DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof
+DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1252,10 +1349,10 @@ DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm6
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex:/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex:/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex:/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex:/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex:/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex:/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex:/system/framework/arm/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex:/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex:/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex:/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex:/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index fedd5640e..73e33f4fb 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -410,7 +410,7 @@ func TestAndroidMkEntriesForApex(t *testing.T) {
verifyEntries(t,
"entriesList[0]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- "/dexpreopt/oat/arm64/javalib.odex",
+ "/dexpreopt/service-foo/oat/arm64/javalib.odex",
"/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
entriesList[0])
@@ -418,7 +418,7 @@ func TestAndroidMkEntriesForApex(t *testing.T) {
verifyEntries(t,
"entriesList[1]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- "/dexpreopt/oat/arm64/javalib.vdex",
+ "/dexpreopt/service-foo/oat/arm64/javalib.vdex",
"/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
entriesList[1])
@@ -459,7 +459,7 @@ func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) {
ctx := result.TestContext
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
- expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/profile.prof"}
+ expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/foo/profile.prof"}
android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs())
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index dbe021d00..730f23696 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -135,6 +135,9 @@ type DroiddocProperties struct {
// At some point, this might be improved to show more warnings.
Todo_file *string `android:"path"`
+ // A file containing a baseline for allowed lint errors.
+ Lint_baseline *string `android:"path"`
+
// directory under current module source that provide additional resources (images).
Resourcesdir *string
@@ -179,6 +182,17 @@ func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDevi
func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersionTag string) bool {
if ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") {
+ if ctx.Config().BuildFromTextStub() {
+ ctx.ModuleErrorf("Generating stubs from api signature files is not available " +
+ "with WITHOUT_CHECK_API=true, as sync between the source Java files and the " +
+ "api signature files is not guaranteed.\n" +
+ "In order to utilize WITHOUT_CHECK_API, generate stubs from the source Java " +
+ "files with BUILD_FROM_SOURCE_STUB=true.\n" +
+ "However, the usage of WITHOUT_CHECK_API is not preferred as the incremental " +
+ "build is slower when generating stubs from the source Java files.\n" +
+ "Consider updating the api signature files and generating the stubs from " +
+ "them instead.")
+ }
return false
} else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
return true
@@ -205,17 +219,8 @@ type Javadoc struct {
docZip android.WritablePath
stubsSrcJar android.WritablePath
-}
-func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return android.Paths{j.stubsSrcJar}, nil
- case ".docs.zip":
- return android.Paths{j.docZip}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
+ exportableStubsSrcJar android.WritablePath
}
// javadoc converts .java source files to documentation using javadoc.
@@ -238,8 +243,6 @@ func JavadocHostFactory() android.Module {
return module
}
-var _ android.OutputFileProducer = (*Javadoc)(nil)
-
func (j *Javadoc) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return android.SdkSpecFrom(ctx, String(j.properties.Sdk_version))
}
@@ -299,7 +302,7 @@ func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Op
}
flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
- flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
+ flags = append(flags, "-I"+ctx.ModuleDir())
if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
flags = append(flags, "-I"+src.String())
}
@@ -360,8 +363,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
switch tag {
case bootClasspathTag:
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars...)
} else if sm, ok := module.(SystemModulesProvider); ok {
// A system modules dependency has been added to the bootclasspath
@@ -373,19 +375,19 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
case libTag, sdkLibTag:
if dep, ok := module.(SdkLibraryDependency); ok {
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
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 {
ctx.ModuleErrorf("depends on non-java module %q", otherName)
}
+
case java9LibTag:
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
} else {
ctx.ModuleErrorf("depends on non-java module %q", otherName)
@@ -397,6 +399,18 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
sm := module.(SystemModulesProvider)
outputDir, outputDeps := sm.OutputDirAndDeps()
deps.systemModules = &systemModules{outputDir, outputDeps}
+ case aconfigDeclarationTag:
+ if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
+ "module type is allowed for flags_packages property, but %s is neither "+
+ "of these supported module types",
+ module.Name(),
+ )
+ }
}
})
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
@@ -404,6 +418,19 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
j.implicits = append(j.implicits, srcFiles...)
+ // Module can depend on a java_aconfig_library module using the ":module_name{.tag}" syntax.
+ // Find the corresponding aconfig_declarations module name for such case.
+ for _, src := range j.properties.Srcs {
+ if moduleName, tag := android.SrcIsModuleWithTag(src); moduleName != "" {
+ otherModule := android.GetModuleFromPathDep(ctx, moduleName, tag)
+ if otherModule != nil {
+ if dep, ok := android.OtherModuleProvider(ctx, otherModule, android.CodegenInfoProvider); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
+ }
+ }
+ }
+ }
+
filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
if filterPackages == nil {
return srcs
@@ -545,6 +572,9 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
zipSyncCleanupCmd(rule, srcJarDir)
rule.Build("javadoc", "javadoc")
+
+ ctx.SetOutputFiles(android.Paths{j.stubsSrcJar}, "")
+ ctx.SetOutputFiles(android.Paths{j.docZip}, ".docs.zip")
}
// Droiddoc
@@ -576,15 +606,6 @@ func DroiddocHostFactory() android.Module {
return module
}
-func (d *Droiddoc) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "", ".docs.zip":
- return android.Paths{d.Javadoc.docZip}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
@@ -608,6 +629,11 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule
FlagWithArg("-Xmaxerrs ", "10").
FlagWithArg("-Xmaxwarns ", "10").
Flag("-J--add-exports=jdk.javadoc/jdk.javadoc.internal.doclets.formats.html=ALL-UNNAMED").
+ Flag("-J--add-exports=jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED").
+ Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED").
+ Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED").
+ Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED").
+ Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED").
Flag("-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED").
FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-$(cat "+buildNumberFile.String()+")").OrderOnly(buildNumberFile).
FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
@@ -659,6 +685,10 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule
ImplicitOutput(android.PathForModuleOut(ctx, String(d.properties.Todo_file)))
}
+ if String(d.properties.Lint_baseline) != "" {
+ cmd.FlagWithInput("-lintbaseline ", android.PathForModuleSrc(ctx, String(d.properties.Lint_baseline)))
+ }
+
if String(d.properties.Resourcesdir) != "" {
// TODO: should we add files under resourcesDir to the implicits? It seems that
// resourcesDir is one sub dir of htmlDir
@@ -694,7 +724,6 @@ func javadocCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs andro
cmd := rule.Command().
BuiltTool("soong_javac_wrapper").Tool(config.JavadocCmd(ctx)).
Flag(config.JavacVmFlags).
- FlagWithArg("-encoding ", "UTF-8").
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "javadoc.rsp"), srcs).
FlagWithInput("@", srcJarList)
@@ -828,6 +857,9 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
zipSyncCleanupCmd(rule, srcJarDir)
rule.Build("javadoc", desc)
+
+ ctx.SetOutputFiles(android.Paths{d.Javadoc.docZip}, "")
+ ctx.SetOutputFiles(android.Paths{d.Javadoc.docZip}, ".docs.zip")
}
// Exported Droiddoc Directory
diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go
index 8d1f5917c..e5846407f 100644
--- a/java/droiddoc_test.go
+++ b/java/droiddoc_test.go
@@ -69,11 +69,7 @@ func TestDroiddoc(t *testing.T) {
"bar-doc/a.java": nil,
"bar-doc/b.java": nil,
})
- barStubs := ctx.ModuleForTests("bar-stubs", "android_common")
- barStubsOutputs, err := barStubs.Module().(*Droidstubs).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error %q retrieving \"bar-stubs\" output file", err)
- }
+ barStubsOutputs := ctx.ModuleForTests("bar-stubs", "android_common").OutputFiles(t, "")
if len(barStubsOutputs) != 1 {
t.Errorf("Expected one output from \"bar-stubs\" got %s", barStubsOutputs)
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 8a521aabb..a8e0a22e5 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -18,13 +18,11 @@ import (
"fmt"
"path/filepath"
"regexp"
- "sort"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/java/config"
"android/soong/remoteexec"
)
@@ -32,6 +30,41 @@ import (
// The values allowed for Droidstubs' Api_levels_sdk_type
var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
+type StubsType int
+
+const (
+ Everything StubsType = iota
+ Runtime
+ Exportable
+ Unavailable
+)
+
+func (s StubsType) String() string {
+ switch s {
+ case Everything:
+ return "everything"
+ case Runtime:
+ return "runtime"
+ case Exportable:
+ return "exportable"
+ default:
+ return ""
+ }
+}
+
+func StringToStubsType(s string) StubsType {
+ switch strings.ToLower(s) {
+ case Everything.String():
+ return Everything
+ case Runtime.String():
+ return Runtime
+ case Exportable.String():
+ return Exportable
+ default:
+ return Unavailable
+ }
+}
+
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
}
@@ -45,14 +78,22 @@ func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
}
+type stubsArtifacts struct {
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+ apiVersionsXml android.WritablePath
+ metadataZip android.WritablePath
+ metadataDir android.WritablePath
+}
+
// Droidstubs
type Droidstubs struct {
Javadoc
+ embeddableInModuleAndImport
- properties DroidstubsProperties
- apiFile android.Path
- removedApiFile android.Path
- nullabilityWarningsFile android.WritablePath
+ properties DroidstubsProperties
+ apiFile android.Path
+ removedApiFile android.Path
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
@@ -62,11 +103,11 @@ type Droidstubs struct {
checkNullabilityWarningsTimestamp android.WritablePath
- annotationsZip android.WritablePath
- apiVersionsXml android.WritablePath
+ everythingArtifacts stubsArtifacts
+ exportableArtifacts stubsArtifacts
- metadataZip android.WritablePath
- metadataDir android.WritablePath
+ exportableApiFile android.WritablePath
+ exportableRemovedApiFile android.WritablePath
}
type DroidstubsProperties struct {
@@ -123,7 +164,7 @@ type DroidstubsProperties struct {
Generate_stubs *bool
// if set to true, provides a hint to the build system that this rule uses a lot of memory,
- // whicih can be used for scheduling purposes
+ // which can be used for scheduling purposes
High_mem *bool
// if set to true, Metalava will allow framework SDK to contain API levels annotations.
@@ -152,26 +193,64 @@ type DroidstubsProperties struct {
// API surface of this module. If set, the module contributes to an API surface.
// For the full list of available API surfaces, refer to soong/android/sdk_version.go
Api_surface *string
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
}
// Used by xsd_config
type ApiFilePath interface {
- ApiFilePath() android.Path
+ ApiFilePath(StubsType) (android.Path, error)
}
type ApiStubsSrcProvider interface {
- StubsSrcJar() android.Path
+ StubsSrcJar(StubsType) (android.Path, error)
}
// Provider of information about API stubs, used by java_sdk_library.
type ApiStubsProvider interface {
- AnnotationsZip() android.Path
+ AnnotationsZip(StubsType) (android.Path, error)
ApiFilePath
- RemovedApiFilePath() android.Path
+ RemovedApiFilePath(StubsType) (android.Path, error)
ApiStubsSrcProvider
}
+type currentApiTimestampProvider interface {
+ CurrentApiTimestamp() android.Path
+}
+
+type annotationFlagsParams struct {
+ migratingNullability bool
+ validatingNullability bool
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+}
+type stubsCommandParams struct {
+ srcJarDir android.ModuleOutPath
+ stubsDir android.OptionalPath
+ stubsSrcJar android.WritablePath
+ metadataZip android.WritablePath
+ metadataDir android.WritablePath
+ apiVersionsXml android.WritablePath
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+ stubConfig stubsCommandConfigParams
+}
+type stubsCommandConfigParams struct {
+ stubsType StubsType
+ javaVersion javaVersion
+ deps deps
+ checkApi bool
+ generateStubs bool
+ doApiLint bool
+ doCheckReleased bool
+ writeSdkValues bool
+ migratingNullability bool
+ validatingNullability bool
+}
+
// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
// a droiddoc module to generate documentation.
@@ -180,6 +259,7 @@ func DroidstubsFactory() android.Module {
module.AddProperties(&module.properties,
&module.Javadoc.properties)
+ module.initModuleAndImport(module)
InitDroiddocModule(module, android.HostAndDeviceSupported)
@@ -203,46 +283,100 @@ func DroidstubsHostFactory() android.Module {
return module
}
-func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return android.Paths{d.stubsSrcJar}, nil
- case ".docs.zip":
- return android.Paths{d.docZip}, nil
- case ".api.txt", android.DefaultDistTag:
- // This is the default dist path for dist properties that have no tag property.
- return android.Paths{d.apiFile}, nil
- case ".removed-api.txt":
- return android.Paths{d.removedApiFile}, nil
- case ".annotations.zip":
- return android.Paths{d.annotationsZip}, nil
- case ".api_versions.xml":
- return android.Paths{d.apiVersionsXml}, nil
+func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.everythingArtifacts.annotationsZip, nil
+ case Exportable:
+ ret, err = d.exportableArtifacts.annotationsZip, nil
default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
}
+ return ret, err
}
-func (d *Droidstubs) AnnotationsZip() android.Path {
- return d.annotationsZip
+func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.apiFile, nil
+ case Exportable:
+ ret, err = d.exportableApiFile, nil
+ default:
+ ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) ApiFilePath() android.Path {
- return d.apiFile
+func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.everythingArtifacts.apiVersionsXml, nil
+ case Exportable:
+ ret, err = d.exportableArtifacts.apiVersionsXml, nil
+ default:
+ ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.docZip, nil
+ default:
+ ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.removedApiFile, nil
+ case Exportable:
+ ret, err = d.exportableRemovedApiFile, nil
+ default:
+ ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) RemovedApiFilePath() android.Path {
- return d.removedApiFile
+func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.stubsSrcJar, nil
+ case Exportable:
+ ret, err = d.exportableStubsSrcJar, nil
+ default:
+ ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) StubsSrcJar() android.Path {
- return d.stubsSrcJar
+func (d *Droidstubs) CurrentApiTimestamp() android.Path {
+ return d.checkCurrentApiTimestamp
}
var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
+var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
@@ -265,39 +399,57 @@ func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
+ if len(d.properties.Aconfig_declarations) != 0 {
+ for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
+ }
+ }
+
if d.properties.Api_levels_module != nil {
ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
}
}
-func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
- apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
- String(d.properties.Api_filename) != "" {
- filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
- uncheckedApiFile := android.PathForModuleOut(ctx, "metalava", filename)
- cmd.FlagWithOutput("--api ", uncheckedApiFile)
- d.apiFile = uncheckedApiFile
+func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
+ cmd.FlagWithArg("--sdk-values ", metadataDir.String())
+}
+
+func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
+
+ apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
+ uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
+ cmd.FlagWithOutput("--api ", uncheckedApiFile)
+ if checkApi || String(d.properties.Api_filename) != "" {
+ if stubsType == Everything {
+ d.apiFile = uncheckedApiFile
+ } else if stubsType == Exportable {
+ d.exportableApiFile = uncheckedApiFile
+ }
} else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
- // If check api is disabled then make the source file available for export.
- d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
+ if stubsType == Everything {
+ // If check api is disabled then make the source file available for export.
+ d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
+ } else if stubsType == Exportable {
+ d.exportableApiFile = uncheckedApiFile
+ }
}
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
- apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
- String(d.properties.Removed_api_filename) != "" {
- filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
- uncheckedRemovedFile := android.PathForModuleOut(ctx, "metalava", filename)
- cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
- d.removedApiFile = uncheckedRemovedFile
+ removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
+ uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
+ cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
+ if checkApi || String(d.properties.Removed_api_filename) != "" {
+ if stubsType == Everything {
+ d.removedApiFile = uncheckedRemovedFile
+ } else if stubsType == Exportable {
+ d.exportableRemovedApiFile = uncheckedRemovedFile
+ }
} else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
- // If check api is disabled then make the source removed api file available for export.
- d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
- }
-
- if Bool(d.properties.Write_sdk_values) {
- d.metadataDir = android.PathForModuleOut(ctx, "metalava", "metadata")
- cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
+ if stubsType == Everything {
+ // If check api is disabled then make the source removed api file available for export.
+ d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
+ } else if stubsType == Exportable {
+ d.exportableRemovedApiFile = uncheckedRemovedFile
+ }
}
if stubsDir.Valid() {
@@ -312,46 +464,30 @@ func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuil
}
}
-func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
if Bool(d.properties.Annotations_enabled) {
- cmd.Flag("--include-annotations")
-
- cmd.FlagWithArg("--exclude-annotation ", "androidx.annotation.RequiresApi")
+ cmd.Flag(config.MetalavaAnnotationsFlags)
- validatingNullability :=
- strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
- String(d.properties.Validate_nullability_from_list) != ""
-
- migratingNullability := String(d.properties.Previous_api) != ""
- if migratingNullability {
- previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
- cmd.FlagWithInput("--migrate-nullness ", previousApi)
+ if params.migratingNullability {
+ previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
+ cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
}
if s := String(d.properties.Validate_nullability_from_list); s != "" {
cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
}
- if validatingNullability {
- d.nullabilityWarningsFile = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_nullability_warnings.txt")
- cmd.FlagWithOutput("--nullability-warnings-txt ", d.nullabilityWarningsFile)
+ if params.validatingNullability {
+ cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
}
- d.annotationsZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_annotations.zip")
- cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
+ cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
if len(d.properties.Merge_annotations_dirs) != 0 {
d.mergeAnnoDirFlags(ctx, cmd)
}
- // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
- cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
- FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction").
- // b/222738070
- FlagWithArg("--hide ", "BannedThrow").
- // b/223382732
- FlagWithArg("--hide ", "ChangedDefault")
+ cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
}
}
@@ -377,15 +513,21 @@ func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *a
})
}
-func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
var apiVersions android.Path
if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
- d.apiLevelsGenerationFlags(ctx, cmd)
- apiVersions = d.apiVersionsXml
+ d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
+ apiVersions = apiVersionsXml
} else {
ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
if s, ok := m.(*Droidstubs); ok {
- apiVersions = s.apiVersionsXml
+ if stubsType == Everything {
+ apiVersions = s.everythingArtifacts.apiVersionsXml
+ } else if stubsType == Exportable {
+ apiVersions = s.exportableArtifacts.apiVersionsXml
+ } else {
+ ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
+ }
} else {
ctx.PropertyErrorf("api_levels_module",
"module %q is not a droidstubs module", ctx.OtherModuleName(m))
@@ -399,36 +541,87 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a
}
}
-func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
+// `system-server` directories that contain all the APIs provided by the platform and updatable
+// modules because the `android.jar` files do not. See b/337836752.
+const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
+
+func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
if len(d.properties.Api_levels_annotations_dirs) == 0 {
ctx.PropertyErrorf("api_levels_annotations_dirs",
"has to be non-empty if api levels annotations was enabled!")
}
- d.apiVersionsXml = android.PathForModuleOut(ctx, "metalava", "api-versions.xml")
- cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
+ // TODO: Avoid the duplication of API surfaces, reuse apiScope.
+ // Add all relevant --android-jar-pattern patterns for Metalava.
+ // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
+ // an actual file present on disk (in the order the patterns were passed). For system APIs for
+ // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
+ // for older releases. Similarly, module-lib falls back to system API.
+ var sdkDirs []string
+ apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
+ switch apiLevelsSdkType {
+ case "system-server":
+ sdkDirs = []string{"system-server", "module-lib", "system", "public"}
+ case "module-lib":
+ sdkDirs = []string{"module-lib", "system", "public"}
+ case "system":
+ sdkDirs = []string{"system", "public"}
+ case "public":
+ sdkDirs = []string{"public"}
+ default:
+ ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
+ return
+ }
+
+ // Construct a pattern to match the appropriate extensions that should be included in the
+ // generated api-versions.xml file.
+ //
+ // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
+ // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
+ // The exception is for system-server which needs to include module-lib and system-server. That
+ // is because while system-server extends module-lib the system-server extension directory only
+ // contains service-* modules which provide system-server APIs it does not list the modules which
+ // only provide a module-lib, so they have to be included separately.
+ extensionSurfacesPattern := sdkDirs[0]
+ if apiLevelsSdkType == "system-server" {
+ // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
+ // a pattern that will match either.
+ extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
+ }
+ extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
+
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() + `/extensions/[0-9]+/public/.*\.jar`)
+ 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 {
+ // 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"
}
cmd.Implicit(dep)
- }
- if dep.Base() == filename {
+ } else if depBase == filename {
+ // Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc..
cmd.Implicit(dep)
- }
- if filename != "android.jar" && dep.Base() == "android.jar" {
+ } 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
@@ -446,29 +639,25 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an
}
})
- // Add all relevant --android-jar-pattern patterns for Metalava.
- // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
- // an actual file present on disk (in the order the patterns were passed). For system APIs for
- // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
- // for older releases. Similarly, module-lib falls back to system API.
- var sdkDirs []string
- switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
- case "system-server":
- sdkDirs = []string{"system-server", "module-lib", "system", "public"}
- case "module-lib":
- sdkDirs = []string{"module-lib", "system", "public"}
- case "system":
- sdkDirs = []string{"system", "public"}
- case "public":
- sdkDirs = []string{"public"}
- default:
- ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
- return
- }
-
+ // 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..
for _, sdkDir := range sdkDirs {
for _, dir := range dirs {
- cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
+ addPattern := func(jarFilename string) {
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
+ }
+
+ if sdkDir == "module-lib" || sdkDir == "system-server" {
+ // The module-lib and system-server android.jars do not include the updatable modules (as
+ // doing so in the source would introduce dependency cycles and the prebuilts have to
+ // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
+ // that does include the updatable modules and this pattern will match that. This pattern
+ // is added in addition to the following pattern to decouple this change from the change
+ // to add the `android-plus-updatable.jar`.
+ addPattern(AndroidPlusUpdatableJar)
+ }
+
+ addPattern(filename)
}
}
@@ -483,12 +672,29 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an
}
}
+func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
+ if len(d.Javadoc.properties.Out) > 0 {
+ ctx.PropertyErrorf("out", "out property may not be combined with check_api")
+ }
+
+ apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
+ removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
+
+ cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
+ cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
+
+ baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
+ if baselineFile.Valid() {
+ cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
+ }
+}
+
func metalavaUseRbe(ctx android.ModuleContext) bool {
return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
}
-func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
- srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
+func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
+ srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -498,87 +704,137 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
if metalavaUseRbe(ctx) {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
+ remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
labels := map[string]string{"type": "tool", "name": "metalava"}
// TODO: metalava pool rejects these jobs
pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
rule.Rewrapper(&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Platform: map[string]string{remoteexec.PoolKey: pool},
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ Compare: compare,
+ NumLocalRuns: 1,
+ NumRemoteRuns: 1,
+ NoRemoteUpdateCache: !remoteUpdateCache,
})
}
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
- Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
- FlagWithArg("-source ", javaVersion.String()).
- FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
+ Flag(config.MetalavaAddOpens).
+ FlagWithArg("--java-source ", params.javaVersion.String()).
+ FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
FlagWithInput("@", srcJarList)
- if len(bootclasspath) > 0 {
- cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
- }
-
- if len(classpath) > 0 {
- cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":")
+ // Metalava does not differentiate between bootclasspath and classpath and has not done so for
+ // years, so it is unlikely to change any time soon.
+ combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
+ combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
+ if len(combinedPaths) > 0 {
+ cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
- cmd.Flag("--no-banner").
- Flag("--color").
- Flag("--quiet").
- Flag("--format=v2").
- FlagWithArg("--repeat-errors-max ", "10").
- FlagWithArg("--hide ", "UnresolvedImport").
- FlagWithArg("--hide ", "InvalidNullabilityOverride").
- // b/223382732
- FlagWithArg("--hide ", "ChangedDefault")
+ cmd.Flag(config.MetalavaFlags)
return cmd
}
-func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- deps := d.Javadoc.collectDeps(ctx)
+// 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
+// enabled via release configurations and are not specified in aconfig_declarations
+func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
- javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
+ if len(aconfigFlagsPaths) == 0 {
+ cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
+ return
+ }
- // Create rule for metalava
+ releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
+ revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
- srcJarDir := android.PathForModuleOut(ctx, "metalava", "srcjars")
+ var filterArgs string
+ switch stubsType {
+ // No flagged apis specific flags need to be passed to metalava when generating
+ // everything stubs
+ case Everything:
+ return
- rule := android.NewRuleBuilder(pctx, ctx)
+ case Runtime:
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
- rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
- android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
- SandboxInputs()
+ case Exportable:
+ // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
+ // the flagged apis that have read_write permissions are exposed on top of the enabled
+ // and read_only apis. This is to support local override of flag values at runtime.
+ if ctx.Config().ReleaseExportRuntimeApis() {
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
+ } else {
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
+ }
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: gatherReleasedFlaggedApisRule,
+ Inputs: aconfigFlagsPaths,
+ Output: releasedFlaggedApisFile,
+ Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
+ Args: map[string]string{
+ "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
+ "filter_args": filterArgs,
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateMetalavaRevertAnnotationsRule,
+ Input: releasedFlaggedApisFile,
+ Output: revertAnnotationsFile,
+ Description: fmt.Sprintf("%s revert annotations", stubsType),
+ })
+ cmd.FlagWithInput("@", revertAnnotationsFile)
+}
+
+func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
+ params stubsCommandParams) *android.RuleBuilderCommand {
if BoolDefault(d.properties.High_mem, false) {
// This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
rule.HighMem()
}
- generateStubs := BoolDefault(d.properties.Generate_stubs, true)
- var stubsDir android.OptionalPath
- if generateStubs {
- d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
- stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
- rule.Command().Text("rm -rf").Text(stubsDir.String())
- rule.Command().Text("mkdir -p").Text(stubsDir.String())
+ if params.stubConfig.generateStubs {
+ rule.Command().Text("rm -rf").Text(params.stubsDir.String())
+ rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
}
- srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
+ srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
- homeDir := android.PathForModuleOut(ctx, "metalava", "home")
- cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
- deps.bootClasspath, deps.classpath, homeDir)
+ homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
+ cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
cmd.Implicits(d.Javadoc.implicits)
- d.stubsFlags(ctx, cmd, stubsDir)
+ d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
+
+ if params.stubConfig.writeSdkValues {
+ d.sdkValuesFlags(ctx, cmd, params.metadataDir)
+ }
+
+ annotationParams := annotationFlagsParams{
+ migratingNullability: params.stubConfig.migratingNullability,
+ validatingNullability: params.stubConfig.validatingNullability,
+ nullabilityWarningsFile: params.nullabilityWarningsFile,
+ annotationsZip: params.annotationsZip,
+ }
- d.annotationsFlags(ctx, cmd)
+ d.annotationsFlags(ctx, cmd, annotationParams)
d.inclusionAnnotationsFlags(ctx, cmd)
- d.apiLevelsAnnotationsFlags(ctx, cmd)
+ d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
+
+ if params.stubConfig.doCheckReleased {
+ d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
+ }
d.expandArgs(ctx, cmd)
@@ -586,36 +842,118 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
}
- // Add options for the other optional tasks: API-lint and check-released.
- // We generate separate timestamp files for them.
+ return cmd
+}
- doApiLint := false
- doCheckReleased := false
+// Sandbox rule for generating the everything stubs and other artifacts
+func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
+ srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
+ android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
+ SandboxInputs()
- // Add API lint options.
+ var stubsDir android.OptionalPath
+ if params.generateStubs {
+ stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
+ d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+ }
- if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) {
- doApiLint = true
+ if params.writeSdkValues {
+ d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
+ d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
+ }
- newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
- if newSince.Valid() {
- cmd.FlagWithInput("--api-lint ", newSince.Path())
- } else {
- cmd.Flag("--api-lint")
+ if Bool(d.properties.Annotations_enabled) {
+ if params.validatingNullability {
+ d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
+ }
+ d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
+ }
+ if Bool(d.properties.Api_levels_annotations_enabled) {
+ d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
+ }
+
+ commonCmdParams := stubsCommandParams{
+ srcJarDir: srcJarDir,
+ stubsDir: stubsDir,
+ stubsSrcJar: d.Javadoc.stubsSrcJar,
+ metadataDir: d.everythingArtifacts.metadataDir,
+ apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
+ nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
+ annotationsZip: d.everythingArtifacts.annotationsZip,
+ stubConfig: params,
+ }
+
+ cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
+
+ d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
+
+ if params.generateStubs {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+ }
+
+ if params.writeSdkValues {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-d").
+ FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
+ FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
+ FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
+ }
+
+ // TODO: We don't really need two separate API files, but this is a reminiscence of how
+ // we used to run metalava separately for API lint and the "last_released" check. Unify them.
+ if params.doApiLint {
+ rule.Command().Text("touch").Output(d.apiLintTimestamp)
+ }
+ if params.doCheckReleased {
+ rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
+ }
+
+ // TODO(b/183630617): rewrapper doesn't support restat rules
+ if !metalavaUseRbe(ctx) {
+ rule.Restat()
+ }
+
+ zipSyncCleanupCmd(rule, srcJarDir)
+
+ rule.Build("metalava", "metalava merged")
+}
+
+// Sandbox rule for generating the everything artifacts that are not run by
+// default but only run based on the module configurations
+func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
+
+ // Add API lint options.
+ treatDocumentationIssuesAsErrors := false
+ if doApiLint {
+ var newSince android.Paths
+ if d.properties.Check_api.Api_lint.New_since != nil {
+ newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
}
- d.apiLintReport = android.PathForModuleOut(ctx, "metalava", "api_lint_report.txt")
+ cmd.Flag("--api-lint")
+ cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
+ d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
// TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
if d.Name() != "android.car-system-stubs-docs" &&
d.Name() != "android.car-stubs-docs" {
- cmd.Flag("--lints-as-errors")
+ treatDocumentationIssuesAsErrors = true
cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
}
baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
- updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "api_lint_baseline.txt")
- d.apiLintTimestamp = android.PathForModuleOut(ctx, "metalava", "api_lint.timestamp")
+ updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
+ d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
// Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
//
@@ -655,30 +993,18 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.FlagWithArg("--error-message:api-lint ", msg)
}
- // Add "check released" options. (Detect incompatible API changes from the last public release)
-
- if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
- doCheckReleased = true
-
- if len(d.Javadoc.properties.Out) > 0 {
- ctx.PropertyErrorf("out", "out property may not be combined with check_api")
- }
+ if !treatDocumentationIssuesAsErrors {
+ treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
+ }
- apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
- removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
+ // Add "check released" options. (Detect incompatible API changes from the last public release)
+ if doCheckReleased {
baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
- updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "last_released_baseline.txt")
-
- d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_last_released_api.timestamp")
-
- cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
- cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
-
+ d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
if baselineFile.Valid() {
- cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
+ updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
}
-
// Note this string includes quote ($' ... '), which decodes the "\n"s.
msg := `$'\n******************************\n` +
`You have tried to change the API from what has been previously released in\n` +
@@ -688,34 +1014,121 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.FlagWithArg("--error-message:compatibility:released ", msg)
}
- if generateStubs {
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
+ // Pass the current API file into metalava so it can use it as the basis for determining how to
+ // generate the output signature files (both api and removed).
+ currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
+ cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
+ }
+}
+
+// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
+// hidden as they are very noisy and provide little value.
+var HIDDEN_DOCUMENTATION_ISSUES = []string{
+ "Deprecated",
+ "IntDef",
+ "Nullable",
+}
+
+func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
+ // Treat documentation issues as warnings, but error when new.
+ cmd.Flag("--error-when-new-category").Flag("Documentation")
+
+ // Hide some documentation issues that generated a lot of noise for little benefit.
+ cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
+}
+
+// Sandbox rule for generating exportable stubs and other artifacts
+func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
+ optionalCmdParams := stubsCommandParams{
+ stubConfig: params,
+ }
+
+ if params.generateStubs {
+ d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+ optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
+ }
+
+ if params.writeSdkValues {
+ d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
+ d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
+ optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
+ optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
+ }
+
+ if Bool(d.properties.Annotations_enabled) {
+ if params.validatingNullability {
+ d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
+ optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
+ }
+ d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
+ optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
+ }
+ if Bool(d.properties.Api_levels_annotations_enabled) {
+ d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
+ optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
+ }
+
+ if params.checkApi || String(d.properties.Api_filename) != "" {
+ filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
+ d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
+ }
+
+ if params.checkApi || String(d.properties.Removed_api_filename) != "" {
+ filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
+ d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
+ }
+
+ d.optionalStubCmd(ctx, optionalCmdParams)
+}
+
+func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
+
+ params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
+ android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
+ SandboxInputs()
+
+ if params.stubConfig.generateStubs {
+ params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
+ }
+
+ cmd := d.commonMetalavaStubCmd(ctx, rule, params)
+
+ generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
+
+ if params.stubConfig.doApiLint {
+ // Pass the lint baseline file as an input to resolve the lint errors.
+ // The exportable stubs generation does not update the lint baseline file.
+ // Lint baseline file update is handled by the everything stubs
+ baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
+ if baselineFile.Valid() {
+ cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
+ }
+ }
+
+ // Treat documentation issues as warnings, but error when new.
+ treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
+
+ if params.stubConfig.generateStubs {
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-jar").
- FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+ FlagWithOutput("-o ", params.stubsSrcJar).
+ FlagWithArg("-C ", params.stubsDir.String()).
+ FlagWithArg("-D ", params.stubsDir.String())
}
- if Bool(d.properties.Write_sdk_values) {
- d.metadataZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-metadata.zip")
+ if params.stubConfig.writeSdkValues {
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-d").
- FlagWithOutput("-o ", d.metadataZip).
- FlagWithArg("-C ", d.metadataDir.String()).
- FlagWithArg("-D ", d.metadataDir.String())
- }
-
- // TODO: We don't really need two separate API files, but this is a reminiscence of how
- // we used to run metalava separately for API lint and the "last_released" check. Unify them.
- if doApiLint {
- rule.Command().Text("touch").Output(d.apiLintTimestamp)
- }
- if doCheckReleased {
- rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
+ FlagWithOutput("-o ", params.metadataZip).
+ FlagWithArg("-C ", params.metadataDir.String()).
+ FlagWithArg("-D ", params.metadataDir.String())
}
// TODO(b/183630617): rewrapper doesn't support restat rules
@@ -723,9 +1136,53 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Restat()
}
- zipSyncCleanupCmd(rule, srcJarDir)
+ zipSyncCleanupCmd(rule, params.srcJarDir)
- rule.Build("metalava", "metalava merged")
+ rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
+}
+
+func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ deps := d.Javadoc.collectDeps(ctx)
+
+ javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
+ generateStubs := BoolDefault(d.properties.Generate_stubs, true)
+
+ // Add options for the other optional tasks: API-lint and check-released.
+ // We generate separate timestamp files for them.
+ doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
+ doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
+
+ writeSdkValues := Bool(d.properties.Write_sdk_values)
+
+ annotationsEnabled := Bool(d.properties.Annotations_enabled)
+
+ migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
+ validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
+ String(d.properties.Validate_nullability_from_list) != "")
+
+ checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
+ apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
+
+ stubCmdParams := stubsCommandConfigParams{
+ javaVersion: javaVersion,
+ deps: deps,
+ checkApi: checkApi,
+ generateStubs: generateStubs,
+ doApiLint: doApiLint,
+ doCheckReleased: doCheckReleased,
+ writeSdkValues: writeSdkValues,
+ migratingNullability: migratingNullability,
+ validatingNullability: validatingNullability,
+ }
+ stubCmdParams.stubsType = Everything
+ // Create default (i.e. "everything" stubs) rule for metalava
+ d.everythingStubCmd(ctx, stubCmdParams)
+
+ // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
+ // aconfig_declarations property is defined or not. If the property is not defined, the module simply
+ // strips all flagged apis to generate the "exportable" stubs
+ stubCmdParams.stubsType = Exportable
+ d.exportableStubCmd(ctx, stubCmdParams)
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
@@ -741,7 +1198,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
}
- d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_current_api.timestamp")
+ d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
rule := android.NewRuleBuilder(pctx, ctx)
@@ -768,6 +1225,12 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
` m %s-update-current-api\n\n`+
` To submit the revised current.txt to the main Android repository,\n`+
` you will need approval.\n`+
+ `If your build failed due to stub validation, you can resolve the errors with\n`+
+ `either of the two choices above and try re-building the target.\n`+
+ `If the mismatch between the stubs and the current.txt is intended,\n`+
+ `you can try re-building the target by executing the following command:\n`+
+ `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
+ `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
`******************************\n`, ctx.ModuleName())
rule.Command().
@@ -779,7 +1242,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build("metalavaCurrentApiCheck", "check current API")
- d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "update_current_api.timestamp")
+ d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
// update API rule
rule = android.NewRuleBuilder(pctx, ctx)
@@ -807,14 +1270,14 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
if String(d.properties.Check_nullability_warnings) != "" {
- if d.nullabilityWarningsFile == nil {
+ 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, "metalava", "check_nullability_warnings.timestamp")
+ 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`+
@@ -824,13 +1287,13 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
` 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.nullabilityWarningsFile, checkNullabilityWarnings)
+ d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
Text("(").
- Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
+ Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Text("&&").
Text("touch").Output(d.checkNullabilityWarningsTimestamp).
Text(") || (").
@@ -840,34 +1303,46 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build("nullabilityWarningsCheck", "nullability warnings check")
}
-}
-var _ android.ApiProvider = (*Droidstubs)(nil)
-
-type bazelJavaApiContributionAttributes struct {
- Api bazel.LabelAttribute
- Api_surface *string
+ d.setOutputFiles(ctx)
}
-func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_api_contribution",
- Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl",
+// This method sets the outputFiles property, which is used to set the
+// OutputFilesProvider later.
+// Droidstubs' tag supports specifying with the stubs type.
+// While supporting the pre-existing tags, it also supports tags with
+// the stubs type prefix. Some examples are shown below:
+// {.annotations.zip} - pre-existing behavior. Returns the path to the
+// annotation zip.
+// {.exportable} - Returns the path to the exportable stubs src jar.
+// {.exportable.annotations.zip} - Returns the path to the exportable
+// annotations zip file.
+// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
+// xml file. For unsupported combinations, the default everything output file
+// is returned.
+func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) {
+ tagToOutputFileFunc := map[string]func(StubsType) (android.Path, error){
+ "": d.StubsSrcJar,
+ ".docs.zip": d.DocZip,
+ ".api.txt": d.ApiFilePath,
+ android.DefaultDistTag: d.ApiFilePath,
+ ".removed-api.txt": d.RemovedApiFilePath,
+ ".annotations.zip": d.AnnotationsZip,
+ ".api_versions.xml": d.ApiVersionsXmlFilePath,
}
- apiFile := d.properties.Check_api.Current.Api_file
- // Do not generate a target if check_api is not set
- if apiFile == nil {
- return
+ stubsTypeToPrefix := map[StubsType]string{
+ Everything: "",
+ Exportable: ".exportable",
}
- attrs := &bazelJavaApiContributionAttributes{
- Api: *bazel.MakeLabelAttribute(
- android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label,
- ),
- Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())),
+ for _, tag := range android.SortedKeys(tagToOutputFileFunc) {
+ for _, stubType := range android.SortedKeys(stubsTypeToPrefix) {
+ tagWithPrefix := stubsTypeToPrefix[stubType] + tag
+ outputFile, err := tagToOutputFileFunc[tag](stubType)
+ if err == nil {
+ ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix)
+ }
+ }
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: android.ApiContributionTargetName(ctx.ModuleName()),
- }, attrs)
}
func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
@@ -895,7 +1370,7 @@ func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
// use a strict naming convention
var (
droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
- //public is commented out since the core libraries use public in their java_sdk_library names
+ // public is commented out since the core libraries use public in their java_sdk_library names
"intracore": android.SdkIntraCore,
"intra.core": android.SdkIntraCore,
"system_server": android.SdkSystemServer,
@@ -909,28 +1384,6 @@ var (
}
)
-// A helper function that returns the api surface of the corresponding java_api_contribution Bazel target
-// The api_surface is populated using the naming convention of the droidstubs module.
-func bazelApiSurfaceName(name string) string {
- // Sort the keys so that longer strings appear first
- // Otherwise substrings like system will match both system and system_server
- sortedKeys := make([]string, 0)
- for key := range droidstubsModuleNamingToSdkKind {
- sortedKeys = append(sortedKeys, key)
- }
- sort.Slice(sortedKeys, func(i, j int) bool {
- return len(sortedKeys[i]) > len(sortedKeys[j])
- })
- for _, sortedKey := range sortedKeys {
- if strings.Contains(name, sortedKey) {
- sdkKind := droidstubsModuleNamingToSdkKind[sortedKey]
- return sdkKind.String() + "api"
- }
- }
- // Default is publicapi
- return android.SdkPublic.String() + "api"
-}
-
func StubsDefaultsFactory() android.Module {
module := &DocDefaults{}
@@ -948,11 +1401,31 @@ var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
type PrebuiltStubsSourcesProperties struct {
Srcs []string `android:"path"`
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
+}
+
+func (j *PrebuiltStubsSources) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
+func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
+ return j.properties.Created_by_java_sdk_library_name
}
type PrebuiltStubsSources struct {
android.ModuleBase
android.DefaultableModuleBase
+ embeddableInModuleAndImport
+
prebuilt android.Prebuilt
properties PrebuiltStubsSourcesProperties
@@ -960,17 +1433,8 @@ type PrebuiltStubsSources struct {
stubsSrcJar android.Path
}
-func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return android.Paths{p.stubsSrcJar}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
-func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
- return d.stubsSrcJar
+func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
+ return d.stubsSrcJar, nil
}
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1007,6 +1471,11 @@ func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleCon
rule.Build("zip src", "Create srcjar from prebuilt source")
p.stubsSrcJar = outPath
}
+
+ ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
+ // prebuilt droidstubs does not output "exportable" stubs.
+ // Output the "everything" stubs srcjar file if the tag is ".exportable".
+ ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
}
func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
@@ -1031,6 +1500,7 @@ func PrebuiltStubsSourcesFactory() android.Module {
module := &PrebuiltStubsSources{}
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
android.InitPrebuiltModule(module, &module.properties.Srcs)
InitDroiddocModule(module, android.HostAndDeviceSupported)
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 7a04d7326..6a14f3645 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -22,6 +22,8 @@ import (
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
func TestDroidstubs(t *testing.T) {
@@ -82,7 +84,7 @@ func TestDroidstubs(t *testing.T) {
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ 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 != "" {
@@ -131,7 +133,7 @@ func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string {
m := ctx.ModuleForTests("foo-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
return r.FindAllString(cmd, -1)
}
@@ -210,8 +212,8 @@ func TestDroidstubsSandbox(t *testing.T) {
t.Errorf("Expected inputs %q, got %q", w, g)
}
- manifest := android.RuleBuilderSboxProtoForTests(t, m.Output("metalava.sbox.textproto"))
- if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
+ manifest := android.RuleBuilderSboxProtoForTests(t, ctx, m.Output("metalava.sbox.textproto"))
+ if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/soong/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
t.Errorf("Expected command to contain %q, got %q", w, g)
}
}
@@ -300,53 +302,11 @@ func TestDroidstubsWithSdkExtensions(t *testing.T) {
})
m := ctx.ModuleForTests("baz-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- cmdline := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ 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, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
}
-func TestApiSurfaceFromDroidStubsName(t *testing.T) {
- testCases := []struct {
- desc string
- name string
- expectedApiSurface string
- }{
- {
- desc: "Default is publicapi",
- name: "mydroidstubs",
- expectedApiSurface: "publicapi",
- },
- {
- desc: "name contains system substring",
- name: "mydroidstubs.system.suffix",
- expectedApiSurface: "systemapi",
- },
- {
- desc: "name contains system_server substring",
- name: "mydroidstubs.system_server.suffix",
- expectedApiSurface: "system-serverapi",
- },
- {
- desc: "name contains module_lib substring",
- name: "mydroidstubs.module_lib.suffix",
- expectedApiSurface: "module-libapi",
- },
- {
- desc: "name contains test substring",
- name: "mydroidstubs.test.suffix",
- expectedApiSurface: "testapi",
- },
- {
- desc: "name contains intra.core substring",
- name: "mydroidstubs.intra.core.suffix",
- expectedApiSurface: "intracoreapi",
- },
- }
- for _, tc := range testCases {
- android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name))
- }
-}
-
func TestDroidStubsApiContributionGeneration(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
droidstubs {
@@ -377,6 +337,7 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
name: "bar",
api_surface: "public",
api_contributions: ["foo.api.contribution"],
+ stubs_type: "everything",
}
`
ctx, _ := testJavaWithFS(t, `
@@ -390,7 +351,7 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
removed_api_file: "A/removed.txt",
}
},
- visibility: ["//a"],
+ visibility: ["//a", "//b"],
}
`,
map[string][]byte{
@@ -403,3 +364,101 @@ func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
ctx.ModuleForTests("bar", "android_common")
}
+
+func TestAconfigDeclarations(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ // Check that droidstubs depend on aconfig_declarations
+ android.AssertBoolEquals(t, "foo expected to depend on bar",
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
+
+ m := result.ModuleForTests("foo", "android_common")
+ android.AssertStringDoesContain(t, "foo generates revert annotations file",
+ strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+
+ // revert-annotations.txt passed to exportable stubs generation metalava command
+ manifest := m.Output("metalava_exportable.sbox.textproto")
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
+ android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
+
+ android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
+ strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
+}
+
+func TestReleaseExportRuntimeApis(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ variables.ExportRuntimeApis = proptools.BoolPtr(true)
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ m := result.ModuleForTests("foo", "android_common")
+
+ rule := m.Output("released-flagged-apis-exportable.txt")
+ exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
+ android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"])
+}
diff --git a/java/fuzz.go b/java/fuzz.go
index 2b9e22b8e..d37c55804 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -30,15 +30,19 @@ import (
const (
hostString = "host"
targetString = "target"
+ deviceString = "device"
)
+// Any shared libs for these deps will also be packaged
+var artDeps = []string{"libdl_android"}
+
func init() {
RegisterJavaFuzzBuildComponents(android.InitRegistrationContext)
}
func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_fuzz", JavaFuzzFactory)
- ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
+ ctx.RegisterParallelSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
}
type JavaFuzzTest struct {
@@ -60,6 +64,8 @@ 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.sourceProperties.Test_only = proptools.BoolPtr(true)
+ module.Module.sourceProperties.Top_level_test_target = true
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
disableLinuxBionic := struct {
@@ -78,7 +84,18 @@ func JavaFuzzFactory() android.Module {
}
func (j *JavaFuzzTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if j.Os().Class.String() == deviceString {
+ j.testProperties.Jni_libs = append(j.testProperties.Jni_libs, artDeps...)
+ }
+
if len(j.testProperties.Jni_libs) > 0 {
+ if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
+ config := &fuzz.FuzzConfig{}
+ j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
+ }
+ // this will be used by the ingestion pipeline to determine the version
+ // of jazzer to add to the fuzzer package
+ j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
for _, target := range ctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
@@ -106,7 +123,7 @@ func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
_, sharedDeps := cc.CollectAllSharedDependencies(ctx)
for _, dep := range sharedDeps {
- sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
if sharedLibInfo.SharedLibrary != nil {
arch := "lib"
if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
@@ -150,7 +167,9 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
}
hostOrTargetString := "target"
- if javaFuzzModule.Host() {
+ if javaFuzzModule.Target().HostCross {
+ hostOrTargetString = "host_cross"
+ } else if javaFuzzModule.Host() {
hostOrTargetString = "host"
}
@@ -160,7 +179,7 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
javaFuzzModule.ApexModuleBase,
}
- if ok := fuzz.IsValid(fuzzModuleValidator); !ok {
+ if ok := fuzz.IsValid(ctx, fuzzModuleValidator); !ok {
return
}
@@ -175,11 +194,15 @@ func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
// Add .jar
- files = append(files, fuzz.FileToZip{javaFuzzModule.implementationJarFile, ""})
+ if !javaFuzzModule.Host() {
+ files = append(files, fuzz.FileToZip{SourceFilePath: javaFuzzModule.implementationJarFile, DestinationPathPrefix: "classes"})
+ }
+
+ files = append(files, fuzz.FileToZip{SourceFilePath: javaFuzzModule.outputFile})
// Add jni .so files
for _, fPath := range javaFuzzModule.jniFilePaths {
- files = append(files, fuzz.FileToZip{fPath, ""})
+ files = append(files, fuzz.FileToZip{SourceFilePath: fPath})
}
archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index dd1e96b3e..f29c91327 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -71,8 +71,8 @@ func TestJavaFuzz(t *testing.T) {
}
baz := result.ModuleForTests("baz", osCommonTarget).Rule("javac").Output.String()
- barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac", "bar.jar")
- bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac", "baz.jar")
+ barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac-header", "bar.jar")
+ bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac-header", "baz.jar")
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barOut)
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazOut)
diff --git a/java/gen.go b/java/gen.go
index 638da255a..1b4f4c7dc 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -27,7 +27,6 @@ import (
func init() {
pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
- pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py")
pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
}
@@ -37,12 +36,6 @@ var (
Command: "$logtagsCmd -o $out $in",
CommandDeps: []string{"$logtagsCmd", "$logtagsLib"},
})
-
- mergeLogtags = pctx.AndroidStaticRule("mergeLogtags",
- blueprint.RuleParams{
- Command: "$mergeLogtagsCmd -o $out $in",
- CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"},
- })
)
func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlGlobalFlags string, aidlIndividualFlags map[string]string, deps android.Paths) android.Paths {
@@ -129,19 +122,7 @@ func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, exclud
baseDir = filepath.Clean(baseDir)
baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings)
- // For go/bp2build mixed builds, a file may be listed under a
- // directory in the Bazel output tree that is symlinked to a
- // directory under the android source tree. We should only
- // include one copy of this directory so that the AIDL tool
- // doesn't find multiple definitions of the same AIDL class.
- // This code comes into effect when filegroups are used in mixed builds.
- bazelPathPrefix := android.PathForBazelOut(ctx, "").String()
- bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir)
- bazelBaseDirSeen := err == nil &&
- android.InList(bazelBaseDir, baseDirs) ||
- android.InList(bazelBaseDir, excludeDirsStrings)
-
- if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen {
+ if baseDir != "" && !baseDirSeen {
baseDirs = append(baseDirs, baseDir)
}
}
@@ -190,37 +171,9 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
outSrcFiles = append(outSrcFiles, srcJarFiles...)
}
- return outSrcFiles
-}
-
-func LogtagsSingleton() android.Singleton {
- return &logtagsSingleton{}
-}
-
-type logtagsProducer interface {
- logtags() android.Paths
-}
-
-func (j *Module) logtags() android.Paths {
- return j.logtagsSrcs
-}
-
-var _ logtagsProducer = (*Module)(nil)
-
-type logtagsSingleton struct{}
-
-func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var allLogtags android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if logtags, ok := module.(logtagsProducer); ok {
- allLogtags = append(allLogtags, logtags.logtags()...)
- }
+ android.SetProvider(ctx, android.LogtagsProviderKey, &android.LogtagsInfo{
+ Logtags: j.logtagsSrcs,
})
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeLogtags,
- Description: "merge logtags",
- Output: android.PathForIntermediates(ctx, "all-event-log-tags.txt"),
- Inputs: allLogtags,
- })
+ return outSrcFiles
}
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
new file mode 100644
index 000000000..d5e6d8fec
--- /dev/null
+++ b/java/generated_java_library.go
@@ -0,0 +1,116 @@
+// Copyright 2023 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 (
+ "android/soong/android"
+)
+
+type GeneratedJavaLibraryModule struct {
+ Library
+ callbacks GeneratedJavaLibraryCallbacks
+ moduleName string
+
+ // true if we've already called DepsMutator. Can't call AddLibrary or AddSharedLibrary
+ // after DepsMutator.
+ depsMutatorDone bool
+}
+
+type GeneratedJavaLibraryCallbacks interface {
+ // Called from inside DepsMutator, gives a chance to AddDependencies
+ DepsMutator(module *GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext)
+
+ // Called from inside GenerateAndroidBuildActions. Add the build rules to
+ // make the srcjar, and return the path to it.
+ GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) (android.Path, android.Path)
+}
+
+// GeneratedJavaLibraryModuleFactory provides a utility for modules that are generated
+// source code, including ones outside the java package to build jar files
+// from that generated source.
+//
+// To use GeneratedJavaLibraryModule, call GeneratedJavaLibraryModuleFactory with
+// a callback interface and a properties object to add to the module.
+//
+// These modules will have some properties blocked, and it will be an error if
+// modules attempt to set them. See the list of property names in GeneratedAndroidBuildActions
+// for the list of those properties.
+func GeneratedJavaLibraryModuleFactory(moduleName string, callbacks GeneratedJavaLibraryCallbacks, properties interface{}) android.Module {
+ module := &GeneratedJavaLibraryModule{
+ callbacks: callbacks,
+ moduleName: moduleName,
+ }
+ module.addHostAndDeviceProperties()
+ module.initModuleAndImport(module)
+ android.InitApexModule(module)
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ if properties != nil {
+ module.AddProperties(properties)
+ }
+ return module
+}
+
+// Add a java shared library as a dependency, as if they had said `libs: [ "name" ]`
+func (module *GeneratedJavaLibraryModule) AddSharedLibrary(name string) {
+ if module.depsMutatorDone {
+ panic("GeneratedJavaLibraryModule.AddLibrary called after DepsMutator")
+ }
+ module.Library.properties.Libs = append(module.Library.properties.Libs, name)
+}
+
+// Add a java shared library as a dependency, as if they had said `libs: [ "name" ]`
+func (module *GeneratedJavaLibraryModule) AddStaticLibrary(name string) {
+ if module.depsMutatorDone {
+ panic("GeneratedJavaLibraryModule.AddStaticLibrary called after DepsMutator")
+ }
+ module.Library.properties.Static_libs = append(module.Library.properties.Static_libs, name)
+}
+
+func (module *GeneratedJavaLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ module.callbacks.DepsMutator(module, ctx)
+ module.depsMutatorDone = true
+ module.Library.DepsMutator(ctx)
+}
+
+func checkPropertyEmpty(ctx android.ModuleContext, module *GeneratedJavaLibraryModule, name string, value []string) {
+ if len(value) != 0 {
+ ctx.PropertyErrorf(name, "%s not allowed on %s", name, module.moduleName)
+ }
+}
+
+func (module *GeneratedJavaLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // These modules are all-generated, so disallow these properties to keep it simple.
+ // No additional sources
+ checkPropertyEmpty(ctx, module, "srcs", module.Library.properties.Srcs)
+ checkPropertyEmpty(ctx, module, "common_srcs", module.Library.properties.Common_srcs)
+ checkPropertyEmpty(ctx, module, "exclude_srcs", module.Library.properties.Exclude_srcs)
+ checkPropertyEmpty(ctx, module, "java_resource_dirs", module.Library.properties.Java_resource_dirs)
+ checkPropertyEmpty(ctx, module, "exclude_java_resource_dirs", module.Library.properties.Exclude_java_resource_dirs)
+ // Restrict these for no good reason other than to limit the surface area. If there's a
+ // good use case put them back.
+ checkPropertyEmpty(ctx, module, "plugins", module.Library.properties.Plugins)
+ checkPropertyEmpty(ctx, module, "exported_plugins", module.Library.properties.Exported_plugins)
+
+ srcJarPath, cacheOutputPath := module.callbacks.GenerateSourceJarBuildActions(module, ctx)
+
+ module.Library.properties.Generated_srcjars = append(module.Library.properties.Generated_srcjars, srcJarPath)
+ module.Library.properties.Aconfig_Cache_files = append(module.Library.properties.Aconfig_Cache_files, cacheOutputPath)
+ module.Library.GenerateAndroidBuildActions(ctx)
+}
+
+// Add a rule to the jarjar renaming rules. See RepackageProviderData.
+func (module *GeneratedJavaLibraryModule) AddJarJarRenameRule(original string, renamed string) {
+ module.addJarJarRenameRule(original, renamed)
+}
diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go
new file mode 100644
index 000000000..a5c4be111
--- /dev/null
+++ b/java/generated_java_library_test.go
@@ -0,0 +1,65 @@
+// 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 (
+ "testing"
+
+ "android/soong/android"
+)
+
+func JavaGenLibTestFactory() android.Module {
+ callbacks := &JavaGenLibTestCallbacks{}
+ return GeneratedJavaLibraryModuleFactory("test_java_gen_lib", callbacks, &callbacks.properties)
+}
+
+type JavaGenLibTestProperties struct {
+ Foo string
+}
+
+type JavaGenLibTestCallbacks struct {
+ properties JavaGenLibTestProperties
+}
+
+func (callbacks *JavaGenLibTestCallbacks) DepsMutator(module *GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
+}
+
+func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) (android.Path, android.Path) {
+ return android.PathForOutput(ctx, "blah.srcjar"), android.PathForOutput(ctx, "blah.pb")
+}
+
+func testGenLib(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
+ return android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("test_java_gen_lib", JavaGenLibTestFactory)
+ }),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
+
+func TestGenLib(t *testing.T) {
+ bp := `
+ test_java_gen_lib {
+ name: "javagenlibtest",
+ foo: "bar", // Note: This won't parse if the property didn't get added
+ }
+ `
+ result := testGenLib(t, android.FixtureExpectsNoErrors, bp)
+
+ javagenlibtest := result.ModuleForTests("javagenlibtest", "android_common").Module().(*GeneratedJavaLibraryModule)
+ android.AssertPathsEndWith(t, "Generated_srcjars", []string{"/blah.srcjar"}, javagenlibtest.Library.properties.Generated_srcjars)
+}
diff --git a/java/genrule.go b/java/genrule.go
index 208e1f43b..b84225fa5 100644
--- a/java/genrule.go
+++ b/java/genrule.go
@@ -65,7 +65,6 @@ func GenRuleFactory() android.Module {
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -79,7 +78,6 @@ func GenRuleFactoryHost() android.Module {
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index d25096b15..5441a3b6e 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -44,7 +44,8 @@ type hiddenAPI struct {
//
// 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
+ bootDexJarPath OptionalDexJarPath
+ bootDexJarPathErr error
// The paths to the classes jars that contain classes and class members annotated with
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
@@ -56,7 +57,10 @@ type hiddenAPI struct {
uncompressDexState *bool
}
-func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
+func (h *hiddenAPI) bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if h.bootDexJarPathErr != nil {
+ ctx.ModuleErrorf(h.bootDexJarPathErr.Error())
+ }
return h.bootDexJarPath
}
@@ -77,7 +81,7 @@ type hiddenAPIModule interface {
}
type hiddenAPIIntf interface {
- bootDexJar() OptionalDexJarPath
+ bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath
classesJars() android.Paths
uncompressDex() *bool
}
@@ -94,7 +98,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ
// processing.
classesJars := android.Paths{classesJar}
ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
- javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ javaInfo, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
classesJars = append(classesJars, javaInfo.ImplementationJars...)
})
h.classesJarPaths = classesJars
@@ -106,7 +110,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ
h.uncompressDexState = uncompressedDexState
// If hiddenapi processing is disabled treat this as inactive.
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
@@ -126,6 +130,11 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ
h.active = isModuleInBootClassPath(ctx, module)
}
+// Store any error encountered during the initialization of hiddenapi structure (e.g. unflagged co-existing prebuilt apexes)
+func (h *hiddenAPI) initHiddenAPIError(err error) {
+ h.bootDexJarPathErr = err
+}
+
func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
// Get the configured platform and apex boot jars.
nonApexBootJars := ctx.Config().NonApexBootJars()
@@ -305,7 +314,7 @@ func hiddenAPIEncodeDex(ctx android.ModuleContext, dexInput, flagsCSV android.Pa
})
if uncompressDex {
- TransformZipAlign(ctx, output, encodeRuleOutput)
+ TransformZipAlign(ctx, output, encodeRuleOutput, nil)
}
return output
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index c6176e67c..4144de82b 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -19,6 +19,7 @@ import (
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"github.com/google/blueprint"
)
@@ -38,10 +39,14 @@ type HiddenAPIScope struct {
// The option needed to passed to "hiddenapi list".
hiddenAPIListOption string
- // The name sof the source stub library modules that contain the API provided by the platform,
+ // The names of the source stub library modules that contain the API provided by the platform,
// i.e. by modules that are not in an APEX.
nonUpdatableSourceModule string
+ // The names of from-text stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatableFromTextModule string
+
// The names of the prebuilt stub library modules that contain the API provided by the platform,
// i.e. by modules that are not in an APEX.
nonUpdatablePrebuiltModule string
@@ -86,6 +91,9 @@ func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext,
if ctx.Config().AlwaysUsePrebuiltSdks() {
return l.nonUpdatablePrebuiltModule
} else {
+ if l.nonUpdatableFromTextModule != "" && ctx.Config().BuildFromTextStub() {
+ return l.nonUpdatableFromTextModule
+ }
return l.nonUpdatableSourceModule
}
} else {
@@ -117,8 +125,9 @@ var (
hiddenAPIListOption: "--test-stub-classpath",
})
ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
- name: "module-lib",
- sdkKind: android.SdkModule,
+ name: "module-lib",
+ sdkKind: android.SdkModule,
+ nonUpdatableFromTextModule: "android-non-updatable.stubs.test_module_lib",
})
CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
name: "core-platform",
@@ -236,12 +245,22 @@ func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*Hidden
testStubModules = append(testStubModules, "sdk_test_current_android")
} else {
// Use stub modules built from source
- publicStubModules = append(publicStubModules, android.SdkPublic.JavaLibraryName(config))
- systemStubModules = append(systemStubModules, android.SdkSystem.JavaLibraryName(config))
- testStubModules = append(testStubModules, android.SdkTest.JavaLibraryName(config))
+ if config.ReleaseHiddenApiExportableStubs() {
+ publicStubModules = append(publicStubModules, android.SdkPublic.DefaultExportableJavaLibraryName())
+ systemStubModules = append(systemStubModules, android.SdkSystem.DefaultExportableJavaLibraryName())
+ testStubModules = append(testStubModules, android.SdkTest.DefaultExportableJavaLibraryName())
+ } else {
+ publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
+ systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
+ testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
+ }
}
// We do not have prebuilts of the core platform api yet
- corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+ if config.ReleaseHiddenApiExportableStubs() {
+ corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs.exportable")
+ } else {
+ corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+ }
// Allow products to define their own stubs for custom product jars that apps can use.
publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
@@ -280,9 +299,14 @@ func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScop
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
var dexJar OptionalDexJarPath
if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
- dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ dexJar = sdkLibrary.SdkApiExportableStubDexJar(ctx, kind)
+ } else {
+ dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+ }
+
} else if j, ok := module.(UsesLibraryDependency); ok {
- dexJar = j.DexJarBuildPath()
+ dexJar = j.DexJarBuildPath(ctx)
} else {
ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
return nil
@@ -350,7 +374,7 @@ func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name,
// If there are stub flag files that have been generated by fragments on which this depends then
// use them to validate the stub flag file generated by the rules created by this method.
- if len(stubFlagSubsets) > 0 {
+ if !ctx.Config().DisableVerifyOverlaps() && len(stubFlagSubsets) > 0 {
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
@@ -411,122 +435,118 @@ type HiddenAPIFlagFileProperties struct {
}
}
-type hiddenAPIFlagFileCategory struct {
- // PropertyName is the name of the property for this category.
- PropertyName string
+type hiddenAPIFlagFileCategory int
- // propertyValueReader retrieves the value of the property for this category from the set of
- // properties.
- propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
+const (
+ // The flag file category for removed members of the API.
+ //
+ // This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
+ // list of removed API members that are generated automatically from the removed.txt files provided
+ // by API stubs.
+ hiddenAPIFlagFileCategoryRemoved hiddenAPIFlagFileCategory = iota
+ hiddenAPIFlagFileCategoryUnsupported
+ hiddenAPIFlagFileCategoryMaxTargetRLowPriority
+ hiddenAPIFlagFileCategoryMaxTargetQ
+ hiddenAPIFlagFileCategoryMaxTargetP
+ hiddenAPIFlagFileCategoryMaxTargetOLowPriority
+ hiddenAPIFlagFileCategoryBlocked
+ hiddenAPIFlagFileCategoryUnsupportedPackages
+)
- // commandMutator adds the appropriate command line options for this category to the supplied
- // command
- commandMutator func(command *android.RuleBuilderCommand, path android.Path)
+func (c hiddenAPIFlagFileCategory) PropertyName() string {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
+ return "removed"
+ case hiddenAPIFlagFileCategoryUnsupported:
+ return "unsupported"
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ return "max_target_r_low_priority"
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ return "max_target_q"
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ return "max_target_p"
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ return "max_target_o_low_priority"
+ case hiddenAPIFlagFileCategoryBlocked:
+ return "blocked"
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ return "unsupported_packages"
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
+ }
}
-// The flag file category for removed members of the API.
-//
-// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
-// list of removed API members that are generated automatically from the removed.txt files provided
-// by API stubs.
-var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
- // See HiddenAPIFlagFileProperties.Removed
- PropertyName: "removed",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
+// propertyValueReader retrieves the value of the property for this category from the set of properties.
+func (c hiddenAPIFlagFileCategory) propertyValueReader(properties *HiddenAPIFlagFileProperties) []string {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
return properties.Hidden_api.Removed
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
- },
+ case hiddenAPIFlagFileCategoryUnsupported:
+ return properties.Hidden_api.Unsupported
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ return properties.Hidden_api.Max_target_r_low_priority
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ return properties.Hidden_api.Max_target_q
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ return properties.Hidden_api.Max_target_p
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ return properties.Hidden_api.Max_target_o_low_priority
+ case hiddenAPIFlagFileCategoryBlocked:
+ return properties.Hidden_api.Blocked
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ return properties.Hidden_api.Unsupported_packages
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
+ }
}
-type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory
-
-func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory {
- for _, category := range c {
- if category.PropertyName == name {
- return category
- }
+// commandMutator adds the appropriate command line options for this category to the supplied command
+func (c hiddenAPIFlagFileCategory) commandMutator(command *android.RuleBuilderCommand, path android.Path) {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
+ command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
+ case hiddenAPIFlagFileCategoryUnsupported:
+ command.FlagWithInput("--unsupported ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ command.FlagWithInput("--max-target-q ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ command.FlagWithInput("--max-target-p ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
+ case hiddenAPIFlagFileCategoryBlocked:
+ command.FlagWithInput("--blocked ", path)
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ command.FlagWithInput("--unsupported ", path).Flag("--packages ")
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
}
- panic(fmt.Errorf("no category exists with property name %q in %v", name, c))
}
+type hiddenAPIFlagFileCategories []hiddenAPIFlagFileCategory
+
var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
// See HiddenAPIFlagFileProperties.Unsupported
- {
- PropertyName: "unsupported",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Unsupported
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path)
- },
- },
- hiddenAPIRemovedFlagFileCategory,
+ hiddenAPIFlagFileCategoryUnsupported,
+ // See HiddenAPIFlagFileProperties.Removed
+ hiddenAPIFlagFileCategoryRemoved,
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
- {
- PropertyName: "max_target_r_low_priority",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_r_low_priority
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetRLowPriority,
// See HiddenAPIFlagFileProperties.Max_target_q
- {
- PropertyName: "max_target_q",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_q
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-q ", path)
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetQ,
// See HiddenAPIFlagFileProperties.Max_target_p
- {
- PropertyName: "max_target_p",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_p
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-p ", path)
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetP,
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
- {
- PropertyName: "max_target_o_low_priority",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_o_low_priority
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetOLowPriority,
// See HiddenAPIFlagFileProperties.Blocked
- {
- PropertyName: "blocked",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Blocked
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--blocked ", path)
- },
- },
+ hiddenAPIFlagFileCategoryBlocked,
// See HiddenAPIFlagFileProperties.Unsupported_packages
- {
- PropertyName: "unsupported_packages",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Unsupported_packages
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path).Flag("--packages ")
- },
- },
+ hiddenAPIFlagFileCategoryUnsupportedPackages,
}
// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
-type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
+type FlagFilesByCategory map[hiddenAPIFlagFileCategory]android.Paths
// append the supplied flags files to the corresponding category in this map.
func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
@@ -571,8 +591,7 @@ func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragmen
// Merge all the information from the fragments. The fragments form a DAG so it is possible that
// this will introduce duplicates so they will be resolved after processing all the fragments.
for _, fragment := range fragments {
- if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
- info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ if info, ok := android.OtherModuleProvider(ctx, fragment, HiddenAPIInfoProvider); ok {
i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
}
}
@@ -592,7 +611,7 @@ func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset {
return SignatureCsvSubset{i.FilteredFlagsPath, i.SignaturePatternsPath}
}
-var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
+var HiddenAPIInfoProvider = blueprint.NewProvider[HiddenAPIInfo]()
// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
// by the sdk snapshot.
@@ -609,7 +628,7 @@ type HiddenAPIInfoForSdk struct {
}
// Provides hidden API info for the sdk snapshot.
-var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
+var HiddenAPIInfoForSdkProvider = blueprint.NewProvider[HiddenAPIInfoForSdk]()
// ModuleStubDexJars contains the stub dex jars provided by a single module.
//
@@ -647,7 +666,7 @@ func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module and
// public version is provided by the art.module.public.api module. In those cases it is necessary
// to treat all those modules as they were the same name, otherwise it will result in multiple
// definitions of a single class being passed to hidden API processing which will cause an error.
- if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
+ if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule || name == scope.nonUpdatableFromTextModule {
// Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
// java_sdk_library.
// TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
@@ -741,7 +760,7 @@ type HiddenAPIPropertyInfo struct {
SplitPackages []string
}
-var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{})
+var hiddenAPIPropertyInfoProvider = blueprint.NewProvider[HiddenAPIPropertyInfo]()
// newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
@@ -769,8 +788,7 @@ func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPa
func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
for _, module := range contents {
- if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) {
- info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
+ if info, ok := android.OtherModuleProvider(ctx, module, hiddenAPIPropertyInfoProvider); ok {
i.FlagFilesByCategory.append(info.FlagFilesByCategory)
i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
@@ -941,6 +959,7 @@ type HiddenAPIOutput struct {
HiddenAPIFlagOutput
// The map from base module name to the path to the encoded boot dex file.
+ // This field is not available in prebuilt apexes
EncodedBootDexFilesByModule bootDexJarByModule
}
@@ -991,14 +1010,14 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
// If available then pass the automatically generated file containing dex signatures of removed
// API members to the rule so they can be marked as removed.
if generatedRemovedDexSignatures.Valid() {
- hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
+ hiddenAPIFlagFileCategoryRemoved.commandMutator(command, generatedRemovedDexSignatures.Path())
}
commitChangeForRestat(rule, tempPath, outputPath)
// If there are flag files that have been generated by fragments on which this depends then use
// them to validate the flag file generated by the rules created by this method.
- if len(flagSubsets) > 0 {
+ if !ctx.Config().DisableVerifyOverlaps() && len(flagSubsets) > 0 {
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
@@ -1236,17 +1255,35 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix s
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("metalava").
- Flag("--no-banner").
+ Text("signature-to-dex").
Inputs(removedTxtFiles).
- FlagWithOutput("--dex-api ", output)
+ FlagWithOutput("--out ", output)
rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
return android.OptionalPathForPath(output)
}
// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes contain a ApexExportsInfo
+// 2. Legacy: An edge to java_sdk_library(_import) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
bootDexJars := bootDexJarByModule{}
+
+ apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
+ // For ART and mainline module jars, query apexNameToApexExportsInfoMap to get the dex file
+ apexJars := dexpreopt.GetGlobalConfig(ctx).ArtApexJars.AppendList(&dexpreopt.GetGlobalConfig(ctx).ApexBootJars)
+ for i := 0; i < apexJars.Len(); i++ {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, apexJars.Apex(i), apexJars.Jar(i)); found {
+ bootDexJars[apexJars.Jar(i)] = dex
+ }
+ }
+
+ // TODO - b/308174306: Drop the legacy mechanism
for _, module := range contents {
+ if _, exists := bootDexJars[android.RemoveOptionalPrebuiltPrefix(module.Name())]; exists {
+ continue
+ }
hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
if hiddenAPIModule == nil {
continue
@@ -1317,7 +1354,7 @@ func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android
// invalid, then create a fake path and either report an error immediately or defer reporting of the
// error until the path is actually used.
func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
- bootDexJar := module.bootDexJar()
+ bootDexJar := module.bootDexJar(ctx)
if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
@@ -1392,12 +1429,12 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
// should not contribute to anything. So, rather than have a missing dex jar cause a Soong
// failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
// built Ninja should never use the dex jar file.
- if !isActiveModule(module) {
+ if !isActiveModule(ctx, module) {
return true
}
if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
- apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
return true
}
@@ -1432,7 +1469,9 @@ func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module,
// However, under certain conditions, e.g. errors, or special build configurations it will return
// a path to a fake file.
func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
- bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath()
+ bootDexJar := module.(interface {
+ DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
+ }).DexJarBuildPath(ctx)
if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
@@ -1440,13 +1479,3 @@ func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module andro
}
return bootDexJar.Path()
}
-
-// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
-func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
- encodedDexJarsByModuleName := bootDexJarByModule{}
- for _, module := range contents {
- path := retrieveEncodedBootDexJarFromModule(ctx, module)
- encodedDexJarsByModuleName.addPath(module, path)
- }
- return encodedDexJarsByModuleName
-}
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index 5956e3c6c..1e30c5f82 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -67,9 +67,8 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F
case *ClasspathFragmentElement:
fragment := e.Module()
- if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
- info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
- monolithicInfo.append(&info)
+ if info, ok := android.OtherModuleProvider(ctx, fragment, HiddenAPIInfoProvider); ok {
+ monolithicInfo.append(ctx, fragment, &info)
} else {
ctx.ModuleErrorf("%s does not provide hidden API information", fragment)
}
@@ -80,14 +79,25 @@ func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory F
}
// append appends all the files from the supplied info to the corresponding files in this struct.
-func (i *MonolithicHiddenAPIInfo) append(other *HiddenAPIInfo) {
+func (i *MonolithicHiddenAPIInfo) append(ctx android.ModuleContext, otherModule android.Module, other *HiddenAPIInfo) {
i.FlagsFilesByCategory.append(other.FlagFilesByCategory)
i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPath)
i.MetadataPaths = append(i.MetadataPaths, other.MetadataPath)
i.IndexPaths = append(i.IndexPaths, other.IndexPath)
- i.StubFlagSubsets = append(i.StubFlagSubsets, other.StubFlagSubset())
- i.FlagSubsets = append(i.FlagSubsets, other.FlagSubset())
+ apexInfo, ok := android.OtherModuleProvider(ctx, otherModule, android.ApexInfoProvider)
+ if !ok {
+ ctx.ModuleErrorf("Could not determine min_version_version of %s\n", otherModule.Name())
+ return
+ }
+ if apexInfo.MinSdkVersion.LessThanOrEqualTo(android.ApiLevelR) {
+ // Restrict verify_overlaps to R and older modules.
+ // The runtime in S does not have the same restriction that
+ // requires the hiddenapi flags to be generated in a monolithic
+ // invocation.
+ i.StubFlagSubsets = append(i.StubFlagSubsets, other.StubFlagSubset())
+ i.FlagSubsets = append(i.FlagSubsets, other.FlagSubset())
+ }
}
-var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
+var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider[MonolithicHiddenAPIInfo]()
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 52934a327..7d21b7a61 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -25,7 +25,7 @@ func init() {
}
func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ ctx.RegisterParallelSingletonType("hiddenapi", hiddenAPISingletonFactory)
}
var PrepareForTestWithHiddenApiBuildComponents = android.FixtureRegisterWithContext(RegisterHiddenApiSingletonComponents)
@@ -121,8 +121,8 @@ type hiddenAPISingleton struct {
// hiddenAPI singleton rules
func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
- // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ // Don't run any hiddenapi rules if hiddenapi checks are disabled
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
@@ -150,6 +150,10 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu
// Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
name = android.RemoveOptionalPrebuiltPrefix(name)
+ // Strip the ".impl" suffix, so that the implementation library of the java_sdk_library is
+ // treated identical to the top level java_sdk_library.
+ name = strings.TrimSuffix(name, ".impl")
+
// Ignore any module that is not listed in the boot image configuration.
index := configuredBootJars.IndexOfJar(name)
if index == -1 {
@@ -162,11 +166,11 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu
return false
}
- apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
- if requiredApex == "platform" || requiredApex == "system_ext" {
+ if android.IsConfiguredJarForPlatform(requiredApex) {
if len(apexInfo.InApexVariants) != 0 {
// A platform variant is required but this is for an apex so ignore it.
return false
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index ef792f970..62297978c 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -177,10 +177,10 @@ func TestHiddenAPISingletonSdks(t *testing.T) {
{
name: "testBundled",
unbundledBuild: false,
- publicStub: "android_stubs_current",
- systemStub: "android_system_stubs_current",
- testStub: "android_test_stubs_current",
- corePlatformStub: "legacy.core.platform.api.stubs",
+ publicStub: "android_stubs_current_exportable",
+ systemStub: "android_system_stubs_current_exportable",
+ testStub: "android_test_stubs_current_exportable",
+ corePlatformStub: "legacy.core.platform.api.stubs.exportable",
preparer: android.GroupFixturePreparers(),
}, {
name: "testUnbundled",
@@ -188,7 +188,7 @@ func TestHiddenAPISingletonSdks(t *testing.T) {
publicStub: "sdk_public_current_android",
systemStub: "sdk_system_current_android",
testStub: "sdk_test_current_android",
- corePlatformStub: "legacy.core.platform.api.stubs",
+ corePlatformStub: "legacy.core.platform.api.stubs.exportable",
preparer: PrepareForTestWithPrebuiltsOfCurrentApi,
},
}
@@ -198,10 +198,22 @@ func TestHiddenAPISingletonSdks(t *testing.T) {
hiddenApiFixtureFactory,
tc.preparer,
prepareForTestWithDefaultPlatformBootclasspath,
+ // Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi
+ // file creation.
+ FixtureConfigureBootJars("platform:foo"),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
}),
- ).RunTest(t)
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+ `)
hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
@@ -300,7 +312,7 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
`)
checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
- moduleForTests := result.ModuleForTests(name, "android_common")
+ moduleForTests := result.ModuleForTests(name+".impl", "android_common")
encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
actualUnencodedDexJar := encodeDexRule.Input
@@ -309,24 +321,15 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
// Make sure that the encoded dex jar is the exported one.
- exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath().Path()
+ errCtx := moduleErrorfTestCtx{}
+ exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath(errCtx).Path()
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/android_common/aligned/foo.jar"
- expectedEncodedDexJar := "out/soong/.intermediates/foo/android_common/hiddenapi/foo.jar"
+ 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)
})
-
- // The dex jar of the child implementation java_library of the java_sdk_library is not currently
- // dex encoded.
- t.Run("foo.impl", func(t *testing.T) {
- fooImpl := result.ModuleForTests("foo.impl", "android_common")
- encodeDexRule := fooImpl.MaybeRule("hiddenAPIEncodeDex")
- if encodeDexRule.Rule != nil {
- t.Errorf("foo.impl is not expected to be encoded")
- }
- })
}
diff --git a/java/jacoco.go b/java/jacoco.go
index f8012b852..696a0cc37 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -34,13 +34,11 @@ var (
`${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
`${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JacocoCLIJar} ` +
` instrument --quiet --dest $tmpDir $strippedJar && ` +
- `${config.Ziptime} $tmpJar && ` +
`${config.MergeZipsCmd} --ignore-duplicates -j $out $tmpJar $in`,
CommandDeps: []string{
"${config.Zip2ZipCmd}",
"${config.JavaCmd}",
"${config.JacocoCLIJar}",
- "${config.Ziptime}",
"${config.MergeZipsCmd}",
},
},
@@ -55,7 +53,7 @@ func jacocoDepsMutator(ctx android.BottomUpMutatorContext) {
}
j, ok := ctx.Module().(instrumentable)
- if !ctx.Module().Enabled() || !ok {
+ if !ctx.Module().Enabled(ctx) || !ok {
return
}
diff --git a/java/java.go b/java/java.go
index 0eb251815..88b31b586 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,11 +21,12 @@ package java
import (
"fmt"
"path/filepath"
+ "slices"
+ "sort"
"strings"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"android/soong/remoteexec"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -62,6 +63,7 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("dex_import", DexImportFactory)
ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
+ ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
// This mutator registers dependencies on dex2oat for modules that should be
// dexpreopted. This is done late when the final variants have been
@@ -73,19 +75,26 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) {
ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel()
})
- ctx.RegisterSingletonType("logtags", LogtagsSingleton)
- ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
+ ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
func RegisterJavaSdkMemberTypes() {
// Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
android.RegisterSdkMemberType(javaLibsSdkMemberType)
- android.RegisterSdkMemberType(javaBootLibsSdkMemberType)
- android.RegisterSdkMemberType(javaSystemserverLibsSdkMemberType)
+ android.RegisterSdkMemberType(JavaBootLibsSdkMemberType)
+ android.RegisterSdkMemberType(JavaSystemserverLibsSdkMemberType)
android.RegisterSdkMemberType(javaTestSdkMemberType)
}
+type StubsLinkType int
+
+const (
+ Unknown StubsLinkType = iota
+ Stubs
+ Implementation
+)
+
var (
// Supports adding java header libraries to module_exports and sdk.
javaHeaderLibsSdkMemberType = &librarySdkMemberType{
@@ -145,7 +154,7 @@ var (
// either java_libs, or java_header_libs would end up exporting more information than was strictly
// necessary. The java_boot_libs property to allow those modules to be exported as part of the
// sdk/module_exports without exposing any unnecessary information.
- javaBootLibsSdkMemberType = &librarySdkMemberType{
+ JavaBootLibsSdkMemberType = &librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_boot_libs",
SupportsSdk: true,
@@ -184,7 +193,7 @@ var (
// either java_libs, or java_header_libs would end up exporting more information than was strictly
// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
// the sdk/module_exports without exposing any unnecessary information.
- javaSystemserverLibsSdkMemberType = &librarySdkMemberType{
+ JavaSystemserverLibsSdkMemberType = &librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_systemserver_libs",
SupportsSdk: true,
@@ -224,17 +233,36 @@ var (
}, "jar_name", "partition", "main_class")
)
+type ProguardSpecInfo struct {
+ // If true, proguard flags files will be exported to reverse dependencies across libs edges
+ // If false, proguard flags files will only be exported to reverse dependencies across
+ // static_libs edges.
+ Export_proguard_flags_files bool
+
+ // TransitiveDepsProguardSpecFiles is a depset of paths to proguard flags files that are exported from
+ // all transitive deps. This list includes all proguard flags files from transitive static dependencies,
+ // and all proguard flags files from transitive libs dependencies which set `export_proguard_spec: true`.
+ ProguardFlagsFiles *android.DepSet[android.Path]
+
+ // implementation detail to store transitive proguard flags files from exporting shared deps
+ UnconditionallyExportedProguardFlags *android.DepSet[android.Path]
+}
+
+var ProguardSpecInfoProvider = blueprint.NewProvider[ProguardSpecInfo]()
+
// 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
// against this module. If empty, ImplementationJars should be used instead.
HeaderJars android.Paths
+ RepackagedHeaderJars android.Paths
+
// set of header jars for all transitive libs deps
- TransitiveLibsHeaderJars *android.DepSet
+ TransitiveLibsHeaderJars *android.DepSet[android.Path]
// set of header jars for all transitive static libs deps
- TransitiveStaticLibsHeaderJars *android.DepSet
+ TransitiveStaticLibsHeaderJars *android.DepSet[android.Path]
// ImplementationAndResourceJars is a list of jars that contain the implementations of classes
// in the module as well as any resources included in the module.
@@ -258,6 +286,9 @@ type JavaInfo struct {
// SrcJarDeps is a list of paths to depend on when packaging the sources of this module.
SrcJarDeps android.Paths
+ // The source files of this module and all its transitive static dependencies.
+ TransitiveSrcFiles *android.DepSet[android.Path]
+
// ExportedPlugins is a list of paths that should be used as annotation processors for any
// module that depends on this module.
ExportedPlugins android.Paths
@@ -273,9 +304,18 @@ type JavaInfo struct {
// JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
// instrumented by jacoco.
JacocoReportClassesFile android.Path
+
+ // StubsLinkType provides information about whether the provided jars are stub jars or
+ // implementation jars. If the provider is set by java_sdk_library, the link type is "unknown"
+ // and selection between the stub jar vs implementation jar is deferred to SdkLibrary.sdkJars(...)
+ StubsLinkType StubsLinkType
+
+ // AconfigIntermediateCacheOutputPaths is a path to the cache files collected from the
+ // java_aconfig_library modules that are statically linked to this module.
+ AconfigIntermediateCacheOutputPaths android.Paths
}
-var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
+var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
// the sysprop implementation library.
@@ -285,7 +325,7 @@ type SyspropPublicStubInfo struct {
JavaInfo JavaInfo
}
-var SyspropPublicStubInfoProvider = blueprint.NewProvider(SyspropPublicStubInfo{})
+var SyspropPublicStubInfoProvider = blueprint.NewProvider[SyspropPublicStubInfo]()
// Methods that need to be implemented for a module that is added to apex java_libs property.
type ApexDependency interface {
@@ -295,16 +335,11 @@ type ApexDependency interface {
// Provides build path and install path to DEX jars.
type UsesLibraryDependency interface {
- DexJarBuildPath() OptionalDexJarPath
+ DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
DexJarInstallPath() android.Path
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
-// Provides transitive Proguard flag files to downstream DEX jars.
-type LibraryDependency interface {
- ExportedProguardFlagFiles() android.Paths
-}
-
// TODO(jungjw): Move this to kythe.go once it's created.
type xref interface {
XrefJavaFiles() android.Paths
@@ -314,6 +349,12 @@ func (j *Module) XrefJavaFiles() android.Paths {
return j.kytheFiles
}
+func (d dependencyTag) PropagateAconfigValidation() bool {
+ return d.static
+}
+
+var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
+
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -323,14 +364,16 @@ type dependencyTag struct {
// True if the dependency is a toolchain, for example an annotation processor.
toolchain bool
+
+ static bool
+
+ installable bool
}
-// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
-// dependency to be installed when the parent module is installed.
-type installDependencyTag struct {
- blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag
- name string
+var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil)
+
+func (d dependencyTag) InstallDepNeeded() bool {
+ return d.installable
}
func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
@@ -362,13 +405,13 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDepe
}
func IsJniDepTag(depTag blueprint.DependencyTag) bool {
- return depTag == jniLibTag
+ return depTag == jniLibTag || depTag == jniInstallTag
}
var (
dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
- staticLibTag = dependencyTag{name: "staticlib"}
+ staticLibTag = dependencyTag{name: "staticlib", static: true}
libTag = dependencyTag{name: "javalib", runtimeLinked: true}
sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
@@ -390,8 +433,9 @@ var (
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
- jniInstallTag = installDependencyTag{name: "jni install"}
- binaryInstallTag = installDependencyTag{name: "binary install"}
+ aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
+ jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
+ binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
@@ -447,6 +491,7 @@ type jniLib struct {
coverageFile android.OptionalPath
unstrippedFile android.Path
partition string
+ installPaths android.InstallPaths
}
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
@@ -456,7 +501,9 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext,
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
- ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, proguardRaiseTag,
+ config.LegacyCorePlatformBootclasspathLibraries...,
+ )
}
if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
@@ -501,6 +548,7 @@ type deps struct {
kotlinStdlib android.Paths
kotlinAnnotations android.Paths
kotlinPlugins android.Paths
+ aconfigProtoFiles android.Paths
disableTurbine bool
}
@@ -519,6 +567,12 @@ func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext an
return normalizeJavaVersion(ctx, javaVersion)
} else if ctx.Device() {
return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
+ } else if ctx.Config().TargetsJava21() {
+ // Temporary experimental flag to be able to try and build with
+ // java version 21 options. The flag, if used, just sets Java
+ // 21 as the default version, leaving any components that
+ // target an older version intact.
+ return JAVA_VERSION_21
} else {
return JAVA_VERSION_17
}
@@ -539,14 +593,17 @@ const (
JAVA_VERSION_9 = 9
JAVA_VERSION_11 = 11
JAVA_VERSION_17 = 17
+ JAVA_VERSION_21 = 21
)
func (v javaVersion) String() string {
switch v {
case JAVA_VERSION_6:
- return "1.6"
+ // Java version 1.6 no longer supported, bumping to 1.8
+ return "1.8"
case JAVA_VERSION_7:
- return "1.7"
+ // Java version 1.7 no longer supported, bumping to 1.8
+ return "1.8"
case JAVA_VERSION_8:
return "1.8"
case JAVA_VERSION_9:
@@ -555,6 +612,8 @@ func (v javaVersion) String() string {
return "11"
case JAVA_VERSION_17:
return "17"
+ case JAVA_VERSION_21:
+ return "21"
default:
return "unsupported"
}
@@ -563,10 +622,12 @@ func (v javaVersion) String() string {
func (v javaVersion) StringForKotlinc() string {
// $ ./external/kotlinc/bin/kotlinc -jvm-target foo
// error: unknown JVM target version: foo
- // Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
+ // Supported versions: 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
switch v {
+ case JAVA_VERSION_6:
+ return "1.8"
case JAVA_VERSION_7:
- return "1.6"
+ return "1.8"
case JAVA_VERSION_9:
return "9"
default:
@@ -582,9 +643,11 @@ func (v javaVersion) usesJavaModules() bool {
func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) javaVersion {
switch javaVersion {
case "1.6", "6":
- return JAVA_VERSION_6
+ // Java version 1.6 no longer supported, bumping to 1.8
+ return JAVA_VERSION_8
case "1.7", "7":
- return JAVA_VERSION_7
+ // Java version 1.7 no longer supported, bumping to 1.8
+ return JAVA_VERSION_8
case "1.8", "8":
return JAVA_VERSION_8
case "1.9", "9":
@@ -593,6 +656,8 @@ func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) jav
return JAVA_VERSION_11
case "17":
return JAVA_VERSION_17
+ case "21":
+ return JAVA_VERSION_21
case "10", "12", "13", "14", "15", "16":
ctx.PropertyErrorf("java_version", "Java language level %s is not supported", javaVersion)
return JAVA_VERSION_UNSUPPORTED
@@ -609,19 +674,17 @@ func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) jav
type Library struct {
Module
- exportedProguardFlagFiles android.Paths
+ combinedExportedProguardFlagsFile android.Path
- InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
+ InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths)
}
-var _ LibraryDependency = (*Library)(nil)
+var _ android.ApexModule = (*Library)(nil)
-func (j *Library) ExportedProguardFlagFiles() android.Paths {
- return j.exportedProguardFlagFiles
+func (j *Library) CheckDepsMinSdkVersion(ctx android.ModuleContext) {
+ CheckMinSdkVersion(ctx, j)
}
-var _ android.ApexModule = (*Library)(nil)
-
// Provides access to the list of permitted packages from apex boot jars.
type PermittedPackagesForUpdatableBootJars interface {
PermittedPackagesForUpdatableBootJars() []string
@@ -633,9 +696,9 @@ func (j *Library) PermittedPackagesForUpdatableBootJars() []string {
return j.properties.Permitted_packages
}
-func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
+func shouldUncompressDex(ctx android.ModuleContext, libName string, dexpreopter *dexpreopter) bool {
// Store uncompressed (and aligned) any dex files from jars in APEXes.
- if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
return true
}
@@ -644,10 +707,11 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
return true
}
- // Store uncompressed dex files that are preopted on /system.
- if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, dexpreopter.installPath)) {
+ // Store uncompressed dex files that are preopted on /system or /system_other.
+ if !dexpreopter.dexpreoptDisabled(ctx, libName) {
return true
}
+
if ctx.Config().UncompressPrivAppDex() &&
inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
return true
@@ -660,40 +724,268 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) {
if dexer.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, dexpreopter))
+ dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexpreopter))
}
}
-func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+// list of java_library modules that set platform_apis: true
+// this property is a no-op for java_library
+// TODO (b/215379393): Remove this allowlist
+var (
+ aospPlatformApiAllowlist = map[string]bool{
+ "adservices-test-scenarios": true,
+ "aidl-cpp-java-test-interface-java": true,
+ "aidl-test-extras-java": true,
+ "aidl-test-interface-java": true,
+ "aidl-test-interface-permission-java": true,
+ "aidl_test_java_client_permission": true,
+ "aidl_test_java_client_sdk1": true,
+ "aidl_test_java_client_sdk29": true,
+ "aidl_test_java_client": true,
+ "aidl_test_java_service_permission": true,
+ "aidl_test_java_service_sdk1": true,
+ "aidl_test_java_service_sdk29": true,
+ "aidl_test_java_service": true,
+ "aidl_test_loggable_interface-java": true,
+ "aidl_test_nonvintf_parcelable-V1-java": true,
+ "aidl_test_nonvintf_parcelable-V2-java": true,
+ "aidl_test_unstable_parcelable-java": true,
+ "aidl_test_vintf_parcelable-V1-java": true,
+ "aidl_test_vintf_parcelable-V2-java": true,
+ "android.aidl.test.trunk-V1-java": true,
+ "android.aidl.test.trunk-V2-java": true,
+ "android.frameworks.location.altitude-V1-java": true,
+ "android.frameworks.location.altitude-V2-java": true,
+ "android.frameworks.stats-V1-java": true,
+ "android.frameworks.stats-V2-java": true,
+ "android.frameworks.stats-V3-java": true,
+ "android.hardware.authsecret-V1-java": true,
+ "android.hardware.authsecret-V2-java": true,
+ "android.hardware.biometrics.common-V1-java": true,
+ "android.hardware.biometrics.common-V2-java": true,
+ "android.hardware.biometrics.common-V3-java": true,
+ "android.hardware.biometrics.common-V4-java": true,
+ "android.hardware.biometrics.face-V1-java": true,
+ "android.hardware.biometrics.face-V2-java": true,
+ "android.hardware.biometrics.face-V3-java": true,
+ "android.hardware.biometrics.face-V4-java": true,
+ "android.hardware.biometrics.fingerprint-V1-java": true,
+ "android.hardware.biometrics.fingerprint-V2-java": true,
+ "android.hardware.biometrics.fingerprint-V3-java": true,
+ "android.hardware.biometrics.fingerprint-V4-java": true,
+ "android.hardware.bluetooth.lmp_event-V1-java": true,
+ "android.hardware.confirmationui-V1-java": true,
+ "android.hardware.confirmationui-V2-java": true,
+ "android.hardware.gatekeeper-V1-java": true,
+ "android.hardware.gatekeeper-V2-java": true,
+ "android.hardware.gnss-V1-java": true,
+ "android.hardware.gnss-V2-java": true,
+ "android.hardware.gnss-V3-java": true,
+ "android.hardware.gnss-V4-java": true,
+ "android.hardware.graphics.common-V1-java": true,
+ "android.hardware.graphics.common-V2-java": true,
+ "android.hardware.graphics.common-V3-java": true,
+ "android.hardware.graphics.common-V4-java": true,
+ "android.hardware.graphics.common-V5-java": true,
+ "android.hardware.identity-V1-java": true,
+ "android.hardware.identity-V2-java": true,
+ "android.hardware.identity-V3-java": true,
+ "android.hardware.identity-V4-java": true,
+ "android.hardware.identity-V5-java": true,
+ "android.hardware.identity-V6-java": true,
+ "android.hardware.keymaster-V1-java": true,
+ "android.hardware.keymaster-V2-java": true,
+ "android.hardware.keymaster-V3-java": true,
+ "android.hardware.keymaster-V4-java": true,
+ "android.hardware.keymaster-V5-java": true,
+ "android.hardware.oemlock-V1-java": true,
+ "android.hardware.oemlock-V2-java": true,
+ "android.hardware.power.stats-V1-java": true,
+ "android.hardware.power.stats-V2-java": true,
+ "android.hardware.power.stats-V3-java": true,
+ "android.hardware.power-V1-java": true,
+ "android.hardware.power-V2-java": true,
+ "android.hardware.power-V3-java": true,
+ "android.hardware.power-V4-java": true,
+ "android.hardware.power-V5-java": true,
+ "android.hardware.rebootescrow-V1-java": true,
+ "android.hardware.rebootescrow-V2-java": true,
+ "android.hardware.security.authgraph-V1-java": true,
+ "android.hardware.security.keymint-V1-java": true,
+ "android.hardware.security.keymint-V2-java": true,
+ "android.hardware.security.keymint-V3-java": true,
+ "android.hardware.security.keymint-V4-java": true,
+ "android.hardware.security.secretkeeper-V1-java": true,
+ "android.hardware.security.secureclock-V1-java": true,
+ "android.hardware.security.secureclock-V2-java": true,
+ "android.hardware.thermal-V1-java": true,
+ "android.hardware.thermal-V2-java": true,
+ "android.hardware.threadnetwork-V1-java": true,
+ "android.hardware.weaver-V1-java": true,
+ "android.hardware.weaver-V2-java": true,
+ "android.hardware.weaver-V3-java": true,
+ "android.security.attestationmanager-java": true,
+ "android.security.authorization-java": true,
+ "android.security.compat-java": true,
+ "android.security.legacykeystore-java": true,
+ "android.security.maintenance-java": true,
+ "android.security.metrics-java": true,
+ "android.system.keystore2-V1-java": true,
+ "android.system.keystore2-V2-java": true,
+ "android.system.keystore2-V3-java": true,
+ "android.system.keystore2-V4-java": true,
+ "binderReadParcelIface-java": true,
+ "binderRecordReplayTestIface-java": true,
+ "car-experimental-api-static-lib": true,
+ "collector-device-lib-platform": true,
+ "com.android.car.oem": true,
+ "com.google.hardware.pixel.display-V10-java": true,
+ "com.google.hardware.pixel.display-V1-java": true,
+ "com.google.hardware.pixel.display-V2-java": true,
+ "com.google.hardware.pixel.display-V3-java": true,
+ "com.google.hardware.pixel.display-V4-java": true,
+ "com.google.hardware.pixel.display-V5-java": true,
+ "com.google.hardware.pixel.display-V6-java": true,
+ "com.google.hardware.pixel.display-V7-java": true,
+ "com.google.hardware.pixel.display-V8-java": true,
+ "com.google.hardware.pixel.display-V9-java": true,
+ "conscrypt-support": true,
+ "cts-keystore-test-util": true,
+ "cts-keystore-user-auth-helper-library": true,
+ "ctsmediautil": true,
+ "CtsNetTestsNonUpdatableLib": true,
+ "DpmWrapper": true,
+ "flickerlib-apphelpers": true,
+ "flickerlib-helpers": true,
+ "flickerlib-parsers": true,
+ "flickerlib": true,
+ "hardware.google.bluetooth.ccc-V1-java": true,
+ "hardware.google.bluetooth.sar-V1-java": true,
+ "monet": true,
+ "pixel-power-ext-V1-java": true,
+ "pixel-power-ext-V2-java": true,
+ "pixel_stateresidency_provider_aidl_interface-java": true,
+ "pixel-thermal-ext-V1-java": true,
+ "protolog-lib": true,
+ "RkpRegistrationCheck": true,
+ "rotary-service-javastream-protos": true,
+ "service_based_camera_extensions": true,
+ "statsd-helper-test": true,
+ "statsd-helper": true,
+ "test-piece-2-V1-java": true,
+ "test-piece-2-V2-java": true,
+ "test-piece-3-V1-java": true,
+ "test-piece-3-V2-java": true,
+ "test-piece-3-V3-java": true,
+ "test-piece-4-V1-java": true,
+ "test-piece-4-V2-java": true,
+ "test-root-package-V1-java": true,
+ "test-root-package-V2-java": true,
+ "test-root-package-V3-java": true,
+ "test-root-package-V4-java": true,
+ "testServiceIface-java": true,
+ "wm-flicker-common-app-helpers": true,
+ "wm-flicker-common-assertions": true,
+ "wm-shell-flicker-utils": true,
+ "wycheproof-keystore": true,
+ }
+
+ // Union of aosp and internal allowlists
+ PlatformApiAllowlist = map[string]bool{}
+)
+func init() {
+ for k, v := range aospPlatformApiAllowlist {
+ PlatformApiAllowlist[k] = v
+ }
+}
+
+func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if disableSourceApexVariant(ctx) {
+ // Prebuilts are active, do not create the installation rules for the source javalib.
+ // Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules.
+ // TODO (b/331665856): Implement a principled solution for this.
+ j.HideFromMake()
+ }
j.provideHiddenAPIPropertyInfo(ctx)
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
j.maxSdkVersion = j.MaxSdkVersion(ctx)
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ // Check min_sdk_version of the transitive dependencies if this module is created from
+ // java_sdk_library.
+ if j.overridableProperties.Min_sdk_version != nil && j.SdkLibraryName() != nil {
+ j.CheckDepsMinSdkVersion(ctx)
+ }
+
+ // SdkLibrary.GenerateAndroidBuildActions(ctx) sets the stubsLinkType to Unknown.
+ // If the stubsLinkType has already been set to Unknown, the stubsLinkType should
+ // not be overridden.
+ if j.stubsLinkType != Unknown {
+ if proptools.Bool(j.properties.Is_stubs_module) {
+ j.stubsLinkType = Stubs
+ } else {
+ j.stubsLinkType = Implementation
+ }
+ }
+
+ j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
+
+ proguardSpecInfo := j.collectProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
+ exportedProguardFlagsFiles := proguardSpecInfo.ProguardFlagsFiles.ToList()
+ j.extraProguardFlagsFiles = append(j.extraProguardFlagsFiles, exportedProguardFlagsFiles...)
+
+ combinedExportedProguardFlagFile := android.PathForModuleOut(ctx, "export_proguard_flags")
+ writeCombinedProguardFlagsFile(ctx, combinedExportedProguardFlagFile, exportedProguardFlagsFiles)
+ j.combinedExportedProguardFlagsFile = combinedExportedProguardFlagFile
+
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
j.checkSdkVersions(ctx)
+ j.checkHeadersOnly(ctx)
if ctx.Device() {
+ libName := j.Name()
+ if j.SdkLibraryName() != nil && strings.HasSuffix(libName, ".impl") {
+ libName = proptools.String(j.SdkLibraryName())
+ }
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
+ ctx, libName, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+ if j.usesLibrary.shouldDisableDexpreopt {
+ j.dexpreopter.disableDexpreopt()
+ }
}
- j.compile(ctx, nil)
+ j.compile(ctx, nil, nil, nil)
+
+ // If this module is an impl library created from java_sdk_library,
+ // install the files under the java_sdk_library module outdir instead of this module outdir.
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ j.setInstallRules(ctx, proptools.String(j.SdkLibraryName()))
+ } else {
+ j.setInstallRules(ctx, ctx.ModuleName())
+ }
+
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: Bool(j.sourceProperties.Test_only),
+ TopLevelTarget: j.sourceProperties.Top_level_test_target,
+ })
- // Collect the module directory for IDE info in java/jdeps.go.
- j.modulePaths = append(j.modulePaths, ctx.ModuleDir())
+ setOutputFiles(ctx, j.Module)
+}
+
+func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- exclusivelyForApex := !apexInfo.IsForPlatform()
- if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
- var extraInstallDeps android.Paths
+ if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
+ var extraInstallDeps android.InstallPaths
if j.InstallMixin != nil {
extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
}
@@ -709,26 +1001,27 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if !ctx.Host() {
archDir = ctx.DeviceConfig().DeviceArch()
}
- installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+ installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
} else {
installDir = android.PathForModuleInstall(ctx, "framework")
}
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
-
- j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles,
- android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)...)
- ctx.VisitDirectDeps(func(m android.Module) {
- if lib, ok := m.(LibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
- j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
- }
- })
- j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles)
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
- j.deps(ctx)
j.usesLibrary.deps(ctx, false)
+ j.deps(ctx)
+
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ dexpreopt.RegisterToolDeps(ctx)
+ }
+ prebuiltSdkLibExists := ctx.OtherModuleExists(android.PrebuiltNameFromSource(proptools.String(j.SdkLibraryName())))
+ if prebuiltSdkLibExists && ctx.OtherModuleExists("all_apex_contributions") {
+ ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions")
+ }
+ }
}
const (
@@ -812,8 +1105,11 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberCo
// If the min_sdk_version was set then add the canonical representation of the API level to the
// snapshot.
- if j.deviceProperties.Min_sdk_version != nil {
- canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
+ if j.overridableProperties.Min_sdk_version != nil {
+ canonical, err := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
p.MinSdkVersion = proptools.StringPtr(canonical)
}
@@ -886,11 +1182,11 @@ func LibraryFactory() android.Module {
module := &Library{}
module.addHostAndDeviceProperties()
+ module.AddProperties(&module.sourceProperties)
module.initModuleAndImport(module)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -912,7 +1208,6 @@ func LibraryHostFactory() android.Module {
module.Module.properties.Installable = proptools.BoolPtr(true)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -1063,6 +1358,10 @@ func (j *JavaTestImport) InstallInTestcases() bool {
return true
}
+func (j *TestHost) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool {
+ return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
if len(j.testHostProperties.Data_device_bins_first) > 0 {
deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
@@ -1199,10 +1498,23 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
+ InstalledFiles: j.data,
+ OutputFile: j.outputFile,
+ TestConfig: j.testConfig,
+ RequiredModuleNames: j.RequiredModuleNames(ctx),
+ TestSuites: j.testProperties.Test_suites,
+ IsHost: true,
+ LocalSdkVersion: j.sdkVersion.String(),
+ IsUnitTest: Bool(j.testProperties.Test_options.Unit_test),
+ })
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ checkMinSdkVersionMts(ctx, j.MinSdkVersion(ctx))
j.generateAndroidBuildActionsWithConfig(ctx, nil)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
@@ -1238,7 +1550,7 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext,
})
ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
- sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
if sharedLibInfo.SharedLibrary != nil {
// Copy to an intermediate output directory to append "lib[64]" to the path,
// so that it's compatible with the default rpath values.
@@ -1355,6 +1667,8 @@ 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.sourceProperties.Test_only = proptools.BoolPtr(true)
+ module.Module.sourceProperties.Top_level_test_target = true
InitJavaModule(module, android.HostAndDeviceSupported)
return module
@@ -1370,6 +1684,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.sourceProperties.Test_only = proptools.BoolPtr(true)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
@@ -1425,6 +1740,8 @@ func InitTestHost(th *TestHost, installable *bool, testSuites []string, autoGenC
th.properties.Installable = installable
th.testProperties.Auto_gen_config = autoGenConfig
th.testProperties.Test_suites = testSuites
+ th.sourceProperties.Test_only = proptools.BoolPtr(true)
+ th.sourceProperties.Top_level_test_target = true
}
//
@@ -1459,6 +1776,8 @@ func (j *Binary) HostToolPath() android.OptionalPath {
}
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
+
if ctx.Arch().ArchType == android.Common {
// Compile the jar
if j.binaryProperties.Main_class != nil {
@@ -1519,6 +1838,8 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// libraries. This is verified by TestBinary.
j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
ctx.ModuleName()+ext, j.wrapperFile)
+
+ setOutputFiles(ctx, j.Library.Module)
}
}
@@ -1548,13 +1869,12 @@ func BinaryFactory() android.Module {
module := &Binary{}
module.addHostAndDeviceProperties()
- module.AddProperties(&module.binaryProperties)
+ module.AddProperties(&module.binaryProperties, &module.sourceProperties)
module.Module.properties.Installable = proptools.BoolPtr(true)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -1573,13 +1893,13 @@ func BinaryHostFactory() android.Module {
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
type JavaApiContribution struct {
android.ModuleBase
android.DefaultableModuleBase
+ embeddableInModuleAndImport
properties struct {
// name of the API surface
@@ -1595,14 +1915,16 @@ func ApiContributionFactory() android.Module {
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
return module
}
type JavaApiImportInfo struct {
- ApiFile android.Path
+ ApiFile android.Path
+ ApiSurface string
}
-var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
+var JavaApiImportProvider = blueprint.NewProvider[JavaApiImportInfo]()
func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var apiFile android.Path = nil
@@ -1610,24 +1932,19 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon
apiFile = android.PathForModuleSrc(ctx, String(apiFileString))
}
- ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
- ApiFile: apiFile,
+ android.SetProvider(ctx, JavaApiImportProvider, JavaApiImportInfo{
+ ApiFile: apiFile,
+ ApiSurface: proptools.String(ap.properties.Api_surface),
})
}
-type JavaApiLibraryDepsInfo struct {
- JavaInfo
- StubsSrcJar android.Path
-}
-
-var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{})
-
type ApiLibrary struct {
android.ModuleBase
android.DefaultableModuleBase
hiddenAPI
dexer
+ embeddableInModuleAndImport
properties JavaApiLibraryProperties
@@ -1637,6 +1954,12 @@ type ApiLibrary struct {
extractedSrcJar android.WritablePath
// .dex of stubs, used for hiddenapi processing
dexJarFile OptionalDexJarPath
+
+ validationPaths android.Paths
+
+ stubsType StubsType
+
+ aconfigProtoFiles android.Paths
}
type JavaApiLibraryProperties struct {
@@ -1647,11 +1970,6 @@ type JavaApiLibraryProperties struct {
// This is a list of Soong modules
Api_contributions []string
- // list of api.txt files relative to this directory that contribute to the
- // API surface.
- // This is a list of relative paths
- Api_files []string
-
// List of flags to be passed to the javac compiler to generate jar file
Javacflags []string
@@ -1663,16 +1981,47 @@ type JavaApiLibraryProperties struct {
// merge zipped after metalava invocation
Static_libs []string
- // Java Api library to provide the full API surface text files and jar file.
- // If this property is set, the provided full API surface text files and
- // jar file are passed to metalava invocation.
- Dep_api_srcs *string
+ // Java Api library to provide the full API surface stub jar file.
+ // If this property is set, the stub jar of this module is created by
+ // extracting the compiled class files provided by the
+ // full_api_surface_stub module.
+ Full_api_surface_stub *string
+
+ // Version of previously released API file for compatibility check.
+ Previous_api *string `android:"path"`
+
+ // java_system_modules module providing the jar to be added to the
+ // bootclasspath when compiling the stubs.
+ // The jar will also be passed to metalava as a classpath to
+ // generate compilable stubs.
+ System_modules *string
+
+ // If true, the module runs validation on the API signature files provided
+ // by the modules passed via api_contributions by checking if the files are
+ // in sync with the source Java files. However, the environment variable
+ // DISABLE_STUB_VALIDATION has precedence over this property.
+ Enable_validation *bool
+
+ // Type of stubs the module should generate. Must be one of "everything", "runtime" or
+ // "exportable". Defaults to "everything".
+ // - "everything" stubs include all non-flagged apis and flagged apis, regardless of the state
+ // of the flag.
+ // - "runtime" stubs include all non-flagged apis and flagged apis that are ENABLED or
+ // READ_WRITE, and all other flagged apis are stripped.
+ // - "exportable" stubs include all non-flagged apis and flagged apis that are ENABLED and
+ // READ_ONLY, and all other flagged apis are stripped.
+ Stubs_type *string
+
+ // List of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
}
func ApiLibraryFactory() android.Module {
module := &ApiLibrary{}
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
android.InitDefaultableModule(module)
return module
}
@@ -1686,7 +2035,8 @@ func (al *ApiLibrary) StubsJar() android.Path {
}
func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
- srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+ srcs android.Paths, homeDir android.WritablePath,
+ classpath android.Paths) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -1710,13 +2060,10 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
FlagWithInputList("--source-files ", srcs, " ")
- cmd.Flag("--no-banner").
- Flag("--color").
+ cmd.Flag("--color").
Flag("--quiet").
- Flag("--format=v2").
Flag("--include-annotations").
// The flag makes nullability issues as warnings rather than errors by replacing
// @Nullable/@NonNull in the listed packages APIs with @RecentlyNullable/@RecentlyNonNull,
@@ -1728,6 +2075,18 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
FlagWithArg("--hide ", "InvalidNullabilityOverride").
FlagWithArg("--hide ", "ChangedDefault")
+ 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
+ // does not specify `--classpath` this is not needed for that. However, this is also used as a
+ // signal to the special metalava code for generating stubs from text files that it needs to add
+ // some additional items into the API (e.g. default constructors).
+ cmd.FlagWithArg("--api-class-resolution ", "api")
+ } else {
+ cmd.FlagWithArg("--api-class-resolution ", "api:classpath")
+ cmd.FlagWithInputList("--classpath ", classpath, ":")
+ }
+
return cmd
}
@@ -1745,50 +2104,120 @@ func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBui
}
}
-// This method extracts the stub java files from the srcjar file provided from dep_api_srcs module
-// and replaces the java stubs generated by invoking metalava in this module.
+func (al *ApiLibrary) addValidation(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, validationPaths android.Paths) {
+ for _, validationPath := range validationPaths {
+ cmd.Validation(validationPath)
+ }
+}
+
+// This method extracts the stub class files from the stub jar file provided
+// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
// This method is used because metalava can generate compilable from-text stubs only when
-// the codebase encompasses all classes listed in the input API text file, but a class can extend
+// the codebase encompasses all classes listed in the input API text file, and a class can extend
// a class that is not within the same API domain.
-func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, depApiSrcsSrcJar android.Path) {
- generatedStubsList := android.PathForModuleOut(ctx, "metalava", "sources.txt")
+func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) {
+ classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt")
unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
rule.Command().
BuiltTool("list_files").
Text(stubsDir.String()).
- FlagWithOutput("--out ", generatedStubsList).
+ FlagWithOutput("--out ", classFilesList).
FlagWithArg("--extensions ", ".java").
- FlagWithArg("--root ", unzippedSrcJarDir.String())
+ FlagWithArg("--root ", unzippedSrcJarDir.String()).
+ Flag("--classes")
rule.Command().
Text("unzip").
Flag("-q").
- Input(depApiSrcsSrcJar).
+ Input(fullApiSurfaceStubJar).
FlagWithArg("-d ", unzippedSrcJarDir.String())
rule.Command().
BuiltTool("soong_zip").
- Flag("-srcjar").
+ Flag("-jar").
Flag("-write_if_changed").
+ Flag("-ignore_missing_files").
+ Flag("-quiet").
FlagWithArg("-C ", unzippedSrcJarDir.String()).
- FlagWithInput("-l ", generatedStubsList).
- FlagWithOutput("-o ", al.stubsSrcJar)
+ FlagWithInput("-l ", classFilesList).
+ FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
}
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
+ addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
+ !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
+ proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
+
+ // Add the java_api_contribution module generating droidstubs module
+ // as dependency when validation adding conditions are met and
+ // the java_api_contribution module name has ".api.contribution" suffix.
+ // All droidstubs-generated modules possess the suffix in the name,
+ // but there is no such guarantee for tests.
+ if addValidations {
+ if strings.HasSuffix(apiContributionName, ".api.contribution") {
+ ctx.AddDependency(ctx.Module(), metalavaCurrentApiTimestampTag, strings.TrimSuffix(apiContributionName, ".api.contribution"))
+ } else {
+ ctx.ModuleErrorf("Validation is enabled for module %s but a "+
+ "current timestamp provider is not found for the api "+
+ "contribution %s",
+ ctx.ModuleName(),
+ apiContributionName,
+ )
+ }
+ }
}
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
- if al.properties.Dep_api_srcs != nil {
- ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Dep_api_srcs))
+ if al.properties.Full_api_surface_stub != nil {
+ ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
+ }
+ if al.properties.System_modules != nil {
+ ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
+ }
+ for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName)
+ }
+}
+
+// Map where key is the api scope name and value is the int value
+// representing the order of the api scope, narrowest to the widest
+var scopeOrderMap = AllApiScopes.MapToIndex(
+ func(s *apiScope) string { return s.name })
+
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
+ for _, srcFileInfo := range srcFilesInfo {
+ if srcFileInfo.ApiSurface == "" {
+ ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
+ }
+ }
+ sort.Slice(srcFilesInfo, func(i, j int) bool {
+ return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
+ })
+
+ return srcFilesInfo
+}
+
+var validstubsType = []StubsType{Everything, Runtime, Exportable}
+
+func (al *ApiLibrary) validateProperties(ctx android.ModuleContext) {
+ if al.properties.Stubs_type == nil {
+ ctx.ModuleErrorf("java_api_library module type must specify stubs_type property.")
+ } else {
+ al.stubsType = StringToStubsType(proptools.String(al.properties.Stubs_type))
+ }
+
+ if !android.InList(al.stubsType, validstubsType) {
+ ctx.PropertyErrorf("stubs_type", "%s is not a valid stubs_type property value. "+
+ "Must be one of %s.", proptools.String(al.properties.Stubs_type), validstubsType)
}
}
func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ al.validateProperties(ctx)
rule := android.NewRuleBuilder(pctx, ctx)
@@ -1796,81 +2225,110 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
SandboxInputs()
- var stubsDir android.OptionalPath
- stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
+ stubsDir := android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
rule.Command().Text("rm -rf").Text(stubsDir.String())
rule.Command().Text("mkdir -p").Text(stubsDir.String())
homeDir := android.PathForModuleOut(ctx, "metalava", "home")
- var srcFiles android.Paths
+ var srcFilesInfo []JavaApiImportInfo
var classPaths android.Paths
var staticLibs android.Paths
- var depApiSrcsStubsSrcJar android.Path
+ var depApiSrcsStubsJar android.Path
+ var systemModulesPaths android.Paths
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
case javaApiContributionTag:
- provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
- providerApiFile := provider.ApiFile
- if providerApiFile == nil {
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaApiImportProvider)
+ if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name())
}
- srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String()))
+ srcFilesInfo = append(srcFilesInfo, provider)
case libTag:
- provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
classPaths = append(classPaths, provider.HeaderJars...)
case staticLibTag:
- provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
staticLibs = append(staticLibs, provider.HeaderJars...)
case depApiSrcsTag:
- provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo)
- classPaths = append(classPaths, provider.HeaderJars...)
- depApiSrcsStubsSrcJar = provider.StubsSrcJar
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
+ depApiSrcsStubsJar = provider.HeaderJars[0]
+ case systemModulesTag:
+ module := dep.(SystemModulesProvider)
+ systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...)
+ case metalavaCurrentApiTimestampTag:
+ if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
+ al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
+ }
+ case aconfigDeclarationTag:
+ if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
+ al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath)
+ } else if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
+ al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
+ "module type is allowed for flags_packages property, but %s is neither "+
+ "of these supported module types",
+ dep.Name(),
+ )
+ }
}
})
- // Add the api_files inputs
- for _, api := range al.properties.Api_files {
- // Use MaybeExistentPathForSource since the api file might not exist during analysis.
- // This will be provided by the orchestrator in the combined execution.
- srcFiles = append(srcFiles, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), api))
+ srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
+ var srcFiles android.Paths
+ for _, srcFileInfo := range srcFilesInfo {
+ srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
}
- if srcFiles == nil {
+ if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
}
- cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+ cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths)
al.stubsFlags(ctx, cmd, stubsDir)
+ previousApi := String(al.properties.Previous_api)
+ if previousApi != "" {
+ previousApiFiles := android.PathsForModuleSrc(ctx, []string{previousApi})
+ cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
+ }
+
+ al.addValidation(ctx, cmd, al.validationPaths)
+
+ generateRevertAnnotationArgs(ctx, cmd, al.stubsType, al.aconfigProtoFiles)
+
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
+ al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
+ al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
- if depApiSrcsStubsSrcJar != nil {
- al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsSrcJar)
- } else {
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", al.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+ if depApiSrcsStubsJar != nil {
+ al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar)
}
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", al.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
- rule.Build("metalava", "metalava merged")
+ rule.Build("metalava", "metalava merged text")
- al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
- al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
+ if depApiSrcsStubsJar == nil {
+ var flags javaBuilderFlags
+ flags.javaVersion = getStubsJavaVersion()
+ flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
+ flags.classpath = classpath(classPaths)
+ flags.bootClasspath = classpath(systemModulesPaths)
- var flags javaBuilderFlags
- flags.javaVersion = getStubsJavaVersion()
- flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
- flags.classpath = classpath(classPaths)
+ annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
- TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
- android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+ TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
+ android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{})
+ }
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().
@@ -1888,7 +2346,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
classesJar: al.stubsJar,
jarName: ctx.ModuleName() + ".jar",
}
- dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+ dexOutputFile, _ := al.dexer.compileDex(ctx, dexParams)
uncompressed := true
al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
@@ -1896,22 +2354,17 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.Phony(ctx.ModuleName(), al.stubsJar)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(al.stubsJar),
ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
ImplementationJars: android.PathsIfNonNil(al.stubsJar),
AidlIncludeDirs: android.Paths{},
- })
-
- ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
- JavaInfo: JavaInfo{
- HeaderJars: android.PathsIfNonNil(al.stubsJar),
- },
- StubsSrcJar: al.stubsSrcJar,
+ StubsLinkType: Stubs,
+ // No aconfig libraries on api libraries
})
}
-func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
+func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return al.dexJarFile
}
@@ -1964,6 +2417,9 @@ type ImportProperties struct {
// List of shared java libs that this module has dependencies to
Libs []string
+ // List of static java libs that this module has dependencies to
+ Static_libs []string
+
// List of files to remove from the jar file(s)
Exclude_files []string
@@ -1981,13 +2437,25 @@ type ImportProperties struct {
// that depend on this module, as well as to aidl for this module.
Export_include_dirs []string
}
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
+ // Non-nil if this java_import module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
+
+ // Property signifying whether the module provides stubs jar or not.
+ Is_stubs_module *bool
}
type Import struct {
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
prebuilt android.Prebuilt
// Functionality common to Module and Import.
@@ -2001,16 +2469,20 @@ type Import struct {
// output file containing classes.dex and resources
dexJarFile OptionalDexJarPath
+ dexJarFileErr error
dexJarInstallFile android.Path
- combinedClasspathFile android.Path
- classLoaderContexts dexpreopt.ClassLoaderContextMap
- exportAidlIncludeDirs android.Paths
+ combinedImplementationFile android.Path
+ combinedHeaderFile android.Path
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+ exportAidlIncludeDirs android.Paths
hideApexVariantFromMake bool
sdkVersion android.SdkSpec
minSdkVersion android.ApiLevel
+
+ stubsLinkType StubsLinkType
}
var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
@@ -2054,12 +2526,20 @@ func (j *Import) PrebuiltSrcs() []string {
return j.properties.Jars
}
+func (j *Import) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
func (j *Import) Name() string {
return j.prebuilt.Name(j.ModuleBase.Name())
}
func (j *Import) Stem() string {
- return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
+ return proptools.StringDefault(j.properties.Stem, j.BaseModuleName())
+}
+
+func (j *Import) CreatedByJavaSdkLibraryName() *string {
+ return j.properties.Created_by_java_sdk_library_name
}
func (a *Import) JacocoReportClassesFile() android.Path {
@@ -2079,6 +2559,7 @@ func (j *Import) setStrictUpdatabilityLinting(bool) {
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
sdkDeps(ctx, android.SdkContext(j), j.dexer)
@@ -2086,49 +2567,46 @@ func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (j *Import) commonBuildActions(ctx android.ModuleContext) {
- //TODO(b/231322772) these should come from Bazel once available
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
- if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
if ctx.Windows() {
j.HideFromMake()
}
+
+ if proptools.Bool(j.properties.Is_stubs_module) {
+ j.stubsLinkType = Stubs
+ } else {
+ j.stubsLinkType = Implementation
+ }
}
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.commonBuildActions(ctx)
- jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
-
- jarName := j.Stem() + ".jar"
- outputFile := android.PathForModuleOut(ctx, "combined", jarName)
- TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
- false, j.properties.Exclude_files, j.properties.Exclude_dirs)
- if Bool(j.properties.Jetifier) {
- inputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
- TransformJetifier(ctx, outputFile, inputFile)
- }
- j.combinedClasspathFile = outputFile
j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
var flags javaBuilderFlags
j.collectTransitiveHeaderJars(ctx)
+ var staticJars android.Paths
+ var staticHeaderJars android.Paths
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
switch tag {
case libTag, sdkLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
case staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
+ staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
+ staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
}
@@ -2142,6 +2620,50 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
addCLCFromDep(ctx, module, j.classLoaderContexts)
})
+ jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
+ jarName := j.Stem() + ".jar"
+
+ // Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
+ // file of the module to be named jarName.
+ outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+ implementationJars := append(slices.Clone(jars), staticJars...)
+ TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+
+ // If no dependencies have separate header jars then there is no need to create a separate
+ // header jar for this module.
+ reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
+
+ var headerOutputFile android.ModuleOutPath
+ if reuseImplementationJarAsHeaderJar {
+ headerOutputFile = outputFile
+ } else {
+ headerJars := append(slices.Clone(jars), staticHeaderJars...)
+ headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ }
+
+ if Bool(j.properties.Jetifier) {
+ inputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
+ TransformJetifier(ctx, outputFile, inputFile)
+
+ if !reuseImplementationJarAsHeaderJar {
+ headerInputFile := headerOutputFile
+ headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
+ TransformJetifier(ctx, headerOutputFile, headerInputFile)
+ } else {
+ headerOutputFile = outputFile
+ }
+ }
+
+ // 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.
+ j.combinedHeaderFile = headerOutputFile.WithoutRel()
+ j.combinedImplementationFile = outputFile.WithoutRel()
+
j.maybeInstall(ctx, jarName, outputFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
@@ -2149,21 +2671,25 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if ctx.Device() {
// If this is a variant created for a prebuilt_apex then use the dex implementation jar
// obtained from the associated deapexer module.
- ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module.
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
- return // An error has been reported by FindDeapexerProviderForModule.
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call DexJarBuildPath
+ j.dexJarFileErr = err
+ j.initHiddenAPIError(err)
+ return
}
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName())
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
j.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
+ installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
j.dexJarInstallFile = installPath
- j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
+ j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -2171,8 +2697,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexpreopter.inputProfilePathOnHost = profilePath
}
- j.dexpreopt(ctx, dexOutputPath)
-
// Initialize the hiddenapi structure.
j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
} else {
@@ -2193,7 +2717,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Dex compilation
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", jarName))
+ ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", jarName))
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -2206,7 +2730,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
jarName: jarName,
}
- dexOutputFile = j.dexer.compileDex(ctx, dexParams)
+ dexOutputFile, _ = j.dexer.compileDex(ctx, dexParams)
if ctx.Failed() {
return
}
@@ -2222,14 +2746,19 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile),
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
- ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
+ ImplementationJars: android.PathsIfNonNil(j.combinedImplementationFile),
AidlIncludeDirs: j.exportAidlIncludeDirs,
+ StubsLinkType: j.stubsLinkType,
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
+
+ ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, "")
+ ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, ".jar")
}
func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
@@ -2250,32 +2779,18 @@ func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputF
ctx.InstallFile(installDir, jarName, outputFile)
}
-func (j *Import) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "", ".jar":
- return android.Paths{j.combinedClasspathFile}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
-var _ android.OutputFileProducer = (*Import)(nil)
-
func (j *Import) HeaderJars() android.Paths {
- if j.combinedClasspathFile == nil {
- return nil
- }
- return android.Paths{j.combinedClasspathFile}
+ return android.PathsIfNonNil(j.combinedHeaderFile)
}
func (j *Import) ImplementationAndResourcesJars() android.Paths {
- if j.combinedClasspathFile == nil {
- return nil
- }
- return android.Paths{j.combinedClasspathFile}
+ return android.PathsIfNonNil(j.combinedImplementationFile)
}
-func (j *Import) DexJarBuildPath() OptionalDexJarPath {
+func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if j.dexJarFileErr != nil {
+ ctx.ModuleErrorf(j.dexJarFileErr.Error())
+ }
return j.dexJarFile
}
@@ -2316,7 +2831,7 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
// java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set.
func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string {
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name)
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(name)
// Add the dex implementation jar to the set of exported files.
files := []string{
dexJarFileApexRootRelative,
@@ -2327,9 +2842,9 @@ func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []strin
return files
}
-// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
+// ApexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
// the java library with the specified name.
-func apexRootRelativePathToJavaLib(name string) string {
+func ApexRootRelativePathToJavaLib(name string) string {
return filepath.Join("javalib", name+".jar")
}
@@ -2340,6 +2855,10 @@ func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []st
return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
}
+func (j *Import) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2387,7 +2906,6 @@ func ImportFactory() android.Module {
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -2404,7 +2922,6 @@ func ImportFactoryHost() android.Module {
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -2473,14 +2990,14 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
- j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
+ ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
+ j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &j.dexpreopter)
inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
@@ -2519,7 +3036,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
- j.dexpreopt(ctx, dexOutputFile)
+ j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile)
if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
@@ -2527,7 +3044,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
-func (j *DexImport) DexJarBuildPath() OptionalDexJarPath {
+func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile
}
@@ -2599,7 +3116,7 @@ func DefaultsFactory() android.Module {
module.AddProperties(
&CommonProperties{},
&DeviceProperties{},
- &OverridableDeviceProperties{},
+ &OverridableProperties{},
&DexProperties{},
&DexpreoptProperties{},
&android.ProtoProperties{},
@@ -2608,6 +3125,7 @@ func DefaultsFactory() android.Module {
&appProperties{},
&appTestProperties{},
&overridableAppProperties{},
+ &hostTestProperties{},
&testProperties{},
&ImportProperties{},
&AARImportProperties{},
@@ -2619,6 +3137,8 @@ func DefaultsFactory() android.Module {
&LintProperties{},
&appTestHelperAppProperties{},
&JavaApiLibraryProperties{},
+ &bootclasspathFragmentProperties{},
+ &SourceOnlyBootclasspathProperties{},
)
android.InitDefaultsModule(module)
@@ -2648,7 +3168,7 @@ func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonC
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
-var inList = android.InList
+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,
@@ -2693,520 +3213,80 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
// from its CLC should be added to the current CLC.
if sdkLib != nil {
- clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
- dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+ optional := false
+ if module, ok := ctx.Module().(ModuleWithUsesLibrary); ok {
+ if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs) {
+ optional = true
+ }
+ }
+ clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional,
+ dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}
-type javaResourcesAttributes struct {
- Resources bazel.LabelListAttribute
- Resource_strip_prefix *string
-}
-
-func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes {
- var resources bazel.LabelList
- var resourceStripPrefix *string
+func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module,
+ usesLibrary *usesLibrary) {
- if m.properties.Java_resources != nil {
- resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources))
+ dep, ok := depModule.(ModuleWithUsesLibrary)
+ if !ok {
+ return
}
- //TODO(b/179889880) handle case where glob includes files outside package
- resDeps := ResourceDirsToFiles(
- ctx,
- m.properties.Java_resource_dirs,
- m.properties.Exclude_java_resource_dirs,
- m.properties.Exclude_java_resources,
- )
-
- for i, resDep := range resDeps {
- dir, files := resDep.dir, resDep.files
-
- resources.Append(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files)))
-
- // Bazel includes the relative path from the WORKSPACE root when placing the resource
- // inside the JAR file, so we need to remove that prefix
- resourceStripPrefix = proptools.StringPtr(dir.String())
- if i > 0 {
- // TODO(b/226423379) allow multiple resource prefixes
- ctx.ModuleErrorf("bp2build does not support more than one directory in java_resource_dirs (b/226423379)")
+ for _, lib := range dep.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs {
+ if !android.InList(lib, usesLibrary.usesLibraryProperties.Missing_optional_uses_libs) {
+ usesLibrary.usesLibraryProperties.Missing_optional_uses_libs =
+ append(usesLibrary.usesLibraryProperties.Missing_optional_uses_libs, lib)
}
}
-
- return &javaResourcesAttributes{
- Resources: bazel.MakeLabelListAttribute(resources),
- Resource_strip_prefix: resourceStripPrefix,
- }
-}
-
-type javaCommonAttributes struct {
- *javaResourcesAttributes
- *kotlinAttributes
- Srcs bazel.LabelListAttribute
- Plugins bazel.LabelListAttribute
- Javacopts bazel.StringListAttribute
- Sdk_version bazel.StringAttribute
- Java_version bazel.StringAttribute
}
-type javaDependencyLabels struct {
- // Dependencies which DO NOT contribute to the API visible to upstream dependencies.
- Deps bazel.LabelListAttribute
- // Dependencies which DO contribute to the API visible to upstream dependencies.
- StaticDeps bazel.LabelListAttribute
-}
+type JavaApiContributionImport struct {
+ JavaApiContribution
-type eventLogTagsAttributes struct {
- Srcs bazel.LabelListAttribute
+ prebuilt android.Prebuilt
+ prebuiltProperties javaApiContributionImportProperties
}
-type aidlLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Tags bazel.StringListAttribute
-}
+type javaApiContributionImportProperties struct {
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
-type javaAidlLibraryAttributes struct {
- Deps bazel.LabelListAttribute
- Tags bazel.StringListAttribute
+ // Non-nil if this java_import module was dynamically created by a java_sdk_library_import
+ // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
+ // (without any prebuilt_ prefix)
+ Created_by_java_sdk_library_name *string `blueprint:"mutated"`
}
-// bp2BuildJavaInfo has information needed for the conversion of java*_modules
-// that is needed bor Bp2Build conversion but that requires different handling
-// depending on the module type.
-type bp2BuildJavaInfo struct {
- // separates dependencies into dynamic dependencies and static dependencies.
- DepLabels *javaDependencyLabels
- hasKotlin bool
-}
-
-// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
-// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
-// which has other non-attribute information needed for bp2build conversion
-// that needs different handling depending on the module types, and thus needs
-// to be returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) {
- var srcs bazel.LabelListAttribute
- var deps bazel.LabelListAttribute
- var staticDeps bazel.LabelList
-
- archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
- srcs.SetSelectValue(axis, config, archSrcs)
- }
- }
- }
- srcs.ResolveExcludes()
-
- javaSrcPartition := "java"
- protoSrcPartition := "proto"
- logtagSrcPartition := "logtag"
- aidlSrcPartition := "aidl"
- kotlinPartition := "kotlin"
- srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
- javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
- logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
- protoSrcPartition: android.ProtoSrcLabelPartition,
- aidlSrcPartition: android.AidlSrcLabelPartition,
- kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}},
- })
-
- javaSrcs := srcPartitions[javaSrcPartition]
- kotlinSrcs := srcPartitions[kotlinPartition]
- javaSrcs.Append(kotlinSrcs)
-
- if !srcPartitions[logtagSrcPartition].IsEmpty() {
- logtagsLibName := m.Name() + "_logtags"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "event_log_tags",
- Bzl_load_location: "//build/bazel/rules/java:event_log_tags.bzl",
- },
- android.CommonAttributes{Name: logtagsLibName},
- &eventLogTagsAttributes{
- Srcs: srcPartitions[logtagSrcPartition],
- },
- )
-
- logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
- javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
- }
-
- if !srcPartitions[aidlSrcPartition].IsEmpty() {
- aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool {
- return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
- })
-
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
-
- if !aidlSrcs.IsEmpty() {
- aidlLibName := m.Name() + "_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
- },
- android.CommonAttributes{Name: aidlLibName},
- &aidlLibraryAttributes{
- Srcs: aidlSrcs,
- Tags: apexAvailableTags,
- },
- )
- aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
- }
-
- javaAidlLibName := m.Name() + "_java_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "java_aidl_library",
- Bzl_load_location: "//build/bazel/rules/java:java_aidl_library.bzl",
- },
- android.CommonAttributes{Name: javaAidlLibName},
- &javaAidlLibraryAttributes{
- Deps: aidlLibs,
- Tags: apexAvailableTags,
- },
- )
-
- staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName})
- }
-
- var javacopts []string
- if m.properties.Javacflags != nil {
- javacopts = append(javacopts, m.properties.Javacflags...)
- }
-
- epEnabled := m.properties.Errorprone.Enabled
- //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
- if Bool(epEnabled) {
- javacopts = append(javacopts, m.properties.Errorprone.Javacflags...)
- }
-
- commonAttrs := &javaCommonAttributes{
- Srcs: javaSrcs,
- javaResourcesAttributes: m.convertJavaResourcesAttributes(ctx),
- Plugins: bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
- ),
- Javacopts: bazel.MakeStringListAttribute(javacopts),
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- }
-
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- var libLabels []bazel.Label
- for _, d := range archProps.Libs {
- neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
- neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
- libLabels = append(libLabels, neverlinkLabel)
- }
- deps.SetSelectValue(axis, config, bazel.MakeLabelList(libLabels))
- }
- }
- }
-
- protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
- // Soong does not differentiate between a java_library and the Bazel equivalent of
- // a java_proto_library + proto_library pair. Instead, in Soong proto sources are
- // listed directly in the srcs of a java_library, and the classes produced
- // by protoc are included directly in the resulting JAR. Thus upstream dependencies
- // that depend on a java_library with proto sources can link directly to the protobuf API,
- // and so this should be a static dependency.
- staticDeps.Add(protoDepLabel)
-
- depLabels := &javaDependencyLabels{}
- depLabels.Deps = deps
-
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- archStaticLibs := android.BazelLabelForModuleDeps(
- ctx,
- android.LastUniqueStrings(android.CopyOf(archProps.Static_libs)))
- depLabels.StaticDeps.SetSelectValue(axis, config, archStaticLibs)
- }
- }
- }
- depLabels.StaticDeps.Value.Append(staticDeps)
-
- hasKotlin := !kotlinSrcs.IsEmpty()
- commonAttrs.kotlinAttributes = &kotlinAttributes{
- Kotlincflags: &m.properties.Kotlincflags,
- }
- if len(m.properties.Common_srcs) != 0 {
- hasKotlin = true
- commonAttrs.kotlinAttributes.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
- }
-
- bp2BuildInfo := &bp2BuildJavaInfo{
- DepLabels: depLabels,
- hasKotlin: hasKotlin,
- }
-
- return commonAttrs, bp2BuildInfo
-}
-
-type javaLibraryAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
- Neverlink bazel.BoolAttribute
-}
-
-type kotlinAttributes struct {
- Common_srcs bazel.LabelListAttribute
- Kotlincflags *[]string
-}
-
-func ktJvmLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:rules.bzl",
- }
-}
-
-func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "java_library",
- Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
- }
-}
-
-func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
- commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- if !commonAttrs.Srcs.IsEmpty() {
- deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
- } else if !deps.IsEmpty() {
- ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
- }
- var props bazel.BazelTargetModuleProperties
- attrs := &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Exports: depLabels.StaticDeps,
- }
- name := m.Name()
-
- if !bp2BuildInfo.hasKotlin {
- props = javaLibraryBazelTargetModuleProperties()
- } else {
- props = ktJvmLibraryBazelTargetModuleProperties()
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
- neverlinkProp := true
- neverLinkAttrs := &javaLibraryAttributes{
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- },
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
-
-}
-
-type javaBinaryHostAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Runtime_deps bazel.LabelListAttribute
- Main_class string
- Jvm_flags bazel.StringListAttribute
-}
-
-// JavaBinaryHostBp2Build is for java_binary_host bp2build.
-func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
- commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
- if m.binaryProperties.Jni_libs != nil {
- deps.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs)))
- }
-
- var runtimeDeps bazel.LabelListAttribute
- if commonAttrs.Srcs.IsEmpty() {
- // if there are no sources, then the dependencies can only be used at runtime
- runtimeDeps = deps
- deps = bazel.LabelListAttribute{}
- }
-
- mainClass := ""
- if m.binaryProperties.Main_class != nil {
- mainClass = *m.binaryProperties.Main_class
- }
- if m.properties.Manifest != nil {
- mainClassInManifest, err := android.GetMainClassInManifest(ctx.Config(), android.PathForModuleSrc(ctx, *m.properties.Manifest).String())
- if err != nil {
- return
- }
- mainClass = mainClassInManifest
- }
-
- // Attribute jvm_flags
- var jvmFlags bazel.StringListAttribute
- if m.binaryProperties.Jni_libs != nil {
- jniLibPackages := map[string]bool{}
- for _, jniLibLabel := range android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs).Includes {
- jniLibPackage := jniLibLabel.Label
- indexOfColon := strings.Index(jniLibLabel.Label, ":")
- if indexOfColon > 0 {
- // JNI lib from other package
- jniLibPackage = jniLibLabel.Label[2:indexOfColon]
- } else if indexOfColon == 0 {
- // JNI lib in the same package of java_binary
- packageOfCurrentModule := m.GetBazelLabel(ctx, m)
- jniLibPackage = packageOfCurrentModule[2:strings.Index(packageOfCurrentModule, ":")]
- }
- if _, inMap := jniLibPackages[jniLibPackage]; !inMap {
- jniLibPackages[jniLibPackage] = true
- }
- }
- jniLibPaths := []string{}
- for jniLibPackage, _ := range jniLibPackages {
- // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH
- jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage)
- }
- jvmFlags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")})
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_binary",
- Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
- }
- binAttrs := &javaBinaryHostAttributes{
- Runtime_deps: runtimeDeps,
- Main_class: mainClass,
- Jvm_flags: jvmFlags,
- }
-
- if commonAttrs.Srcs.IsEmpty() {
- binAttrs.javaCommonAttributes = commonAttrs
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
- return
- }
-
- libName := m.Name() + "_lib"
- var libProps bazel.BazelTargetModuleProperties
- if bp2BuildInfo.hasKotlin {
- libProps = ktJvmLibraryBazelTargetModuleProperties()
- } else {
- libProps = javaLibraryBazelTargetModuleProperties()
- }
- libAttrs := &javaLibraryAttributes{
- Deps: deps,
- javaCommonAttributes: commonAttrs,
- }
-
- ctx.CreateBazelTargetModule(libProps, android.CommonAttributes{Name: libName}, libAttrs)
- binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
-
- // Create the BazelTargetModule.
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
-}
-
-type bazelJavaImportAttributes struct {
- Jars bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
+func ApiContributionImportFactory() android.Module {
+ module := &JavaApiContributionImport{}
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ android.InitPrebuiltModule(module, &[]string{""})
+ module.AddProperties(&module.properties, &module.prebuiltProperties)
+ module.AddProperties(&module.sdkLibraryComponentProperties)
+ return module
}
-// java_import bp2Build converter.
-func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- var jars bazel.LabelListAttribute
- archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*ImportProperties); ok {
- archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil))
- jars.SetSelectValue(axis, config, archJars)
- }
- }
- }
-
- attrs := &bazelJavaImportAttributes{
- Jars: jars,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_import",
- Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
- }
-
- name := android.RemoveOptionalPrebuiltPrefix(i.Name())
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
-
- neverlink := true
- neverlinkAttrs := &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
- },
- }
- ctx.CreateBazelTargetModule(
- javaLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: name + "-neverlink"},
- neverlinkAttrs)
-
+func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt {
+ return &module.prebuilt
}
-var _ android.MixedBuildBuildable = (*Import)(nil)
-
-func (i *Import) getBazelModuleLabel(ctx android.BaseModuleContext) string {
- return android.RemoveOptionalPrebuiltPrefixFromBazelLabel(i.GetBazelLabel(ctx, i))
+func (module *JavaApiContributionImport) Name() string {
+ return module.prebuilt.Name(module.ModuleBase.Name())
}
-func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- i.commonBuildActions(ctx)
-
- bazelCtx := ctx.Config().BazelContext
- filePaths, err := bazelCtx.GetOutputFiles(i.getBazelModuleLabel(ctx), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- bazelJars := android.Paths{}
- for _, bazelOutputFile := range filePaths {
- bazelJars = append(bazelJars, android.PathForBazelOut(ctx, bazelOutputFile))
- }
-
- jarName := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ".jar"
- outputFile := android.PathForModuleOut(ctx, "bazelCombined", jarName)
- TransformJarsToJar(ctx, outputFile, "combine prebuilt jars", bazelJars,
- android.OptionalPath{}, // manifest
- false, // stripDirEntries
- []string{}, // filesToStrip
- []string{}, // dirsToStrip
- )
- i.combinedClasspathFile = outputFile
-
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile),
- ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
- ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile),
- //TODO(b/240308299) include AIDL information from Bazel
- })
-
- i.maybeInstall(ctx, jarName, outputFile)
+func (j *JavaApiContributionImport) BaseModuleName() string {
+ return proptools.StringDefault(j.prebuiltProperties.Source_module_name, j.ModuleBase.Name())
}
-func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(i.getBazelModuleLabel(ctx), cquery.GetOutputFiles, android.GetConfigKey(ctx))
+func (j *JavaApiContributionImport) CreatedByJavaSdkLibraryName() *string {
+ return j.prebuiltProperties.Created_by_java_sdk_library_name
}
-func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
+func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index 0c002f385..33079f381 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -24,8 +24,10 @@ import (
"strings"
"testing"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "android/soong/aconfig"
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -47,10 +49,8 @@ var prepareForJavaTest = android.GroupFixturePreparers(
cc.PrepareForTestWithCcBuildComponents,
// Include all the default java modules.
PrepareForTestWithDexpreopt,
- PrepareForTestWithOverlayBuildComponents,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
- }),
+ // Include aconfig modules.
+ aconfig.PrepareForTestWithAconfigBuildComponents,
)
func TestMain(m *testing.M) {
@@ -529,6 +529,15 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
}
}
+// A minimal context object for use with DexJarBuildPath
+type moduleErrorfTestCtx struct {
+}
+
+func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
+}
+
+var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil)
+
func TestPrebuilts(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -579,10 +588,11 @@ func TestPrebuilts(t *testing.T) {
javac := fooModule.Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
barModule := ctx.ModuleForTests("bar", "android_common")
- barJar := barModule.Rule("combineJar").Output
+ barJar := barModule.Output("combined/bar.jar").Output
bazModule := ctx.ModuleForTests("baz", "android_common")
bazJar := bazModule.Rule("combineJar").Output
- sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
+ sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").
+ Output("combined/sdklib.stubs.jar").Output
fooLibrary := fooModule.Module().(*Library)
assertDeepEquals(t, "foo unique sources incorrect",
@@ -596,7 +606,8 @@ func TestPrebuilts(t *testing.T) {
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
}
- barDexJar := barModule.Module().(*Import).DexJarBuildPath()
+ errCtx := moduleErrorfTestCtx{}
+ barDexJar := barModule.Module().(*Import).DexJarBuildPath(errCtx)
if barDexJar.IsSet() {
t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
}
@@ -609,7 +620,7 @@ func TestPrebuilts(t *testing.T) {
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
}
- bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path()
+ bazDexJar := bazModule.Module().(*Import).DexJarBuildPath(errCtx).Path()
expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
@@ -619,8 +630,6 @@ func TestPrebuilts(t *testing.T) {
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0]
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
- entries = android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests("sdklib", "android_common").Module())[0]
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_sdk_library_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
}
func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
@@ -1027,7 +1036,7 @@ func TestExcludeFileGroupInSrcs(t *testing.T) {
}
}
-func TestJavaLibrary(t *testing.T) {
+func TestJavaLibraryOutputFiles(t *testing.T) {
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_library {
@@ -1044,7 +1053,7 @@ func TestJavaLibrary(t *testing.T) {
})
}
-func TestJavaImport(t *testing.T) {
+func TestJavaImportOutputFiles(t *testing.T) {
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_import {
@@ -1060,6 +1069,85 @@ func TestJavaImport(t *testing.T) {
})
}
+func TestJavaImport(t *testing.T) {
+ bp := `
+ java_library {
+ name: "source_library",
+ srcs: ["source.java"],
+ }
+
+ java_import {
+ name: "import_with_no_deps",
+ jars: ["no_deps.jar"],
+ }
+
+ java_import {
+ name: "import_with_source_deps",
+ jars: ["source_deps.jar"],
+ static_libs: ["source_library"],
+ }
+
+ java_import {
+ name: "import_with_import_deps",
+ jars: ["import_deps.jar"],
+ static_libs: ["import_with_no_deps"],
+ }
+ `
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ source := ctx.ModuleForTests("source_library", "android_common")
+ sourceJar := source.Output("javac/source_library.jar")
+ sourceHeaderJar := source.Output("turbine-combined/source_library.jar")
+ sourceJavaInfo, _ := android.SingletonModuleProvider(ctx, source.Module(), JavaInfoProvider)
+
+ // The source library produces separate implementation and header jars
+ android.AssertPathsRelativeToTopEquals(t, "source library implementation jar",
+ []string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "source library header jar",
+ []string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars)
+
+ importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common")
+ importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
+ importWithNoDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
+
+ // An import with no deps produces a single jar used as both the header and implementation jar.
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar",
+ []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar",
+ []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs",
+ []string{"no_deps.jar"}, importWithNoDepsJar.Inputs)
+
+ importWithSourceDeps := ctx.ModuleForTests("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.SingletonModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
+
+ // An import with source deps produces separate header and implementation jars.
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar",
+ []string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar",
+ []string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs",
+ []string{"source_deps.jar", sourceJar.Output.String()}, importWithSourceDepsJar.Inputs)
+ 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")
+ importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
+ importWithImportDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
+
+ // An import with only import deps produces a single jar used as both the header and implementation jar.
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar",
+ []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar",
+ []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs",
+ []string{"import_deps.jar", importWithNoDepsJar.Output.String()}, importWithImportDepsJar.Inputs)
+}
+
var compilerFlagsTestCases = []struct {
in string
out bool
@@ -1206,7 +1294,7 @@ func TestPatchModule(t *testing.T) {
expected := "java.base=.:out/soong"
checkPatchModuleFlag(t, ctx, "bar", expected)
expected = "java.base=" + strings.Join([]string{
- ".", "out/soong", "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
+ ".", "out/soong", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
checkPatchModuleFlag(t, ctx, "baz", expected)
})
}
@@ -1291,43 +1379,6 @@ func TestAidlExportIncludeDirsFromImports(t *testing.T) {
}
}
-func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
- // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
- t.Skip("Re-enable once filegroups are corrected for mixed builds")
- bp := `
- filegroup {
- name: "foo_aidl",
- srcs: ["aidl/foo/IFoo.aidl"],
- path: "aidl/foo",
- bazel_module: { label: "//:foo_aidl" },
- }
- java_library {
- name: "foo",
- srcs: [":foo_aidl"],
- }
-`
-
- outBaseDir := "out/bazel/output"
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.PrepareForTestWithFilegroup,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToOutputFiles: map[string][]string{
- "//:foo_aidl": []string{"aidl/foo/IFoo.aidl"},
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- aidlCommand := result.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
- expectedAidlFlag := "-I" + outBaseDir + "/execroot/__main__/aidl/foo"
- if !strings.Contains(aidlCommand, expectedAidlFlag) {
- t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
- }
-}
-
func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -1744,85 +1795,6 @@ func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
}
}
-func TestImportMixedBuild(t *testing.T) {
- bp := `
- java_import {
- name: "baz",
- jars: [
- "test1.jar",
- "test2.jar",
- ],
- bazel_module: { label: "//foo/bar:baz" },
- }
- `
-
- ctx := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:baz": []string{"test1.jar", "test2.jar"},
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- bazMod := ctx.ModuleForTests("baz", "android_common").Module()
- producer := bazMod.(android.OutputFileProducer)
- expectedOutputFiles := []string{".intermediates/baz/android_common/bazelCombined/baz.jar"}
-
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting java_import outputfiles %s", err)
- }
- actualOutputFiles := android.NormalizePathsForTesting(outputFiles)
- android.AssertDeepEquals(t, "Output files are produced", expectedOutputFiles, actualOutputFiles)
-
- javaInfoProvider := ctx.ModuleProvider(bazMod, JavaInfoProvider)
- javaInfo, ok := javaInfoProvider.(JavaInfo)
- if !ok {
- t.Error("could not get JavaInfo from java_import module")
- }
- android.AssertDeepEquals(t, "Header JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.HeaderJars))
- android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
- android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
-}
-
-func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) {
- bazelOutputBaseDir := filepath.Join("out", "bazel")
- result := android.GroupFixturePreparers(
- PrepareForIntegrationTestWithJava,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: bazelOutputBaseDir,
- }
- }),
- ).RunTest(t)
-
- ctx := &android.TestPathContext{TestResult: result}
-
- srcDirectory := filepath.Join("frameworks", "base")
- srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java")
- bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory)
- bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded)
- srcs := android.Paths{
- android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"),
- }
- dirsAlreadyIncluded := android.Paths{
- android.PathForTesting(srcDirectoryAlreadyIncluded),
- }
-
- expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base"
- flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded)
- if flags != expectedFlags {
- t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
- }
-}
-
func TestDeviceBinaryWrapperGeneration(t *testing.T) {
// Scenario 1: java_binary has main_class property in its bp
ctx, _ := testJava(t, `
@@ -1847,15 +1819,24 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) {
}
func TestJavaApiContributionEmptyApiFile(t *testing.T) {
- testJavaError(t,
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
"Error: foo has an empty api file.",
- `java_api_contribution {
+ )).RunTestWithBp(t, `
+ java_api_contribution {
name: "foo",
}
java_api_library {
name: "bar",
api_surface: "public",
api_contributions: ["foo"],
+ stubs_type: "everything",
}
`)
}
@@ -1864,32 +1845,44 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
+ stubs_type: "everything",
}
java_api_library {
name: "bar2",
api_surface: "system",
api_contributions: ["foo1", "foo2"],
- api_files: ["api1/current.txt", "api2/current.txt"]
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- })
+ `)
testcases := []struct {
moduleName string
@@ -1897,17 +1890,17 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
}{
{
moduleName: "bar1",
- sourceTextFileDirs: []string{"a/foo1.txt"},
+ sourceTextFileDirs: []string{"a/current.txt"},
},
{
moduleName: "bar2",
- sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt", "api1/current.txt", "api2/current.txt"},
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
},
}
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
@@ -1918,28 +1911,47 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_c := `
java_api_contribution {
name: "foo3",
- api_file: "foo3.txt",
+ api_file: "system-current.txt",
+ api_surface: "system",
}
`
provider_bp_d := `
java_api_contribution {
name: "foo4",
- api_file: "foo4.txt",
+ api_file: "system-current.txt",
+ api_surface: "system",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(provider_bp_c),
+ "d/Android.bp": []byte(provider_bp_d),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_defaults {
name: "baz1",
api_surface: "public",
@@ -1956,12 +1968,14 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
+ stubs_type: "everything",
}
java_api_library {
name: "bar2",
api_surface: "public",
defaults:["baz1"],
+ stubs_type: "everything",
}
java_api_library {
@@ -1969,15 +1983,9 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
api_surface: "system",
defaults:["baz1", "baz2"],
api_contributions: ["foo4"],
- api_files: ["api1/current.txt", "api2/current.txt"]
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(provider_bp_c),
- "d/Android.bp": []byte(provider_bp_d),
- })
+ `)
testcases := []struct {
moduleName string
@@ -1985,21 +1993,22 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
}{
{
moduleName: "bar1",
- sourceTextFileDirs: []string{"a/foo1.txt"},
+ sourceTextFileDirs: []string{"a/current.txt"},
},
{
moduleName: "bar2",
- sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
},
{
- moduleName: "bar3",
- sourceTextFileDirs: []string{"c/foo3.txt", "a/foo1.txt", "b/foo2.txt", "d/foo4.txt", "api1/current.txt", "api2/current.txt"},
+ moduleName: "bar3",
+ // API text files need to be sorted from the narrower api scope to the wider api scope
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"},
},
}
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
@@ -2010,32 +2019,45 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
+ stubs_type: "everything",
}
java_api_library {
name: "bar2",
api_surface: "system",
api_contributions: ["foo1", "foo2"],
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- })
+ `)
testcases := []struct {
moduleName string
@@ -2063,13 +2085,15 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2085,12 +2109,30 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ "c/Lib.java": {},
+ "d/Android.bp": []byte(lib_bp_b),
+ "d/Lib.java": {},
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
libs: ["lib1"],
+ stubs_type: "everything",
}
java_api_library {
@@ -2098,16 +2140,9 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
api_surface: "system",
api_contributions: ["foo1", "foo2"],
libs: ["lib1", "lib2", "bar1"],
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- "c/Lib.java": {},
- "d/Android.bp": []byte(lib_bp_b),
- "d/Lib.java": {},
- })
+ `)
testcases := []struct {
moduleName string
@@ -2138,13 +2173,15 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2160,12 +2197,30 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ "c/Lib.java": {},
+ "d/Android.bp": []byte(lib_bp_b),
+ "d/Lib.java": {},
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
static_libs: ["lib1"],
+ stubs_type: "everything",
}
java_api_library {
@@ -2173,16 +2228,9 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
api_surface: "system",
api_contributions: ["foo1", "foo2"],
static_libs: ["lib1", "lib2", "bar1"],
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- "c/Lib.java": {},
- "d/Android.bp": []byte(lib_bp_b),
- "d/Lib.java": {},
- })
+ `)
testcases := []struct {
moduleName string
@@ -2208,17 +2256,19 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
}
}
-func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
+func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2226,30 +2276,62 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
name: "lib1",
api_surface: "public",
api_contributions: ["foo1", "foo2"],
+ stubs_type: "everything",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
- dep_api_srcs: "lib1",
+ full_api_surface_stub: "lib1",
+ stubs_type: "everything",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- })
+ `)
m := ctx.ModuleForTests("bar1", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
+ android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
+}
- android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
- android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
+func TestTransitiveSrcFiles(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "a",
+ srcs: ["a.java"],
+ }
+ java_library {
+ name: "b",
+ srcs: ["b.java"],
+ }
+ java_library {
+ name: "c",
+ srcs: ["c.java"],
+ libs: ["a"],
+ static_libs: ["b"],
+ }
+ `)
+ c := ctx.ModuleForTests("c", "android_common").Module()
+ javaInfo, _ := android.SingletonModuleProvider(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) {
@@ -2299,3 +2381,664 @@ java_test_host {
t.Errorf("Expected args[\"extraTestRunnerConfigs\"] to equal %q, was %q", expected, args["extraTestRunnerConfigs"])
}
}
+
+func TestJavaExcludeStaticLib(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "bar",
+ }
+ java_library {
+ name: "foo",
+ }
+ java_library {
+ name: "baz",
+ static_libs: [
+ "foo",
+ "bar",
+ ],
+ exclude_static_libs: [
+ "bar",
+ ],
+ }
+ `)
+
+ // "bar" not included as dependency of "baz"
+ CheckModuleDependencies(t, ctx, "baz", "android_common", []string{
+ `core-lambda-stubs`,
+ `ext`,
+ `foo`,
+ `framework`,
+ `stable-core-platform-api-stubs-system-modules`,
+ `stable.core.platform.api.stubs`,
+ })
+}
+
+func TestJavaLibraryWithResourcesStem(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ java_library {
+ name: "foo",
+ java_resource_dirs: ["test-jar"],
+ stem: "test",
+ }
+ `,
+ map[string][]byte{
+ "test-jar/test/resource.txt": nil,
+ })
+
+ m := ctx.ModuleForTests("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")
+ }
+}
+
+func TestHeadersOnly(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ headers_only: true,
+ }
+ `)
+
+ turbine := ctx.ModuleForTests("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")
+ android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
+}
+
+func TestJavaApiContributionImport(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: ["bar"],
+ stubs_type: "everything",
+ }
+ java_api_contribution_import {
+ name: "bar",
+ api_file: "current.txt",
+ api_surface: "public",
+ }
+ `)
+ m := ctx.ModuleForTests("foo", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+ sourceFilesFlag := "--source-files current.txt"
+ android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+}
+
+func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: [
+ "system-server-api-stubs-docs-non-updatable.api.contribution",
+ "test-api-stubs-docs-non-updatable.api.contribution",
+ "system-api-stubs-docs-non-updatable.api.contribution",
+ "module-lib-api-stubs-docs-non-updatable.api.contribution",
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ stubs_type: "everything",
+ }
+ `)
+ m := ctx.ModuleForTests("foo", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+
+ // Api files are sorted from the narrowest api scope to the widest api scope.
+ // test api and module lib api surface do not have subset/superset relationship,
+ // but they will never be passed as inputs at the same time.
+ sourceFilesFlag := "--source-files default/java/api/current.txt " +
+ "default/java/api/system-current.txt default/java/api/test-current.txt " +
+ "default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
+ android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
+}
+
+func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "A.java": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ }
+ java_system_modules {
+ name: "baz",
+ libs: ["bar"],
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["A.java"],
+ system_modules: "baz",
+ }
+ `)
+ m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+ classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar"
+ android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag)
+}
+
+func TestApiLibraryDroidstubsDependency(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "A.java": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: [
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ enable_validation: true,
+ stubs_type: "everything",
+ }
+ java_api_library {
+ name: "bar",
+ api_contributions: [
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ enable_validation: false,
+ stubs_type: "everything",
+ }
+ `)
+
+ currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp"
+ foo := result.ModuleForTests("foo", "android_common").Module().(*ApiLibrary)
+ fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ")
+ bar := result.ModuleForTests("bar", "android_common").Module().(*ApiLibrary)
+ barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ")
+ android.AssertStringDoesContain(t,
+ "Module expected to have validation",
+ fooValidationPathsString,
+ currentApiTimestampPath,
+ )
+ android.AssertStringDoesNotContain(t,
+ "Module expected to not have validation",
+ barValidationPathsString,
+ currentApiTimestampPath,
+ )
+}
+
+func TestDisableFromTextStubForCoverageBuild(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ PrepareForTestWithJacocoInstrumentation,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ config.SetBuildFromTextStub(true)
+ }),
+ android.FixtureModifyEnv(func(env map[string]string) {
+ env["EMMA_INSTRUMENT"] = "true"
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["A.java"],
+ }
+ `)
+ android.AssertBoolEquals(t, "stub module expected to depend on from-source stub",
+ true, CheckModuleHasDependency(t, result.TestContext,
+ apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+ apiScopePublic.sourceStubLibraryModuleName("foo")))
+
+ android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub",
+ false, CheckModuleHasDependency(t, result.TestContext,
+ apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+ apiScopePublic.apiLibraryModuleName("foo")))
+}
+
+func TestMultiplePrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ libs: ["bar"],
+ }
+
+ // multiple variations of dep
+ // source
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ }
+ // prebuilt "v2"
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ hasFileWithStem := func(m android.TestingModule, stem string) bool {
+ t.Helper()
+ for _, o := range m.AllOutputs() {
+ _, file := filepath.Split(o)
+ if file == stem+".jar" {
+ return true
+ }
+ }
+ return false
+ }
+
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedDependencyName string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "bar",
+ expectedDependencyName: "bar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar",
+ expectedDependencyName: "prebuilt_bar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar.v2",
+ expectedDependencyName: "prebuilt_bar.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).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")
+ 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
+ // The filename should be agnostic to source/prebuilt/prebuilt_version
+ android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar"))
+
+ // check LOCAL_MODULE of the selected module name
+ // the prebuilt should have the same LOCAL_MODULE when exported to make
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0]
+ android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
+ }
+}
+
+func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) {
+ bp := `
+ // multiple variations of platform_compat_config
+ // source
+ platform_compat_config {
+ name: "myconfig",
+ }
+ // prebuilt "v1"
+ prebuilt_platform_compat_config {
+ name: "myconfig",
+ metadata: "myconfig.xml",
+ }
+ // prebuilt "v2"
+ prebuilt_platform_compat_config {
+ name: "myconfig.v2",
+ source_module_name: "myconfig", // without source_module_name, the singleton will merge two .xml files
+ metadata: "myconfig.v2.xml",
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedPlatformCompatConfigXml string
+ }{
+ {
+ desc: "Source platform_compat_config is selected using apex_contributions",
+ selectedDependencyName: "myconfig",
+ expectedPlatformCompatConfigXml: "out/soong/.intermediates/myconfig/android_common/myconfig_meta.xml",
+ },
+ {
+ desc: "Prebuilt platform_compat_config v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_myconfig",
+ expectedPlatformCompatConfigXml: "myconfig.xml",
+ },
+ {
+ desc: "Prebuilt platform_compat_config v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_myconfig.v2",
+ expectedPlatformCompatConfigXml: "myconfig.v2.xml",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithPlatformCompatConfig,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "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")
+ 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) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ java_api_contribution {
+ name: "baz",
+ api_file: "a/current.txt",
+ api_surface: "public",
+ }
+ java_api_library {
+ name: "foo",
+ api_surface: "public",
+ api_contributions: [
+ "baz",
+ ],
+ aconfig_declarations: [
+ "bar",
+ ],
+ stubs_type: "exportable",
+ enable_validation: false,
+ }
+ `)
+
+ // Check if java_api_library depends on aconfig_declarations
+ android.AssertBoolEquals(t, "foo expected to depend on bar",
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
+
+ m := result.ModuleForTests("foo", "android_common")
+ android.AssertStringDoesContain(t, "foo generates revert annotations file",
+ strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+
+ // revert-annotations.txt passed to exportable stubs generation metalava command
+ manifest := m.Output("metalava.sbox.textproto")
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
+ android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
+}
+
+func TestTestOnly(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ // These should be test-only
+ java_library {
+ name: "lib1-test-only",
+ srcs: ["a.java"],
+ test_only: true,
+ }
+ java_test {
+ name: "java-test",
+ }
+ java_test_host {
+ name: "java-test-host",
+ }
+ java_test_helper_library {
+ name: "helper-library",
+ }
+ java_binary {
+ name: "java-data-binary",
+ srcs: ["foo.java"],
+ main_class: "foo.bar.jb",
+ test_only: true,
+ }
+
+ // These are NOT
+ java_library {
+ name: "lib2-app",
+ srcs: ["b.java"],
+ }
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ }
+ java_binary {
+ name: "java-binary",
+ srcs: ["foo.java"],
+ main_class: "foo.bar.jb",
+ }
+ `)
+
+ expectedTestOnlyModules := []string{
+ "lib1-test-only",
+ "java-test",
+ "java-test-host",
+ "helper-library",
+ "java-data-binary",
+ }
+ expectedTopLevelTests := []string{
+ "java-test",
+ "java-test-host",
+ }
+ assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests)
+}
+
+// Don't allow setting test-only on things that are always tests or never tests.
+func TestInvalidTestOnlyTargets(t *testing.T) {
+ 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"], } `,
+ ` java_test_import { name: "java-test-import", test_only: true, } `,
+ ` java_api_library { name: "java-api-library", test_only: true, } `,
+ ` java_test_helper_library { name: "test-help-lib", test_only: true, } `,
+ ` java_defaults { name: "java-defaults", test_only: true, } `,
+ }
+
+ for i, bp := range testCases {
+ android.GroupFixturePreparers(prepareForJavaTest).
+ ExtendWithErrorHandler(
+ expectOneError("unrecognized property \"test_only\"",
+ fmt.Sprintf("testcase: %d", i))).
+ RunTestWithBp(t, bp)
+ }
+}
+
+// Expect exactly one that matches 'expected'.
+// Append 'msg' to the Errorf that printed.
+func expectOneError(expected string, msg string) android.FixtureErrorHandler {
+ return android.FixtureCustomErrorHandler(func(t *testing.T, result *android.TestResult) {
+ t.Helper()
+ if len(result.Errs) != 1 {
+ t.Errorf("Expected exactly one error, but found: %d when setting test_only on: %s", len(result.Errs), msg)
+ return
+ }
+ actualErrMsg := result.Errs[0].Error()
+ if !strings.Contains(actualErrMsg, expected) {
+ t.Errorf("Different error than expected. Received: [%v] on %s expected: %s", actualErrMsg, msg, expected)
+ }
+ })
+}
+
+func TestJavaLibHostWithStem(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library_host {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ }
+ `)
+
+ buildOS := ctx.Config().BuildOS.String()
+ foo := ctx.ModuleForTests("foo", buildOS+"_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.jar") {
+ t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+ }
+}
+
+func TestJavaLibWithStem(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ }
+ `)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.jar") {
+ t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+ }
+}
+
+func TestJavaLibraryOutputFilesRel(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ java_import {
+ name: "bar",
+ jars: ["bar.aar"],
+
+ }
+
+ java_import {
+ name: "baz",
+ jars: ["baz.aar"],
+ static_libs: ["bar"],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ bar := result.ModuleForTests("bar", "android_common")
+ baz := result.ModuleForTests("baz", "android_common")
+
+ fooOutputPaths := foo.OutputFiles(t, "")
+ barOutputPaths := bar.OutputFiles(t, "")
+ bazOutputPaths := baz.OutputFiles(t, "")
+
+ android.AssertPathsRelativeToTopEquals(t, "foo output path",
+ []string{"out/soong/.intermediates/foo/android_common/javac/foo.jar"}, fooOutputPaths)
+ android.AssertPathsRelativeToTopEquals(t, "bar output path",
+ []string{"out/soong/.intermediates/bar/android_common/combined/bar.jar"}, barOutputPaths)
+ android.AssertPathsRelativeToTopEquals(t, "baz output path",
+ []string{"out/soong/.intermediates/baz/android_common/combined/baz.jar"}, bazOutputPaths)
+
+ android.AssertStringEquals(t, "foo relative output path",
+ "foo.jar", fooOutputPaths[0].Rel())
+ android.AssertStringEquals(t, "bar relative output path",
+ "bar.jar", barOutputPaths[0].Rel())
+ android.AssertStringEquals(t, "baz relative output path",
+ "baz.jar", bazOutputPaths[0].Rel())
+}
+
+func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTestOnly []string, expectedTopLevel []string) {
+ t.Helper()
+ actualTrueModules := []string{}
+ actualTopLevelTests := []string{}
+ addActuals := func(m blueprint.Module, key blueprint.ProviderKey[android.TestModuleInformation]) {
+ if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, key); ok {
+ if provider.TestOnly {
+ actualTrueModules = append(actualTrueModules, m.Name())
+ }
+ if provider.TopLevelTarget {
+ actualTopLevelTests = append(actualTopLevelTests, m.Name())
+ }
+ }
+ }
+
+ ctx.VisitAllModules(func(m blueprint.Module) {
+ addActuals(m, android.TestOnlyProviderKey)
+
+ })
+
+ notEqual, left, right := android.ListSetDifference(expectedTestOnly, actualTrueModules)
+ if notEqual {
+ t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
+ }
+
+ notEqual, left, right = android.ListSetDifference(expectedTopLevel, actualTopLevelTests)
+ if notEqual {
+ t.Errorf("top-level: Expected but not found: %v, Found but not expected: %v", left, right)
+ }
+}
diff --git a/java/jdeps.go b/java/jdeps.go
index a52b86708..340026318 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -26,7 +26,7 @@ import (
// called. Dependency info file is generated in $OUT/module_bp_java_depend.json.
func init() {
- android.RegisterSingletonType("jdeps_generator", jDepsGeneratorSingleton)
+ android.RegisterParallelSingletonType("jdeps_generator", jDepsGeneratorSingleton)
}
func jDepsGeneratorSingleton() android.Singleton {
@@ -48,7 +48,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont
moduleInfos := make(map[string]android.IdeInfo)
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
@@ -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
@@ -89,8 +89,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont
dpInfo.Classes = append(dpInfo.Classes, data.Class)
}
- if ctx.ModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
dpInfo.Installed_paths = append(dpInfo.Installed_paths, dep.ImplementationJars.Strings()...)
}
dpInfo.Classes = android.FirstUniqueStrings(dpInfo.Classes)
diff --git a/java/kotlin.go b/java/kotlin.go
index 9bff5ea01..aa2db0ecd 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -30,7 +30,7 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports
blueprint.RuleParams{
Command: `rm -rf "$classesDir" "$headerClassesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
`mkdir -p "$classesDir" "$headerClassesDir" "$srcJarDir" "$emptyDir" && ` +
- `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+ `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
@@ -42,7 +42,7 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports
` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` +
`${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` +
- `rm -rf "$srcJarDir"`,
+ `rm -rf "$srcJarDir" "$classesDir" "$headerClassesDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
@@ -145,7 +145,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
`$kaptProcessorPath ` +
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
- `${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+ `${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
@@ -157,6 +157,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
+ Restat: true,
},
"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 6cb549eaf..4be7d0470 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -28,6 +28,7 @@ var legacyCorePlatformApiModules = []string{
"FloralClocks",
"framework-jobscheduler",
"framework-minus-apex",
+ "framework-minus-apex-headers",
"framework-minus-apex-intdefs",
"FrameworksCoreTests",
"HelloOslo",
diff --git a/java/lint.go b/java/lint.go
index 40ef48416..2eea07d31 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,7 +17,6 @@ package java
import (
"fmt"
"sort"
- "strconv"
"strings"
"github.com/google/blueprint/proptools"
@@ -56,7 +55,8 @@ type LintProperties struct {
// Modules that provide extra lint checks
Extra_check_modules []string
- // Name of the file that lint uses as the baseline. Defaults to "lint-baseline.xml".
+ // The lint baseline file to use. If specified, lint warnings listed in this file will be
+ // suppressed during lint checks.
Baseline_filename *string
// If true, baselining updatability lint checks (e.g. NewApi) is prohibited. Defaults to false.
@@ -66,6 +66,10 @@ type LintProperties struct {
// This will be true by default for test module types, false otherwise.
// If soong gets support for testonly, this flag should be replaced with that.
Test *bool
+
+ // Whether to ignore the exit code of Android lint. This is the --exit_code
+ // option. Defaults to false.
+ Suppress_exit_code *bool
}
}
@@ -80,15 +84,16 @@ type linter struct {
classes android.Path
extraLintCheckJars android.Paths
library bool
- minSdkVersion int
- targetSdkVersion int
- compileSdkVersion int
+ minSdkVersion android.ApiLevel
+ targetSdkVersion android.ApiLevel
+ compileSdkVersion android.ApiLevel
compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
outputs lintOutputs
properties LintProperties
extraMainlineLintErrors []string
+ compile_data android.Paths
reports android.Paths
@@ -117,18 +122,18 @@ type LintDepSetsIntf interface {
}
type LintDepSets struct {
- HTML, Text, XML *android.DepSet
+ HTML, Text, XML *android.DepSet[android.Path]
}
type LintDepSetsBuilder struct {
- HTML, Text, XML *android.DepSetBuilder
+ HTML, Text, XML *android.DepSetBuilder[android.Path]
}
func NewLintDepSetBuilder() LintDepSetsBuilder {
return LintDepSetsBuilder{
- HTML: android.NewDepSetBuilder(android.POSTORDER),
- Text: android.NewDepSetBuilder(android.POSTORDER),
- XML: android.NewDepSetBuilder(android.POSTORDER),
+ HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
}
}
@@ -314,25 +319,19 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru
cmd.FlagWithInput("@",
android.PathForSource(ctx, "build/soong/java/lint_defaults.txt"))
- if l.compileSdkKind == android.SdkPublic {
- cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors)
- } else {
- // TODO(b/268261262): Remove this branch. We're demoting NewApi to a warning due to pre-existing issues that need to be fixed.
- cmd.FlagForEachArg("--warning_check ", l.extraMainlineLintErrors)
- }
+ cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors)
cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks)
cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks)
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- // TODO(b/193460475): Re-enable strict updatability linting
- //if l.GetStrictUpdatabilityLinting() {
- // // Verify the module does not baseline issues that endanger safe updatability.
- // if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() {
- // cmd.FlagWithInput("--baseline ", baselinePath.Path())
- // cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
- // }
- //}
+ if l.GetStrictUpdatabilityLinting() {
+ // Verify the module does not baseline issues that endanger safe updatability.
+ if l.properties.Lint.Baseline_filename != nil {
+ cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
+ }
+ }
return lintPaths{
projectXML: projectXMLPath,
@@ -352,33 +351,26 @@ func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleB
Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
- Textf(`echo " <uses-sdk android:minSdkVersion='%d' android:targetSdkVersion='%d'/>" &&`,
- l.minSdkVersion, l.targetSdkVersion).
+ Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
+ l.minSdkVersion.String(), l.targetSdkVersion.String()).
Text(`echo "</manifest>"`).
Text(") >").Output(manifestPath)
return manifestPath
}
-func (l *linter) getBaselineFilepath(ctx android.ModuleContext) android.OptionalPath {
- var lintBaseline android.OptionalPath
- if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" {
- if String(l.properties.Lint.Baseline_filename) != "" {
- // if manually specified, we require the file to exist
- lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename))
- } else {
- lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename)
- }
- }
- return lintBaseline
-}
-
func (l *linter) lint(ctx android.ModuleContext) {
if !l.enabled() {
return
}
- if l.minSdkVersion != l.compileSdkVersion {
+ for _, flag := range l.properties.Lint.Flags {
+ if strings.Contains(flag, "--disable") || strings.Contains(flag, "--enable") || strings.Contains(flag, "--check") {
+ ctx.PropertyErrorf("lint.flags", "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")
+ }
+ }
+
+ if l.minSdkVersion.CompareTo(l.compileSdkVersion) == -1 {
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
// Skip lint warning checks for NewApi warnings for libcore where they come from source
// files that reference the API they are adding (b/208656169).
@@ -408,8 +400,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
for _, extraLintCheckModule := range extraLintCheckModules {
- if ctx.OtherModuleHasProvider(extraLintCheckModule, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(extraLintCheckModule, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok {
l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
} else {
ctx.PropertyErrorf("lint.extra_check_modules",
@@ -444,7 +435,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
srcsList := android.PathForModuleOut(ctx, "lint", "lint-srcs.list")
srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
- rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList)
+ rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
lintPaths := l.writeLintProjectXML(ctx, rule, srcsList)
@@ -487,12 +478,13 @@ func (l *linter) lint(ctx android.ModuleContext) {
cmd.BuiltTool("lint").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "lint.jar")).
Flag("--quiet").
+ Flag("--include-aosp-issues").
FlagWithInput("--project ", lintPaths.projectXML).
FlagWithInput("--config ", lintPaths.configXML).
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
- FlagWithArg("--compile-sdk-version ", strconv.Itoa(l.compileSdkVersion)).
+ FlagWithArg("--compile-sdk-version ", l.compileSdkVersion.String()).
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
@@ -504,7 +496,8 @@ func (l *linter) lint(ctx android.ModuleContext) {
rule.Temporary(lintPaths.projectXML)
rule.Temporary(lintPaths.configXML)
- if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" {
+ suppressExitCode := BoolDefault(l.properties.Lint.Suppress_exit_code, false)
+ if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" && !suppressExitCode {
cmd.Flag("--exitcode")
}
@@ -512,9 +505,8 @@ func (l *linter) lint(ctx android.ModuleContext) {
cmd.FlagWithArg("--check ", checkOnly)
}
- lintBaseline := l.getBaselineFilepath(ctx)
- if lintBaseline.Valid() {
- cmd.FlagWithInput("--baseline ", lintBaseline.Path())
+ if l.properties.Lint.Baseline_filename != nil {
+ cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
}
cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -550,12 +542,16 @@ func (l *linter) lint(ctx android.ModuleContext) {
if l.buildModuleReportZip {
l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
}
+
+ // Create a per-module phony target to run the lint check.
+ phonyName := ctx.ModuleName() + "-lint"
+ ctx.Phony(phonyName, xml)
}
func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
- htmlList := depSets.HTML.ToSortedList()
- textList := depSets.Text.ToSortedList()
- xmlList := depSets.XML.ToSortedList()
+ htmlList := android.SortedUniquePaths(depSets.HTML.ToList())
+ textList := android.SortedUniquePaths(depSets.Text.ToList())
+ xmlList := android.SortedUniquePaths(depSets.XML.ToList())
if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 {
return nil
@@ -610,7 +606,7 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
apiVersionsDb := findModuleOrErr(ctx, files.apiVersionsModule)
if apiVersionsDb == nil {
if !ctx.Config().AllowMissingDependencies() {
- ctx.Errorf("lint: missing module api_versions_public")
+ ctx.Errorf("lint: missing module %s", files.apiVersionsModule)
}
return
}
@@ -618,7 +614,7 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
sdkAnnotations := findModuleOrErr(ctx, files.annotationsModule)
if sdkAnnotations == nil {
if !ctx.Config().AllowMissingDependencies() {
- ctx.Errorf("lint: missing module sdk-annotations.zip")
+ ctx.Errorf("lint: missing module %s", files.annotationsModule)
}
return
}
@@ -654,7 +650,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
}
if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
- apexInfo := ctx.ModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, m, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
// There are stray platform variants of modules in apexes that are not available for
// the platform, and they sometimes can't be built. Don't depend on them.
@@ -705,7 +701,7 @@ func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) {
var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
func init() {
- android.RegisterSingletonType("lint",
+ android.RegisterParallelSingletonType("lint",
func() android.Singleton { return &lintSingleton{} })
registerLintBuildComponents(android.InitRegistrationContext)
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 1bb49962c..b8ce95cc8 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -122,3 +122,17 @@
--warning_check RemoteViewLayout
--warning_check SupportAnnotationUsage
--warning_check UniqueConstants
+--warning_check UseSdkSuppress
+# TODO(b/303434307) The intent is for this to be set to error severity
+# once existing violations are cleaned up
+--warning_check FlaggedApi
+
+--warning_check ExactAlarm
+--warning_check ExpiredTargetSdkVersion
+--warning_check ForegroundServicePermission
+--warning_check ObsoleteSdkInt
+--warning_check ScheduleExactAlarm
+--warning_check StartActivityAndCollapseDeprecated
+--warning_check UnspecifiedRegisterReceiverFlag
+--warning_check WearMaterialTheme
+--warning_check WearStandaloneAppFlag
diff --git a/java/lint_test.go b/java/lint_test.go
index ec901aa70..b51753f71 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -21,7 +21,7 @@ import (
"android/soong/android"
)
-func TestJavaLint(t *testing.T) {
+func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -39,31 +39,9 @@ func TestJavaLint(t *testing.T) {
foo := ctx.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
- t.Error("did not pass --baseline flag")
- }
-}
-
-func TestJavaLintWithoutBaseline(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- java_library {
- name: "foo",
- srcs: [
- "a.java",
- "b.java",
- "c.java",
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- }
- `, map[string][]byte{})
-
- foo := ctx.ModuleForTests("foo", "android_common")
-
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if strings.Contains(*sboxProto.Commands[0].Command, "--baseline") {
- t.Error("passed --baseline flag for non existent file")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
+ t.Error("Passed --baseline flag when baseline_filename was not set")
}
}
@@ -108,14 +86,13 @@ func TestJavaLintUsesCorrectBpConfig(t *testing.T) {
foo := ctx.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
t.Error("did not use the correct file for baseline")
}
- if !strings.Contains(*sboxProto.Commands[0].Command, "--warning_check NewApi") {
- // TODO(b/268261262): Change this to check for --error_check
- t.Error("should check NewApi warnings")
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check NewApi") {
+ t.Error("should check NewApi errors")
}
if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check SomeCheck") {
@@ -175,52 +152,55 @@ func TestJavaLintBypassUpdatableChecks(t *testing.T) {
}
}
-// TODO(b/193460475): Re-enable this test
-//func TestJavaLintStrictUpdatabilityLinting(t *testing.T) {
-// bp := `
-// java_library {
-// name: "foo",
-// srcs: [
-// "a.java",
-// ],
-// static_libs: ["bar"],
-// min_sdk_version: "29",
-// sdk_version: "current",
-// lint: {
-// strict_updatability_linting: true,
-// },
-// }
-//
-// java_library {
-// name: "bar",
-// srcs: [
-// "a.java",
-// ],
-// min_sdk_version: "29",
-// sdk_version: "current",
-// }
-// `
-// fs := android.MockFS{
-// "lint-baseline.xml": nil,
-// }
-//
-// result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()).
-// RunTestWithBp(t, bp)
-//
-// foo := result.ModuleForTests("foo", "android_common")
-// sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
-// if !strings.Contains(*sboxProto.Commands[0].Command,
-// "--baseline lint-baseline.xml --disallowed_issues NewApi") {
-// t.Error("did not restrict baselining NewApi")
-// }
-//
-// bar := result.ModuleForTests("bar", "android_common")
-// sboxProto = android.RuleBuilderSboxProtoForTests(t, bar.Output("lint.sbox.textproto"))
-// if !strings.Contains(*sboxProto.Commands[0].Command,
-// "--baseline lint-baseline.xml --disallowed_issues NewApi") {
-// t.Error("did not restrict baselining NewApi")
-// }
-//}
+func TestJavaLintStrictUpdatabilityLinting(t *testing.T) {
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ static_libs: ["bar"],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ strict_updatability_linting: true,
+ baseline_filename: "lint-baseline.xml",
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ }
+ }
+ `
+ fs := android.MockFS{
+ "lint-baseline.xml": nil,
+ }
+
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()).
+ RunTestWithBp(t, bp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ t.Error("did not restrict baselining NewApi")
+ }
+
+ bar := result.ModuleForTests("bar", "android_common")
+ sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ t.Error("did not restrict baselining NewApi")
+ }
+}
func TestJavaLintDatabaseSelectionFull(t *testing.T) {
testCases := []struct {
@@ -276,9 +256,28 @@ func TestJavaLintDatabaseSelectionFull(t *testing.T) {
RunTestWithBp(t, thisBp)
foo := result.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ 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)
}
}
}
+
+func TestCantControlCheckSeverityWithFlags(t *testing.T) {
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ flags: ["--disabled", "NewApi"],
+ },
+ }
+ `
+ PrepareForTestWithJavaDefaultModules.
+ 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)
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 07fb92cfe..38553a61b 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -15,8 +15,6 @@
package java
import (
- "fmt"
-
"android/soong/android"
"android/soong/dexpreopt"
)
@@ -26,7 +24,7 @@ func init() {
}
func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonModuleType("platform_bootclasspath", platformBootclasspathFactory)
+ ctx.RegisterParallelSingletonModuleType("platform_bootclasspath", platformBootclasspathFactory)
}
// The tags used for the dependencies between the platform bootclasspath and any configured boot
@@ -73,8 +71,6 @@ func platformBootclasspathFactory() android.SingletonModule {
return m
}
-var _ android.OutputFileProducer = (*platformBootclasspathModule)(nil)
-
func (b *platformBootclasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) {
entries = append(entries, android.AndroidMkEntries{
Class: "FAKE",
@@ -86,21 +82,10 @@ func (b *platformBootclasspathModule) AndroidMkEntries() (entries []android.Andr
return
}
-// Make the hidden API files available from the platform-bootclasspath module.
-func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "hiddenapi-flags.csv":
- return android.Paths{b.hiddenAPIFlagsCSV}, nil
- case "hiddenapi-index.csv":
- return android.Paths{b.hiddenAPIIndexCSV}, nil
- case "hiddenapi-metadata.csv":
- return android.Paths{b.hiddenAPIMetadataCSV}, nil
- }
-
- return nil, fmt.Errorf("unknown tag %s", tag)
-}
-
func (b *platformBootclasspathModule) 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")
+
b.hiddenAPIDepsMutator(ctx)
if !dexpreopt.IsDex2oatNeeded(ctx) {
@@ -113,7 +98,7 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon
}
func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
@@ -123,16 +108,24 @@ func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpM
}
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies on all the modules configured in the "art" boot image.
- artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
- addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
+ // Add dependencies on all the ART jars.
+ global := dexpreopt.GetGlobalConfig(ctx)
+ addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art")
+ // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
+ addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
- // Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
- // not include modules configured in the "art" boot image.
+ // Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
+ // APEXes.
addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
- // Add dependencies on all the apex jars.
+ // Add dependencies on all the updatable jars, except the ART jars.
apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
+ apexes := []string{}
+ for i := 0; i < apexJars.Len(); i++ {
+ apexes = append(apexes, apexJars.Apex(i))
+ }
+ addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
+ // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
// Add dependencies on all the fragments.
@@ -173,6 +166,18 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo
allModules = append(allModules, apexModules...)
b.configuredModules = allModules
+ var transitiveSrcFiles android.Paths
+ for _, module := range allModules {
+ depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if depInfo.TransitiveSrcFiles != nil {
+ transitiveSrcFiles = append(transitiveSrcFiles, depInfo.TransitiveSrcFiles.ToList()...)
+ }
+ }
+ jarArgs := resourcePathsToJarArgs(transitiveSrcFiles)
+ jarArgs = append(jarArgs, "-srcjar") // Move srcfiles to the right package
+ srcjar := android.PathForModuleOut(ctx, ctx.ModuleName()+"-transitive.srcjar").OutputPath
+ TransformResourcesToJar(ctx, srcjar, jarArgs, transitiveSrcFiles)
+
// Gather all the fragments dependencies.
b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
@@ -186,8 +191,10 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo
bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
- b.generateBootImageBuildActions(ctx)
- b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
+ ctx.SetOutputFiles(android.Paths{b.hiddenAPIFlagsCSV}, "hiddenapi-flags.csv")
+ ctx.SetOutputFiles(android.Paths{b.hiddenAPIIndexCSV}, "hiddenapi-index.csv")
+ ctx.SetOutputFiles(android.Paths{b.hiddenAPIMetadataCSV}, "hiddenapi-metadata.csv")
+ ctx.SetOutputFiles(android.Paths{srcjar}, ".srcjar")
}
// Generate classpaths.proto config
@@ -196,6 +203,7 @@ func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx and
// ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH
classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+ b.classpathFragmentBase().installClasspathProto(ctx)
}
func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
@@ -205,7 +213,7 @@ func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext)
// Include jars from APEXes that don't populate their classpath proto config.
remainingJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
for _, fragment := range b.fragments {
- info := ctx.OtherModuleProvider(fragment, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo)
+ info, _ := android.OtherModuleProvider(ctx, fragment, ClasspathFragmentProtoContentInfoProvider)
if info.ClasspathFragmentProtoGenerated {
remainingJars = remainingJars.RemoveList(info.ClasspathFragmentProtoContents)
}
@@ -218,7 +226,8 @@ func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext)
}
func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) android.ConfiguredJarList {
- return defaultBootImageConfig(ctx).modules.RemoveList(artBootImageConfig(ctx).modules)
+ global := dexpreopt.GetGlobalConfig(ctx)
+ return global.BootJars.RemoveList(global.ArtApexJars)
}
// checkPlatformModules ensures that the non-updatable modules supplied are not part of an
@@ -226,7 +235,7 @@ func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) andr
func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.Module) {
// TODO(satayev): change this check to only allow core-icu4j, all apex jars should not be here.
for _, m := range modules {
- apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
@@ -240,7 +249,7 @@ func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleCon
// checkApexModules ensures that the apex modules supplied are not from the platform.
func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext, modules []android.Module) {
for _, m := range modules {
- apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// ok: this jar is part of an updatable apex
@@ -267,6 +276,15 @@ 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 {
+ createEmptyHiddenApiFiles := func() {
+ paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
+ for _, path := range paths {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: path,
+ })
+ }
+ }
// Save the paths to the monolithic files for retrieval via OutputFiles().
b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags
@@ -275,17 +293,11 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
bootDexJarByModule := extractBootDexJarsFromModules(ctx, modules)
- // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true. This is a performance
+ // Don't run any hiddenapi rules if hidden api checks are disabled. This is a performance
// optimization that can be used to reduce the incremental build time but as its name suggests it
// can be unsafe to use, e.g. when the changes affect anything that goes on the bootclasspath.
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
- paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
- for _, path := range paths {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Touch,
- Output: path,
- })
- }
+ if ctx.Config().DisableHiddenApiChecks() {
+ createEmptyHiddenApiFiles()
return bootDexJarByModule
}
@@ -298,6 +310,13 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
// the fragments will have already provided the flags that are needed.
classesJars := monolithicInfo.ClassesJars
+ if len(classesJars) == 0 {
+ // This product does not include any monolithic jars. Monolithic hiddenapi flag generation is not required.
+ // However, generate an empty file so that the dist tags in f/b/boot/Android.bp can be resolved, and `m dist` works.
+ createEmptyHiddenApiFiles()
+ return bootDexJarByModule
+ }
+
// Create the input to pass to buildRuleToGenerateHiddenAPIStubFlagsFile
input := newHiddenAPIFlagInput()
@@ -374,7 +393,7 @@ func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ct
monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, classpathElements)
// Store the information for testing.
- ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)
+ android.SetProvider(ctx, MonolithicHiddenAPIInfoProvider, monolithicInfo)
return monolithicInfo
}
@@ -398,79 +417,3 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make
// INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
}
-
-// generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext) {
- // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
- // GenerateSingletonBuildActions method as it cannot create it for itself.
- dexpreopt.GetGlobalSoongConfig(ctx)
-
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return
- }
-
- frameworkBootImageConfig := defaultBootImageConfig(ctx)
- bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
- b.generateBootImage(ctx, frameworkBootImageName)
- b.generateBootImage(ctx, mainlineBootImageName)
- dumpOatRules(ctx, frameworkBootImageConfig)
-}
-
-func (b *platformBootclasspathModule) generateBootImage(ctx android.ModuleContext, imageName string) {
- imageConfig := genBootImageConfigs(ctx)[imageName]
-
- modules := b.getModulesForImage(ctx, imageConfig)
-
- // Copy module dex jars to their predefined locations.
- bootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, modules)
- copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
-
- // Build a profile for the image config and then use that to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
-
- // If dexpreopt of boot image jars should be skipped, generate only a profile.
- global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisablePreoptBootImages {
- return
- }
-
- // Build boot image files for the android variants.
- androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
- // Zip the android variant boot image files up.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
-
- // Build boot image files for the host variants. There are use directly by ART host side tests.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-}
-
-// Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps.
-func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) {
- config := GetApexBootConfig(ctx)
- apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules)
- copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule)
-}
-
-func (b *platformBootclasspathModule) getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []android.Module {
- modules := make([]android.Module, 0, imageConfig.modules.Len())
- for i := 0; i < imageConfig.modules.Len(); i++ {
- found := false
- for _, module := range b.configuredModules {
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- if name == imageConfig.modules.Jar(i) {
- modules = append(modules, module)
- found = true
- break
- }
- }
- if !found && !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf(
- "Boot image '%s' module '%s' not added as a dependency of platform_bootclasspath",
- imageConfig.name,
- imageConfig.modules.Jar(i))
- return []android.Module{}
- }
- }
- return modules
-}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index ff2da4bb2..0d2acaea0 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -81,6 +81,15 @@ func TestPlatformBootclasspath(t *testing.T) {
RunTest(t)
})
+ fooSourceSrc := "source/a.java"
+ barSrc := "a.java"
+
+ checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) {
+ t.Helper()
+ srcjar := result.ModuleForTests(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) {
result := android.GroupFixturePreparers(
preparer,
@@ -91,6 +100,10 @@ func TestPlatformBootclasspath(t *testing.T) {
"platform:foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ fooSourceSrc,
+ barSrc,
+ })
})
t.Run("prebuilt", func(t *testing.T) {
@@ -103,6 +116,10 @@ func TestPlatformBootclasspath(t *testing.T) {
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
t.Run("source+prebuilt - source preferred", func(t *testing.T) {
@@ -116,6 +133,10 @@ func TestPlatformBootclasspath(t *testing.T) {
"platform:foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ fooSourceSrc,
+ barSrc,
+ })
})
t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) {
@@ -129,6 +150,10 @@ func TestPlatformBootclasspath(t *testing.T) {
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
t.Run("dex import", func(t *testing.T) {
@@ -146,6 +171,10 @@ func TestPlatformBootclasspath(t *testing.T) {
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
}
@@ -324,7 +353,7 @@ func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) {
// All the intermediate rules use the same inputs.
expectedIntermediateInputs := `
- out/soong/.intermediates/bar/android_common/javac/bar.jar
+ out/soong/.intermediates/bar.impl/android_common/javac/bar.jar
out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
out/soong/.intermediates/foo/android_common/javac/foo.jar
`
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index d41729150..67ed84e1d 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -15,11 +15,12 @@
package java
import (
- "fmt"
"path/filepath"
"android/soong/android"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -36,7 +37,7 @@ var CompatConfigSdkMemberType = &compatConfigMemberType{
}
func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
+ ctx.RegisterParallelSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory)
ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
@@ -59,6 +60,8 @@ type platformCompatConfig struct {
installDirPath android.InstallPath
configFile android.OutputPath
metadataFile android.OutputPath
+
+ installConfigFile android.InstallPath
}
func (p *platformCompatConfig) compatConfigMetadata() android.Path {
@@ -104,21 +107,15 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon
FlagWithOutput("--merged-config ", p.metadataFile)
p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
+ p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base())
rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
-
+ ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile)
}
func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "ETC",
OutputFile: android.OptionalPathForPath(p.configFile),
- Include: "$(BUILD_PREBUILT)",
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base())
- },
- },
}}
}
@@ -184,6 +181,11 @@ type prebuiltCompatConfigModule struct {
type prebuiltCompatConfigProperties struct {
Metadata *string `android:"path"`
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
@@ -198,6 +200,10 @@ func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path {
return module.metadataFile
}
+func (module *prebuiltCompatConfigModule) BaseModuleName() string {
+ return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
+}
+
var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -223,7 +229,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet
var compatConfigMetadata android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled() {
+ if !module.Enabled(ctx) {
return
}
if c, ok := module.(platformCompatConfigMetadataProvider); ok {
@@ -255,7 +261,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet
func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
if p.metadata != nil {
- ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String())
+ ctx.DistForGoal("droidcore", p.metadata)
}
}
@@ -273,32 +279,23 @@ type globalCompatConfig struct {
android.ModuleBase
properties globalCompatConfigProperties
-
- outputFilePath android.OutputPath
}
func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filename := String(c.properties.Filename)
inputPath := platformCompatConfigPath(ctx)
- c.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
+ outputFilePath := android.PathForModuleOut(ctx, filename).OutputPath
// This ensures that outputFilePath has the correct name for others to
// use, as the source file may have a different name.
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
- Output: c.outputFilePath,
+ Output: outputFilePath,
Input: inputPath,
})
-}
-func (h *globalCompatConfig) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return android.Paths{h.outputFilePath}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
+ ctx.SetOutputFiles(android.Paths{outputFilePath}, "")
}
// global_compat_config provides access to the merged compat config xml file generated by the build.
diff --git a/java/plugin.go b/java/plugin.go
index 731dfda00..9c4774a10 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -16,7 +16,6 @@ package java
import (
"android/soong/android"
- "android/soong/bazel"
)
func init() {
@@ -35,8 +34,6 @@ func PluginFactory() android.Module {
InitJavaModule(module, android.HostSupported)
- android.InitBazelModule(module)
-
return module
}
@@ -56,35 +53,3 @@ type PluginProperties struct {
// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
Generates_api *bool
}
-
-type pluginAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Processor_class *string
-}
-
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- pluginName := p.Name()
- commonAttrs, bp2BuildInfo := p.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
-
- var processorClass *string
- if p.pluginProperties.Processor_class != nil {
- processorClass = p.pluginProperties.Processor_class
- }
-
- attrs := &pluginAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Processor_class: processorClass,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_plugin",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: pluginName}, attrs)
-}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 206d99527..00613eee3 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -55,6 +55,11 @@ type prebuiltApisProperties struct {
// If set to true, compile dex for java_import modules. Defaults to false.
Imports_compile_dex *bool
+
+ // If set to true, allow incremental platform API of the form MM.m where MM is the major release
+ // version corresponding to the API level/SDK_INT and m is an incremental release version
+ // (e.g. API changes associated with QPR). Defaults to false.
+ Allow_incremental_platform_api *bool
}
type prebuiltApis struct {
@@ -69,6 +74,8 @@ func (module *prebuiltApis) GenerateAndroidBuildActions(ctx android.ModuleContex
// parsePrebuiltPath parses the relevant variables out of a variety of paths, e.g.
// <version>/<scope>/<module>.jar
// <version>/<scope>/api/<module>.txt
+// *Note when using incremental platform API, <version> may be of the form MM.m where MM is the
+// API level and m is an incremental release, otherwise <version> is a single integer corresponding to the API level only.
// extensions/<version>/<scope>/<module>.jar
// extensions/<version>/<scope>/api/<module>.txt
func parsePrebuiltPath(ctx android.LoadHookContext, p string) (module string, version string, scope string) {
@@ -90,8 +97,25 @@ func parsePrebuiltPath(ctx android.LoadHookContext, p string) (module string, ve
}
// parseFinalizedPrebuiltPath is like parsePrebuiltPath, but verifies the version is numeric (a finalized version).
-func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string) (module string, version int, scope string) {
+func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string, allowIncremental bool) (module string, version int, release int, scope string) {
module, v, scope := parsePrebuiltPath(ctx, p)
+ if allowIncremental {
+ parts := strings.Split(v, ".")
+ if len(parts) != 2 {
+ ctx.ModuleErrorf("Found unexpected version '%v' for incremental prebuilts - expect MM.m format for incremental API with both major (MM) an minor (m) revision.", v)
+ return
+ }
+ sdk, sdk_err := strconv.Atoi(parts[0])
+ qpr, qpr_err := strconv.Atoi(parts[1])
+ if sdk_err != nil || qpr_err != nil {
+ ctx.ModuleErrorf("Unable to read version number for incremental prebuilt api '%v'", v)
+ return
+ }
+ version = sdk
+ release = qpr
+ return
+ }
+ release = 0
version, err := strconv.Atoi(v)
if err != nil {
ctx.ModuleErrorf("Found finalized API files in non-numeric dir '%v'", v)
@@ -103,7 +127,6 @@ func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string) (module s
func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version string) string {
return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module)
}
-
func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) {
props := struct {
Name *string
@@ -111,13 +134,13 @@ func createImport(mctx android.LoadHookContext, module, scope, version, path, sd
Sdk_version *string
Installable *bool
Compile_dex *bool
- }{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version))
- props.Jars = append(props.Jars, path)
- props.Sdk_version = proptools.StringPtr(sdkVersion)
- props.Installable = proptools.BoolPtr(false)
- props.Compile_dex = proptools.BoolPtr(compileDex)
-
+ }{
+ Name: proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version)),
+ Jars: []string{path},
+ Sdk_version: proptools.StringPtr(sdkVersion),
+ Installable: proptools.BoolPtr(false),
+ Compile_dex: proptools.BoolPtr(compileDex),
+ }
mctx.CreateModule(ImportFactory, &props)
}
@@ -135,6 +158,34 @@ func createApiModule(mctx android.LoadHookContext, name string, path string) {
mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
}
+func createCombinedApiFilegroupModule(mctx android.LoadHookContext, name string, srcs []string) {
+ filegroupProps := struct {
+ Name *string
+ Srcs []string
+ }{}
+ filegroupProps.Name = proptools.StringPtr(name)
+
+ var transformedSrcs []string
+ for _, src := range srcs {
+ transformedSrcs = append(transformedSrcs, ":"+src)
+ }
+ filegroupProps.Srcs = transformedSrcs
+ mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
+}
+
+func createLatestApiModuleExtensionVersionFile(mctx android.LoadHookContext, name string, version string) {
+ genruleProps := struct {
+ Name *string
+ Srcs []string
+ Out []string
+ Cmd *string
+ }{}
+ genruleProps.Name = proptools.StringPtr(name)
+ genruleProps.Out = []string{name}
+ genruleProps.Cmd = proptools.StringPtr("echo " + version + " > $(out)")
+ mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
+}
+
func createEmptyFile(mctx android.LoadHookContext, name string) {
props := struct {
Name *string
@@ -216,6 +267,10 @@ func PrebuiltApiModuleName(module, scope, version string) string {
return module + ".api." + scope + "." + version
}
+func PrebuiltApiCombinedModuleName(module, scope, version string) string {
+ return module + ".api.combined." + scope + "." + version
+}
+
func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
// <apiver>/<scope>/api/<module>.txt
apiLevelFiles := globApiDirs(mctx, p, "api/*.txt")
@@ -224,37 +279,44 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
}
// Create modules for all (<module>, <scope, <version>) triplets,
+ allowIncremental := proptools.BoolDefault(p.properties.Allow_incremental_platform_api, false)
for _, f := range apiLevelFiles {
- module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
- createApiModule(mctx, PrebuiltApiModuleName(module, scope, strconv.Itoa(version)), f)
+ module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
+ if allowIncremental {
+ incrementalVersion := strconv.Itoa(version) + "." + strconv.Itoa(release)
+ createApiModule(mctx, PrebuiltApiModuleName(module, scope, incrementalVersion), f)
+ } else {
+ createApiModule(mctx, PrebuiltApiModuleName(module, scope, strconv.Itoa(version)), f)
+ }
}
// Figure out the latest version of each module/scope
type latestApiInfo struct {
module, scope, path string
- version int
+ version, release int
+ isExtensionApiFile bool
}
- getLatest := func(files []string) map[string]latestApiInfo {
+ getLatest := func(files []string, isExtensionApiFile bool) map[string]latestApiInfo {
m := make(map[string]latestApiInfo)
for _, f := range files {
- module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
+ module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
if strings.HasSuffix(module, "incompatibilities") {
continue
}
key := module + "." + scope
info, exists := m[key]
- if !exists || version > info.version {
- m[key] = latestApiInfo{module, scope, f, version}
+ if !exists || version > info.version || (version == info.version && release > info.release) {
+ m[key] = latestApiInfo{module, scope, f, version, release, isExtensionApiFile}
}
}
return m
}
- latest := getLatest(apiLevelFiles)
+ latest := getLatest(apiLevelFiles, false)
if p.properties.Extensions_dir != nil {
extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
- for k, v := range getLatest(extensionApiFiles) {
+ for k, v := range getLatest(extensionApiFiles, true) {
if _, exists := latest[k]; !exists {
mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
}
@@ -264,9 +326,17 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
}
// Sort the keys in order to make build.ninja stable
- for _, k := range android.SortedKeys(latest) {
+ sortedLatestKeys := android.SortedKeys(latest)
+
+ for _, k := range sortedLatestKeys {
info := latest[k]
name := PrebuiltApiModuleName(info.module, info.scope, "latest")
+ latestExtensionVersionModuleName := PrebuiltApiModuleName(info.module, info.scope, "latest.extension_version")
+ if info.isExtensionApiFile {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, strconv.Itoa(info.version))
+ } else {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, "-1")
+ }
createApiModule(mctx, name, info.path)
}
@@ -284,11 +354,38 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
}
}
// Create empty incompatibilities files for remaining modules
- for _, k := range android.SortedKeys(latest) {
+ // If the incompatibility module has been created, create a corresponding combined module
+ for _, k := range sortedLatestKeys {
if _, ok := incompatibilities[k]; !ok {
createEmptyFile(mctx, PrebuiltApiModuleName(latest[k].module+"-incompatibilities", latest[k].scope, "latest"))
}
}
+
+ // Create combined latest api and removed api files modules.
+ // The combined modules list all api files of the api scope and its subset api scopes.
+ for _, k := range sortedLatestKeys {
+ info := latest[k]
+ name := PrebuiltApiCombinedModuleName(info.module, info.scope, "latest")
+
+ // Iterate until the currentApiScope does not extend any other api scopes
+ // i.e. is not a superset of any other api scopes
+ // the relationship between the api scopes is defined in java/sdk_library.go
+ var srcs []string
+ currentApiScope := scopeByName[info.scope]
+ for currentApiScope != nil {
+ if _, ok := latest[fmt.Sprintf("%s.%s", info.module, currentApiScope.name)]; ok {
+ srcs = append(srcs, PrebuiltApiModuleName(info.module, currentApiScope.name, "latest"))
+ }
+ currentApiScope = currentApiScope.extends
+ }
+
+ // srcs is currently listed in the order from the widest api scope to the narrowest api scopes
+ // e.g. module lib -> system -> public
+ // In order to pass the files in metalava from the narrowest api scope to the widest api scope,
+ // the list has to be reversed.
+ android.ReverseSliceInPlace(srcs)
+ createCombinedApiFilegroupModule(mctx, name, srcs)
+ }
}
func createPrebuiltApiModules(mctx android.LoadHookContext) {
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 2b8435325..b6fb2c6bf 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -99,3 +99,26 @@ func TestPrebuiltApis_WithExtensions(t *testing.T) {
android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
}
+
+func TestPrebuiltApis_WithIncrementalApi(t *testing.T) {
+ runTestWithIncrementalApi := func() (foo_input, bar_input, baz_input string) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ FixtureWithPrebuiltIncrementalApis(map[string][]string{
+ "33.0": {"foo"},
+ "33.1": {"foo", "bar", "baz"},
+ "33.2": {"foo", "bar"},
+ "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()
+ return
+ }
+ // 33.1 is the latest for baz, 33.2 is the latest for both foo & bar
+ foo_input, bar_input, baz_input := runTestWithIncrementalApi()
+ android.AssertStringEquals(t, "Expected latest foo = api level 33.2", "prebuilts/sdk/33.2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = api level 33.2", "prebuilts/sdk/33.2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 33.1", "prebuilts/sdk/33.1/public/api/baz.txt", baz_input)
+}
diff --git a/java/proto.go b/java/proto.go
index c732d9842..e27ef2c41 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -19,9 +19,6 @@ import (
"strconv"
"android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
)
const (
@@ -141,57 +138,3 @@ func protoFlags(ctx android.ModuleContext, j *CommonProperties, p *android.Proto
return flags
}
-
-type protoAttributes struct {
- Deps bazel.LabelListAttribute
- Sdk_version bazel.StringAttribute
- Java_version bazel.StringAttribute
-}
-
-func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
- protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
- if !ok {
- return nil
- }
-
- typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
- var rule_class string
- suffix := "_java_proto"
- switch typ {
- case "nano":
- suffix += "_nano"
- rule_class = "java_nano_proto_library"
- case "micro":
- suffix += "_micro"
- rule_class = "java_micro_proto_library"
- case "lite":
- suffix += "_lite"
- rule_class = "java_lite_proto_library"
- case "stream":
- suffix += "_stream"
- rule_class = "java_stream_proto_library"
- case "full":
- rule_class = "java_proto_library"
- default:
- ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
- }
-
- protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"}
- protoAttrs := &protoAttributes{
- Deps: bazel.MakeSingleLabelListAttribute(protoLabel),
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- }
-
- name := m.Name() + suffix
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: rule_class,
- Bzl_load_location: "//build/bazel/rules/java:proto.bzl",
- },
- android.CommonAttributes{Name: name},
- protoAttrs)
-
- return &bazel.Label{Label: ":" + name}
-}
diff --git a/java/ravenwood.go b/java/ravenwood.go
new file mode 100644
index 000000000..908619d5f
--- /dev/null
+++ b/java/ravenwood.go
@@ -0,0 +1,278 @@
+// Copyright 2023 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 (
+ "android/soong/android"
+ "android/soong/tradefed"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterRavenwoodBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterRavenwoodBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("android_ravenwood_test", ravenwoodTestFactory)
+ ctx.RegisterModuleType("android_ravenwood_libgroup", ravenwoodLibgroupFactory)
+}
+
+var ravenwoodLibContentTag = dependencyTag{name: "ravenwoodlibcontent"}
+var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
+var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
+
+const ravenwoodUtilsName = "ravenwood-utils"
+const ravenwoodRuntimeName = "ravenwood-runtime"
+
+type ravenwoodLibgroupJniDepProviderInfo struct {
+ // All the jni_libs module names with transient dependencies.
+ names map[string]bool
+}
+
+var ravenwoodLibgroupJniDepProvider = blueprint.NewProvider[ravenwoodLibgroupJniDepProviderInfo]()
+
+func getLibPath(archType android.ArchType) string {
+ if archType.Multilib == "lib64" {
+ return "lib64"
+ }
+ return "lib"
+}
+
+type ravenwoodTestProperties struct {
+ Jni_libs []string
+}
+
+type ravenwoodTest struct {
+ Library
+
+ ravenwoodTestProperties ravenwoodTestProperties
+
+ testProperties testProperties
+ testConfig android.Path
+
+ forceOSType android.OsType
+ forceArchType android.ArchType
+}
+
+func ravenwoodTestFactory() android.Module {
+ module := &ravenwoodTest{}
+
+ module.addHostAndDeviceProperties()
+ module.AddProperties(&module.testProperties, &module.ravenwoodTestProperties)
+
+ module.Module.dexpreopter.isTest = true
+ module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+
+ module.testProperties.Test_suites = []string{
+ "general-tests",
+ "ravenwood-tests",
+ }
+ module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false)
+
+ InitJavaModule(module, android.DeviceSupported)
+ android.InitDefaultableModule(module)
+
+ return module
+}
+
+func (r *ravenwoodTest) InstallInTestcases() bool { return true }
+func (r *ravenwoodTest) InstallForceOS() (*android.OsType, *android.ArchType) {
+ return &r.forceOSType, &r.forceArchType
+}
+func (r *ravenwoodTest) TestSuites() []string {
+ return r.testProperties.Test_suites
+}
+
+func (r *ravenwoodTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ r.Library.DepsMutator(ctx)
+
+ // Generically depend on the runtime so that it's installed together with us
+ ctx.AddVariationDependencies(nil, ravenwoodRuntimeTag, ravenwoodRuntimeName)
+
+ // Directly depend on any utils so that we link against them
+ utils := ctx.AddVariationDependencies(nil, ravenwoodUtilsTag, ravenwoodUtilsName)[0]
+ if utils != nil {
+ for _, lib := range utils.(*ravenwoodLibgroup).ravenwoodLibgroupProperties.Libs {
+ ctx.AddVariationDependencies(nil, libTag, lib)
+ }
+ }
+
+ // Add jni libs
+ for _, lib := range r.ravenwoodTestProperties.Jni_libs {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
+ }
+}
+
+func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.forceOSType = ctx.Config().BuildOS
+ r.forceArchType = ctx.Config().BuildArch
+
+ 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: "${RavenwoodTestConfigTemplate}",
+ HostTemplate: "${RavenwoodTestConfigTemplate}",
+ })
+
+ r.Library.GenerateAndroidBuildActions(ctx)
+
+ // Start by depending on all files installed by dependencies
+ var installDeps android.InstallPaths
+
+ // All JNI libraries included in the runtime
+ var runtimeJniModuleNames map[string]bool
+
+ if utils := ctx.GetDirectDepsWithTag(ravenwoodUtilsTag)[0]; utils != nil {
+ for _, installFile := range utils.FilesToInstall() {
+ 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 runtime.FilesToInstall() {
+ 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.
+
+ // Also depend on our config
+ installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
+ installConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
+ installDeps = append(installDeps, installConfig)
+
+ // Depend on the JNI libraries, but don't install the ones that the runtime already
+ // contains.
+ soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
+ for _, jniLib := range collectTransitiveJniDeps(ctx) {
+ if _, ok := runtimeJniModuleNames[jniLib.name]; ok {
+ continue // Runtime already includes it.
+ }
+ installJni := ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
+ installDeps = append(installDeps, installJni)
+ }
+
+ // Install our JAR with all dependencies
+ ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
+}
+
+func (r *ravenwoodTest) AndroidMkEntries() []android.AndroidMkEntries {
+ entriesList := r.Library.AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.AddStrings("LOCAL_COMPATIBILITY_SUITE",
+ "general-tests", "ravenwood-tests")
+ if r.testConfig != nil {
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", r.testConfig)
+ }
+ })
+ return entriesList
+}
+
+type ravenwoodLibgroupProperties struct {
+ Libs []string
+
+ Jni_libs []string
+}
+
+type ravenwoodLibgroup struct {
+ android.ModuleBase
+
+ ravenwoodLibgroupProperties ravenwoodLibgroupProperties
+
+ forceOSType android.OsType
+ forceArchType android.ArchType
+}
+
+func ravenwoodLibgroupFactory() android.Module {
+ module := &ravenwoodLibgroup{}
+ module.AddProperties(&module.ravenwoodLibgroupProperties)
+
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+func (r *ravenwoodLibgroup) InstallInTestcases() bool { return true }
+func (r *ravenwoodLibgroup) InstallForceOS() (*android.OsType, *android.ArchType) {
+ return &r.forceOSType, &r.forceArchType
+}
+func (r *ravenwoodLibgroup) TestSuites() []string {
+ return []string{
+ "general-tests",
+ "ravenwood-tests",
+ }
+}
+
+func (r *ravenwoodLibgroup) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Always depends on our underlying libs
+ for _, lib := range r.ravenwoodLibgroupProperties.Libs {
+ ctx.AddVariationDependencies(nil, ravenwoodLibContentTag, lib)
+ }
+ for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
+ }
+}
+
+func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.forceOSType = ctx.Config().BuildOS
+ r.forceArchType = ctx.Config().BuildArch
+
+ // Collect the JNI dependencies, including the transitive deps.
+ jniDepNames := make(map[string]bool)
+ jniLibs := collectTransitiveJniDeps(ctx)
+
+ for _, jni := range jniLibs {
+ jniDepNames[jni.name] = true
+ }
+ android.SetProvider(ctx, ravenwoodLibgroupJniDepProvider, ravenwoodLibgroupJniDepProviderInfo{
+ names: jniDepNames,
+ })
+
+ // 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)
+ libJar := android.OutputFileForModule(ctx, libModule, "")
+ ctx.InstallFile(installPath, lib+".jar", libJar)
+ }
+ soInstallPath := android.PathForModuleInstall(ctx, r.BaseModuleName()).Join(ctx, getLibPath(r.forceArchType))
+
+ for _, jniLib := range jniLibs {
+ ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
+ }
+
+ // Normal build should perform install steps
+ ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
+}
+
+// collectTransitiveJniDeps returns all JNI dependencies, including transitive
+// ones, including NDK / stub libs. (Because Ravenwood has no "preinstalled" libraries)
+func collectTransitiveJniDeps(ctx android.ModuleContext) []jniLib {
+ libs, _ := collectJniDeps(ctx, true, false, nil)
+ return libs
+}
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
new file mode 100644
index 000000000..59612645c
--- /dev/null
+++ b/java/ravenwood_test.go
@@ -0,0 +1,186 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "runtime"
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareRavenwoodRuntime = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ RegisterRavenwoodBuildComponents(ctx)
+ }),
+ android.FixtureAddTextFile("ravenwood/Android.bp", `
+ cc_library_shared {
+ name: "ravenwood-runtime-jni1",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "ravenwood-runtime-jni2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libred",
+ shared_libs: [
+ "ravenwood-runtime-jni3",
+ ],
+ }
+ cc_library_shared {
+ name: "ravenwood-runtime-jni3",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ java_library_static {
+ name: "framework-minus-apex.ravenwood",
+ srcs: ["Framework.java"],
+ }
+ java_library_static {
+ name: "framework-services.ravenwood",
+ srcs: ["Services.java"],
+ }
+ java_library_static {
+ name: "framework-rules.ravenwood",
+ srcs: ["Rules.java"],
+ }
+ android_ravenwood_libgroup {
+ name: "ravenwood-runtime",
+ libs: [
+ "framework-minus-apex.ravenwood",
+ "framework-services.ravenwood",
+ ],
+ jni_libs: [
+ "ravenwood-runtime-jni1",
+ "ravenwood-runtime-jni2",
+ ],
+ }
+ android_ravenwood_libgroup {
+ name: "ravenwood-utils",
+ libs: [
+ "framework-rules.ravenwood",
+ ],
+ }
+ `),
+)
+
+var installPathPrefix = "out/soong/host/linux-x86/testcases"
+
+func TestRavenwoodRuntime(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ prepareRavenwoodRuntime,
+ ).RunTest(t)
+
+ // Verify that our runtime depends on underlying libs
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-minus-apex.ravenwood")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "framework-services.ravenwood")
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-runtime", "android_common", "ravenwood-runtime-jni")
+ 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.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")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
+ utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
+ utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
+}
+
+func TestRavenwoodTest(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ prepareRavenwoodRuntime,
+ ).RunTestWithBp(t, `
+ cc_library_shared {
+ name: "jni-lib1",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "jni-lib2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libblue",
+ shared_libs: [
+ "jni-lib3",
+ ],
+ }
+ cc_library_shared {
+ name: "jni-lib3",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libpink",
+ }
+ android_ravenwood_test {
+ name: "ravenwood-test",
+ srcs: ["Test.java"],
+ jni_libs: [
+ "jni-lib1",
+ "jni-lib2",
+ "ravenwood-runtime-jni2",
+ ],
+ sdk_version: "test_current",
+ }
+ `)
+
+ // Verify that our test depends on underlying libs
+ CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-buildtime")
+ 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")
+ classpath := module.Rule("javac").Args["classpath"]
+
+ // Verify that we're linking against test_current
+ android.AssertStringDoesContain(t, "classpath", classpath, "android_test_stubs_current.jar")
+ // Verify that we're linking against utils
+ android.AssertStringDoesContain(t, "classpath", classpath, "framework-rules.ravenwood.jar")
+ // Verify that we're *NOT* linking against runtime
+ android.AssertStringDoesNotContain(t, "classpath", classpath, "framework-minus-apex.ravenwood.jar")
+ android.AssertStringDoesNotContain(t, "classpath", classpath, "framework-services.ravenwood.jar")
+
+ // Verify that we've emitted test artifacts in expected location
+ outputJar := module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.jar")
+ module.Output(installPathPrefix + "/ravenwood-test/ravenwood-test.config")
+ module.Output(installPathPrefix + "/ravenwood-test/lib64/jni-lib1.so")
+ module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
+ module.Output(installPathPrefix + "/ravenwood-test/lib64/libpink.so")
+
+ // ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted.
+ for _, o := range module.AllOutputs() {
+ android.AssertStringDoesNotContain(t, "runtime libs shouldn't be included", o, "/ravenwood-test/lib64/ravenwood-runtime")
+ }
+
+ // Verify that we're going to install underlying libs
+ orderOnly := outputJar.OrderOnly.Strings()
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/framework-services.ravenwood.jar")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni1.so")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
+ android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar")
+}
diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go
deleted file mode 100644
index 6d5960157..000000000
--- a/java/resourceshrinker.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2022 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "android/soong/android"
-
- "github.com/google/blueprint"
-)
-
-var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
- blueprint.RuleParams{
- Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`,
- CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
- }, "raw_resources")
-
-func ShrinkResources(ctx android.ModuleContext, apk android.Path, outputFile android.WritablePath) {
- protoFile := android.PathForModuleOut(ctx, apk.Base()+".proto.apk")
- aapt2Convert(ctx, protoFile, apk, "proto")
- strictModeFile := android.PathForSource(ctx, "prebuilts/cmdline-tools/shrinker.xml")
- protoOut := android.PathForModuleOut(ctx, apk.Base()+".proto.out.apk")
- ctx.Build(pctx, android.BuildParams{
- Rule: shrinkResources,
- Input: protoFile,
- Output: protoOut,
- Args: map[string]string{
- "raw_resources": strictModeFile.String(),
- },
- })
- aapt2Convert(ctx, outputFile, protoOut, "binary")
-}
diff --git a/java/resourceshrinker_test.go b/java/resourceshrinker_test.go
deleted file mode 100644
index 3bbf11670..000000000
--- a/java/resourceshrinker_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2022 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "testing"
-
- "android/soong/android"
-)
-
-func TestShrinkResourcesArgs(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- ).RunTestWithBp(t, `
- android_app {
- name: "app_shrink",
- platform_apis: true,
- optimize: {
- shrink_resources: true,
- }
- }
-
- android_app {
- name: "app_no_shrink",
- platform_apis: true,
- optimize: {
- shrink_resources: false,
- }
- }
- `)
-
- appShrink := result.ModuleForTests("app_shrink", "android_common")
- appShrinkResources := appShrink.Rule("shrinkResources")
- android.AssertStringDoesContain(t, "expected shrinker.xml in app_shrink resource shrinker flags",
- appShrinkResources.Args["raw_resources"], "shrinker.xml")
-
- appNoShrink := result.ModuleForTests("app_no_shrink", "android_common")
- if appNoShrink.MaybeRule("shrinkResources").Rule != nil {
- t.Errorf("unexpected shrinkResources rule for app_no_shrink")
- }
-}
diff --git a/java/robolectric.go b/java/robolectric.go
index 008b8b1c9..4cad5b153 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -22,19 +22,24 @@ import (
"android/soong/android"
"android/soong/java/config"
+ "android/soong/testing"
"android/soong/tradefed"
"github.com/google/blueprint/proptools"
)
func init() {
- android.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
- android.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory)
+ RegisterRobolectricBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterRobolectricBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
+ ctx.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory)
}
var robolectricDefaultLibs = []string{
"mockito-robolectric-prebuilt",
- "truth-prebuilt",
+ "truth",
// TODO(ccross): this is not needed at link time
"junitxml",
}
@@ -45,6 +50,7 @@ const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
var (
roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
+ roboRuntimeOnlyTag = dependencyTag{name: "roboRuntimeOnlyTag"}
)
type robolectricProperties struct {
@@ -66,9 +72,14 @@ type robolectricProperties struct {
// 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 robolectri
+ // 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
+
+ // Use strict mode to limit access of Robolectric API directly. See go/roboStrictMode
+ Strict_mode *bool
+
+ Jni_libs []string
}
type robolectricTest struct {
@@ -111,7 +122,7 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
- } else {
+ } else if !proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
if proptools.Bool(r.robolectricProperties.Upstream) {
ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream")
} else {
@@ -119,12 +130,23 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
+ if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
+ ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
+ } else {
+ // opting out from strict mode, robolectric_non_strict_mode_permission lib should be added
+ ctx.AddVariationDependencies(nil, libTag, "robolectric_non_strict_mode_permission")
+ }
+
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
roboRuntimesTag, "robolectric-android-all-prebuilts")
+
+ for _, lib := range r.robolectricProperties.Jni_libs {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
+ }
}
func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -144,29 +166,37 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
roboTestConfig := android.PathForModuleGen(ctx, "robolectric").
Join(ctx, "com/android/tools/test_config.properties")
+ var ok bool
+ var instrumentedApp *AndroidApp
+
// TODO: this inserts paths to built files into the test, it should really be inserting the contents.
instrumented := ctx.GetDirectDepsWithTag(instrumentationForTag)
- if len(instrumented) != 1 {
+ if len(instrumented) == 1 {
+ instrumentedApp, ok = instrumented[0].(*AndroidApp)
+ if !ok {
+ ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app")
+ }
+ } else if !ctx.Config().AllowMissingDependencies() {
panic(fmt.Errorf("expected exactly 1 instrumented dependency, got %d", len(instrumented)))
}
- instrumentedApp, ok := instrumented[0].(*AndroidApp)
- if !ok {
- ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app")
- }
-
- r.manifest = instrumentedApp.mergedManifestFile
- r.resourceApk = instrumentedApp.outputFile
+ if instrumentedApp != nil {
+ r.manifest = instrumentedApp.mergedManifestFile
+ r.resourceApk = instrumentedApp.outputFile
- generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp)
- r.extraResources = android.Paths{roboTestConfig}
+ generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp)
+ r.extraResources = android.Paths{roboTestConfig}
+ }
r.Library.GenerateAndroidBuildActions(ctx)
roboSrcJar := android.PathForModuleGen(ctx, "robolectric", ctx.ModuleName()+".srcjar")
- r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp)
- r.roboSrcJar = roboSrcJar
+
+ if instrumentedApp != nil {
+ r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp)
+ r.roboSrcJar = roboSrcJar
+ }
roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar")
generateSameDirRoboTestConfigJar(ctx, roboTestConfigJar)
@@ -177,22 +207,31 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
// once the Make test runner is removed.
roboTestConfigJar,
r.outputFile,
- instrumentedApp.implementationAndResourcesJar,
}
- handleLibDeps := func(dep android.Module) {
- m := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
- r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ if instrumentedApp != nil {
+ combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar)
+ }
+
+ handleLibDeps := func(dep android.Module, runtimeOnly bool) {
+ m, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
+ if !runtimeOnly {
+ r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ }
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars...)
}
}
for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
- handleLibDeps(dep)
+ handleLibDeps(dep, false)
}
for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
- handleLibDeps(dep)
+ handleLibDeps(dep, false)
+ }
+ // handle the runtimeOnly tag for strict_mode
+ for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
+ handleLibDeps(dep, true)
}
r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
@@ -213,28 +252,42 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
r.tests = append(r.tests, s)
}
- r.data = append(r.data, r.manifest, r.resourceApk)
-
- runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag)
-
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
+ var installDeps android.InstallPaths
- installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk)
- installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest)
- installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
+ if r.manifest != nil {
+ r.data = append(r.data, r.manifest)
+ installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest)
+ installDeps = append(installDeps, installedManifest)
+ }
- var installDeps android.Paths
+ if r.resourceApk != nil {
+ r.data = append(r.data, r.resourceApk)
+ installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk)
+ installDeps = append(installDeps, installedResourceApk)
+ }
+
+ runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag)
for _, runtime := range runtimes.(*robolectricRuntimes).runtimes {
installDeps = append(installDeps, runtime)
}
- installDeps = append(installDeps, installedResourceApk, installedManifest, installedConfig)
+
+ installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
+ installDeps = append(installDeps, installedConfig)
for _, data := range android.PathsForModuleSrc(ctx, r.testProperties.Data) {
installedData := ctx.InstallFile(installPath, data.Rel(), data)
installDeps = append(installDeps, installedData)
}
+ soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
+ for _, jniLib := range collectTransitiveJniDeps(ctx) {
+ installJni := ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
+ installDeps = append(installDeps, installJni)
+ }
+
r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -281,12 +334,11 @@ func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile andr
func (r *robolectricTest) generateRoboSrcJar(ctx android.ModuleContext, outputFile android.WritablePath,
instrumentedApp *AndroidApp) {
- srcJarArgs := copyOf(instrumentedApp.srcJarArgs)
+ srcJarArgs := android.CopyOf(instrumentedApp.srcJarArgs)
srcJarDeps := append(android.Paths(nil), instrumentedApp.srcJarDeps...)
for _, m := range ctx.GetDirectDepsWithTag(roboCoverageLibsTag) {
- if ctx.OtherModuleHasProvider(m, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
srcJarArgs = append(srcJarArgs, dep.SrcJarArgs...)
srcJarDeps = append(srcJarDeps, dep.SrcJarDeps...)
}
@@ -340,7 +392,9 @@ func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, test
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
android.AndroidMkEmitAssignList(w, "LOCAL_JAVA_LIBRARIES", []string{module}, r.libs)
fmt.Fprintln(w, "LOCAL_TEST_PACKAGE :=", String(r.robolectricProperties.Instrumentation_for))
- fmt.Fprintln(w, "LOCAL_INSTRUMENT_SRCJARS :=", r.roboSrcJar.String())
+ if r.roboSrcJar != nil {
+ fmt.Fprintln(w, "LOCAL_INSTRUMENT_SRCJARS :=", r.roboSrcJar.String())
+ }
android.AndroidMkEmitAssignList(w, "LOCAL_ROBOTEST_FILES", tests)
if t := r.robolectricProperties.Test_options.Timeout; t != nil {
fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
diff --git a/java/robolectric_test.go b/java/robolectric_test.go
new file mode 100644
index 000000000..4775bac64
--- /dev/null
+++ b/java/robolectric_test.go
@@ -0,0 +1,98 @@
+// Copyright 2024 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 (
+ "runtime"
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareRobolectricRuntime = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ RegisterRobolectricBuildComponents(ctx)
+ }),
+ android.FixtureAddTextFile("robolectric/Android.bp", `
+ java_library {
+ name: "Robolectric_all-target_upstream",
+ srcs: ["Robo.java"]
+ }
+
+ java_library {
+ name: "mockito-robolectric-prebuilt",
+ srcs: ["Mockito.java"]
+ }
+
+ java_library {
+ name: "truth",
+ srcs: ["Truth.java"]
+ }
+
+ java_library {
+ name: "junitxml",
+ srcs: ["JUnitXml.java"]
+ }
+
+ java_library_host {
+ name: "robolectric-host-android_all",
+ srcs: ["Runtime.java"]
+ }
+
+ android_robolectric_runtimes {
+ name: "robolectric-android-all-prebuilts",
+ jars: ["android-all/Runtime.jar"],
+ lib: "robolectric-host-android_all",
+ }
+ `),
+)
+
+func TestRobolectricJniTest(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ prepareRobolectricRuntime,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "inst-target",
+ srcs: ["App.java"],
+ platform_apis: true,
+ }
+
+ cc_library_shared {
+ name: "jni-lib1",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+
+ android_robolectric_test {
+ name: "robo-test",
+ instrumentation_for: "inst-target",
+ srcs: ["FooTest.java"],
+ jni_libs: [
+ "jni-lib1"
+ ],
+ }
+ `)
+
+ 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.Output(installPathPrefix + "/robo-test/lib64/jni-lib1.so")
+}
diff --git a/java/rro.go b/java/rro.go
index 53faca069..0fc6e1c6f 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -122,6 +122,10 @@ func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext)
ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
+
+ for _, aconfig_declaration := range r.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -146,7 +150,15 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-category "+*r.overridableProperties.Category)
}
- r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...)
+ aconfigTextFilePaths := getAconfigFilePaths(ctx)
+ r.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: r,
+ enforceDefaultTargetSdkVersion: false,
+ extraLinkFlags: aaptLinkFlags,
+ aconfigTextFiles: aconfigTextFilePaths,
+ },
+ )
// Sign the built package
_, _, certificates := collectAppDeps(ctx, r, false, false)
@@ -165,6 +177,10 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
partition := rroPartition(ctx)
r.installDir = android.PathForModuleInPartitionInstall(ctx, partition, "overlay", String(r.properties.Theme))
ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile)
+
+ android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
+ AconfigTextFiles: aconfigTextFilePaths,
+ })
}
func (r *RuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
diff --git a/java/rro_test.go b/java/rro_test.go
index 8067a4703..742c83982 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -62,7 +62,6 @@ func TestRuntimeResourceOverlay(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
android.FixtureModifyConfig(android.SetKatiEnabledForTests),
fs.AddToFixture(),
).RunTestWithBp(t, bp)
@@ -330,7 +329,6 @@ func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.ProductResourceOverlays = productResourceOverlays
@@ -407,3 +405,51 @@ func TestRuntimeResourceOverlayPartition(t *testing.T) {
android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
}
}
+
+func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ runtime_resource_overlay {
+ name: "foo",
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ container: "com.android.foo",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := result.ModuleForTests("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,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
diff --git a/java/sdk.go b/java/sdk.go
index 8b4918add..4ef4ee251 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -17,8 +17,6 @@ package java
import (
"fmt"
"path/filepath"
- "sort"
- "strconv"
"android/soong/android"
"android/soong/java/config"
@@ -27,23 +25,33 @@ import (
)
func init() {
- android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
- android.RegisterSingletonType("sdk", sdkSingletonFactory)
+ android.RegisterParallelSingletonType("sdk", sdkSingletonFactory)
android.RegisterMakeVarsProvider(pctx, sdkMakeVars)
}
-var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey")
var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
-var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
-func UseApiFingerprint(ctx android.BaseModuleContext) bool {
- if ctx.Config().UnbundledBuild() &&
- !ctx.Config().AlwaysUsePrebuiltSdks() &&
- ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") {
- return true
+func UseApiFingerprint(ctx android.BaseModuleContext) (useApiFingerprint bool, fingerprintSdkVersion string, fingerprintDeps android.OutputPath) {
+ if ctx.Config().UnbundledBuild() && !ctx.Config().AlwaysUsePrebuiltSdks() {
+ apiFingerprintTrue := ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT")
+ dessertShaIsSet := ctx.Config().Getenv("UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA") != ""
+
+ // Error when both UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT and UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA are set
+ if apiFingerprintTrue && dessertShaIsSet {
+ ctx.ModuleErrorf("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT=true cannot be set alongside with UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA")
+ }
+
+ useApiFingerprint = apiFingerprintTrue || dessertShaIsSet
+ if apiFingerprintTrue {
+ fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", android.ApiFingerprintPath(ctx).String())
+ fingerprintDeps = android.ApiFingerprintPath(ctx)
+ }
+ if dessertShaIsSet {
+ fingerprintSdkVersion = ctx.Config().Getenv("UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA")
+ }
}
- return false
+ return useApiFingerprint, fingerprintSdkVersion, fingerprintDeps
}
func defaultJavaLanguageVersion(ctx android.EarlyModuleContext, s android.SdkSpec) javaVersion {
@@ -51,14 +59,18 @@ func defaultJavaLanguageVersion(ctx android.EarlyModuleContext, s android.SdkSpe
if err != nil {
ctx.PropertyErrorf("sdk_version", "%s", err)
}
- if sdk.FinalOrFutureInt() <= 23 {
- return JAVA_VERSION_7
- } else if sdk.FinalOrFutureInt() <= 29 {
+ if sdk.FinalOrFutureInt() <= 29 {
return JAVA_VERSION_8
} else if sdk.FinalOrFutureInt() <= 31 {
return JAVA_VERSION_9
} else if sdk.FinalOrFutureInt() <= 33 {
return JAVA_VERSION_11
+ } else if ctx.Config().TargetsJava21() {
+ // Temporary experimental flag to be able to try and build with
+ // java version 21 options. The flag, if used, just sets Java
+ // 21 as the default version, leaving any components that
+ // target an older version intact.
+ return JAVA_VERSION_21
} else {
return JAVA_VERSION_17
}
@@ -76,7 +88,8 @@ func systemModuleKind(sdkKind android.SdkKind, apiLevel android.ApiLevel) androi
// Core is by definition what is included in the system module for the public API so should
// just use its system modules.
systemModuleKind = android.SdkPublic
- } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest {
+ } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest ||
+ systemModuleKind == android.SdkTestFrameworksCore {
// The core system and test APIs are currently the same as the public API so they should use
// its system modules.
systemModuleKind = android.SdkPublic
@@ -148,10 +161,10 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext)
toModule := func(module string, aidl android.Path) sdkDep {
// Select the kind of system modules needed for the sdk version.
systemModulesKind := systemModuleKind(sdkVersion.Kind, android.FutureApiLevel)
- systemModules := android.JavaApiLibraryName(ctx.Config(), fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind))
+ systemModules := fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind)
return sdkDep{
useModule: true,
- bootclasspath: []string{module, android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+ bootclasspath: []string{module, config.DefaultLambdaStubsLibrary},
systemModules: systemModules,
java9Classpath: []string{module},
frameworkResModule: "framework-res",
@@ -192,64 +205,26 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext)
bootclasspath: corePlatformBootclasspathLibraries(ctx),
noFrameworksLibs: true,
}
- case android.SdkPublic, android.SdkSystem, android.SdkTest:
- return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
+ case android.SdkPublic, android.SdkSystem, android.SdkTest, android.SdkTestFrameworksCore:
+ return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), sdkFrameworkAidlPath(ctx))
case android.SdkCore:
return sdkDep{
useModule: true,
- bootclasspath: []string{android.SdkCore.JavaLibraryName(ctx.Config()), android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
- systemModules: android.JavaApiLibraryName(ctx.Config(), "core-public-stubs-system-modules"),
+ bootclasspath: []string{android.SdkCore.DefaultJavaLibraryName(), config.DefaultLambdaStubsLibrary},
+ systemModules: "core-public-stubs-system-modules",
noFrameworksLibs: true,
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), nonUpdatableFrameworkAidlPath(ctx))
+ return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), nonUpdatableFrameworkAidlPath(ctx))
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
+ return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), sdkFrameworkAidlPath(ctx))
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
}
-func sdkPreSingletonFactory() android.Singleton {
- return sdkPreSingleton{}
-}
-
-type sdkPreSingleton struct{}
-
-func (sdkPreSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil)
- if err != nil {
- ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error())
- }
-
- var sdkVersions []int
- for _, sdkJar := range sdkJars {
- dir := filepath.Base(filepath.Dir(filepath.Dir(sdkJar)))
- v, err := strconv.Atoi(dir)
- if scerr, ok := err.(*strconv.NumError); ok && scerr.Err == strconv.ErrSyntax {
- continue
- } else if err != nil {
- ctx.Errorf("invalid sdk jar %q, %s, %v", sdkJar, err.Error())
- }
- sdkVersions = append(sdkVersions, v)
- }
-
- sort.Ints(sdkVersions)
-
- ctx.Config().Once(sdkVersionsKey, func() interface{} { return sdkVersions })
-}
-
-func LatestSdkVersionInt(ctx android.EarlyModuleContext) int {
- sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
- latestSdkVersion := 0
- if len(sdkVersions) > 0 {
- latestSdkVersion = sdkVersions[len(sdkVersions)-1]
- }
- return latestSdkVersion
-}
-
func sdkSingletonFactory() android.Singleton {
return sdkSingleton{}
}
@@ -269,9 +244,9 @@ func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Create framework.aidl by extracting anything that implements android.os.Parcelable from the SDK stubs modules.
func createSdkFrameworkAidl(ctx android.SingletonContext) {
stubsModules := []string{
- android.SdkPublic.JavaLibraryName(ctx.Config()),
- android.SdkTest.JavaLibraryName(ctx.Config()),
- android.SdkSystem.JavaLibraryName(ctx.Config()),
+ android.SdkPublic.DefaultJavaLibraryName(),
+ android.SdkTest.DefaultJavaLibraryName(),
+ android.SdkSystem.DefaultJavaLibraryName(),
}
combinedAidl := sdkFrameworkAidlPath(ctx)
@@ -286,7 +261,7 @@ func createSdkFrameworkAidl(ctx android.SingletonContext) {
// Creates a version of framework.aidl for the non-updatable part of the platform.
func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
- stubsModules := []string{android.SdkModule.JavaLibraryName(ctx.Config())}
+ stubsModules := []string{android.SdkModule.DefaultJavaLibraryName()}
combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
tempPath := tempPathForRestat(ctx, combinedAidl)
@@ -303,8 +278,7 @@ func createFrameworkAidl(stubsModules []string, path android.WritablePath, ctx a
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
- if ctx.ModuleHasProvider(module, JavaInfoProvider) {
- j := ctx.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if j, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
name := ctx.ModuleName(module)
if i := android.IndexList(name, stubsModules); i != -1 {
stubsJars[i] = j.HeaderJars
@@ -368,7 +342,7 @@ func nonUpdatableFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
// Create api_fingerprint.txt
func createAPIFingerprint(ctx android.SingletonContext) {
- out := ApiFingerprintPath(ctx)
+ out := android.ApiFingerprintPath(ctx)
rule := android.NewRuleBuilder(pctx, ctx)
@@ -409,17 +383,11 @@ func createAPIFingerprint(ctx android.SingletonContext) {
rule.Build("api_fingerprint", "generate api_fingerprint.txt")
}
-func ApiFingerprintPath(ctx android.PathContext) android.OutputPath {
- return ctx.Config().Once(apiFingerprintPathKey, func() interface{} {
- return android.PathForOutput(ctx, "api_fingerprint.txt")
- }).(android.OutputPath)
-}
-
func sdkMakeVars(ctx android.MakeVarsContext) {
if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String())
- ctx.Strict("API_FINGERPRINT", ApiFingerprintPath(ctx).String())
+ ctx.Strict("API_FINGERPRINT", android.ApiFingerprintPath(ctx).String())
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 103f1ace7..1eb7ab834 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -15,6 +15,7 @@
package java
import (
+ "errors"
"fmt"
"path"
"path/filepath"
@@ -28,8 +29,8 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
+ "android/soong/etc"
)
const (
@@ -105,15 +106,18 @@ type apiScope struct {
// The name of the property in the java_sdk_library_import
propertyName string
- // The tag to use to depend on the stubs library module.
- stubsTag scopeDependencyTag
+ // The tag to use to depend on the prebuilt stubs library module
+ prebuiltStubsTag scopeDependencyTag
+
+ // The tag to use to depend on the everything stubs library module.
+ everythingStubsTag scopeDependencyTag
+
+ // The tag to use to depend on the exportable stubs library module.
+ exportableStubsTag scopeDependencyTag
// The tag to use to depend on the stubs source module (if separate from the API module).
stubsSourceTag scopeDependencyTag
- // The tag to use to depend on the API file generating module (if separate from the stubs source module).
- apiFileTag scopeDependencyTag
-
// The tag to use to depend on the stubs source and API module.
stubsSourceAndApiTag scopeDependencyTag
@@ -156,6 +160,9 @@ type apiScope struct {
// Whether the api scope can be treated as unstable, and should skip compat checks.
unstable bool
+
+ // Represents the SDK kind of this scope.
+ kind android.SdkKind
}
// Initialize a scope, creating and adding appropriate dependency tags
@@ -165,21 +172,26 @@ func initApiScope(scope *apiScope) *apiScope {
allScopeNames = append(allScopeNames, name)
scope.propertyName = strings.ReplaceAll(name, "-", "_")
scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
- scope.stubsTag = scopeDependencyTag{
+ scope.prebuiltStubsTag = scopeDependencyTag{
name: name + "-stubs",
apiScope: scope,
depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
}
+ scope.everythingStubsTag = scopeDependencyTag{
+ name: name + "-stubs-everything",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractEverythingStubsLibraryInfoFromDependency,
+ }
+ scope.exportableStubsTag = scopeDependencyTag{
+ name: name + "-stubs-exportable",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractExportableStubsLibraryInfoFromDependency,
+ }
scope.stubsSourceTag = scopeDependencyTag{
name: name + "-stubs-source",
apiScope: scope,
depInfoExtractor: (*scopePaths).extractStubsSourceInfoFromDep,
}
- scope.apiFileTag = scopeDependencyTag{
- name: name + "-api",
- apiScope: scope,
- depInfoExtractor: (*scopePaths).extractApiInfoFromDep,
- }
scope.stubsSourceAndApiTag = scopeDependencyTag{
name: name + "-stubs-source-and-api",
apiScope: scope,
@@ -229,10 +241,30 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string {
return ".stubs" + scope.moduleSuffix
}
+func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string {
+ return ".stubs.exportable" + scope.moduleSuffix
+}
+
+func (scope *apiScope) apiLibraryModuleName(baseName string) string {
+ return scope.stubsLibraryModuleName(baseName) + ".from-text"
+}
+
+func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string {
+ return scope.stubsLibraryModuleName(baseName) + ".from-source"
+}
+
+func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string {
+ return scope.exportableStubsLibraryModuleName(baseName) + ".from-source"
+}
+
func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
return baseName + scope.stubsLibraryModuleNameSuffix()
}
+func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string {
+ return baseName + scope.exportableStubsLibraryModuleNameSuffix()
+}
+
func (scope *apiScope) stubsSourceModuleName(baseName string) string {
return baseName + ".stubs.source" + scope.moduleSuffix
}
@@ -273,6 +305,27 @@ func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
return list
}
+// Method that maps the apiScopes properties to the index of each apiScopes elements.
+// apiScopes property to be used as the key can be specified with the input accessor.
+// Only a string property of apiScope can be used as the key of the map.
+func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
+ ret := make(map[string]int)
+ for i, scope := range scopes {
+ ret[accessor(scope)] = i
+ }
+ return ret
+}
+
+func (scopes apiScopes) ConvertStubsLibraryExportableToEverything(name string) string {
+ for _, scope := range scopes {
+ if strings.HasSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) {
+ return strings.TrimSuffix(name, scope.exportableStubsLibraryModuleNameSuffix()) +
+ scope.stubsLibraryModuleNameSuffix()
+ }
+ }
+ return name
+}
+
var (
scopeByName = make(map[string]*apiScope)
allScopeNames []string
@@ -289,6 +342,7 @@ var (
return &module.sdkLibraryProperties.Public
},
sdkVersion: "current",
+ kind: android.SdkPublic,
})
apiScopeSystem = initApiScope(&apiScope{
name: "system",
@@ -301,6 +355,7 @@ var (
moduleSuffix: ".system",
sdkVersion: "system_current",
annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)",
+ kind: android.SdkSystem,
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
@@ -314,6 +369,7 @@ var (
sdkVersion: "test_current",
annotation: "android.annotation.TestApi",
unstable: true,
+ kind: android.SdkTest,
})
apiScopeModuleLib = initApiScope(&apiScope{
name: "module-lib",
@@ -331,6 +387,7 @@ var (
moduleSuffix: ".module_lib",
sdkVersion: "module_current",
annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)",
+ kind: android.SdkModule,
})
apiScopeSystemServer = initApiScope(&apiScope{
name: "system-server",
@@ -361,14 +418,32 @@ var (
// com.android.* classes are okay in this interface"
"--hide", "InternalClasses",
},
+ kind: android.SdkSystemServer,
})
- allApiScopes = apiScopes{
+ AllApiScopes = apiScopes{
apiScopePublic,
apiScopeSystem,
apiScopeTest,
apiScopeModuleLib,
apiScopeSystemServer,
}
+ apiLibraryAdditionalProperties = map[string]struct {
+ FullApiSurfaceStubLib string
+ AdditionalApiContribution string
+ }{
+ "legacy.i18n.module.platform.api": {
+ FullApiSurfaceStubLib: "legacy.core.platform.api.stubs",
+ AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
+ },
+ "stable.i18n.module.platform.api": {
+ FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
+ AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
+ },
+ "conscrypt.module.platform.api": {
+ FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
+ AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution",
+ },
+ }
)
var (
@@ -424,6 +499,9 @@ type ApiScopeProperties struct {
// or the API file. They both have to use the same sdk_version as is used for
// compiling the implementation library.
Sdk_version *string
+
+ // Extra libs used when compiling stubs for this scope.
+ Libs []string
}
type sdkLibraryProperties struct {
@@ -460,9 +538,6 @@ type sdkLibraryProperties struct {
// of the API.
Api_packages []string
- // list of package names that must be hidden from the API
- Hidden_api_packages []string
-
// the relative path to the directory containing the api specification files.
// Defaults to "api".
Api_dir *string
@@ -569,8 +644,23 @@ type sdkLibraryProperties struct {
Api_lint struct {
// Enable api linting.
Enabled *bool
+
+ // If API lint is enabled, this flag controls whether a set of legitimate lint errors
+ // are turned off. The default is true.
+ 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
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
+
// TODO: determines whether to create HTML doc or not
// Html_doc *bool
}
@@ -596,6 +686,11 @@ type scopePaths struct {
// This is not the implementation jar, it still only contains stubs.
stubsDexJarPath OptionalDexJarPath
+ // The exportable dex jar for the stubs.
+ // This is not the implementation jar, it still only contains stubs.
+ // Includes unflagged apis and flagged apis enabled by release configurations.
+ exportableStubsDexJarPath OptionalDexJarPath
+
// The API specification file, e.g. system_current.txt.
currentApiFilePath android.OptionalPath
@@ -609,95 +704,144 @@ type scopePaths struct {
annotationsZip android.OptionalPath
// The path to the latest API file.
- latestApiPath android.OptionalPath
+ latestApiPaths android.Paths
// The path to the latest removed API file.
- latestRemovedApiPath android.OptionalPath
+ latestRemovedApiPaths android.Paths
}
func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
- if ctx.OtherModuleHasProvider(dep, JavaInfoProvider) {
- lib := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
libDep := dep.(UsesLibraryDependency)
- paths.stubsDexJarPath = libDep.DexJarBuildPath()
+ paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
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 {
+func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ paths.stubsHeaderPath = lib.HeaderJars
+ if !ctx.Config().ReleaseHiddenApiExportableStubs() {
+ paths.stubsImplPath = lib.ImplementationJars
+ }
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ return nil
+ } else {
+ return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
+ }
+}
+
+func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ paths.stubsImplPath = lib.ImplementationJars
+ }
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ 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 {
- action(apiStubsProvider)
+ err := action(apiStubsProvider)
+ if err != nil {
+ return err
+ }
return nil
} else {
- return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs")
+ return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs")
}
}
-func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider)) error {
+func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error {
if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
- action(apiStubsProvider)
+ err := action(apiStubsProvider)
+ if err != nil {
+ return err
+ }
return nil
} else {
return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
}
}
-func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) {
- paths.annotationsZip = android.OptionalPathForPath(provider.AnnotationsZip())
- paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath())
- paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath())
-}
+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)
-func (paths *scopePaths) extractApiInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
- paths.extractApiInfoFromApiStubsProvider(provider)
- })
+ combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr)
+
+ if combinedError == nil {
+ paths.annotationsZip = android.OptionalPathForPath(annotationsZip)
+ paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath)
+ paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath)
+ }
+ return combinedError
}
-func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider) {
- paths.stubsSrcJar = android.OptionalPathForPath(provider.StubsSrcJar())
+func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error {
+ stubsSrcJar, err := provider.StubsSrcJar(stubsType)
+ if err == nil {
+ paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar)
+ }
+ return err
}
func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) {
- paths.extractStubsSourceInfoFromApiStubsProviders(provider)
+ stubsType := Everything
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ stubsType = Exportable
+ }
+ return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error {
+ return paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType)
})
}
func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
- paths.extractApiInfoFromApiStubsProvider(provider)
- paths.extractStubsSourceInfoFromApiStubsProviders(provider)
+ stubsType := Everything
+ 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 errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
})
}
-func extractSingleOptionalOutputPath(dep android.Module) (android.OptionalPath, error) {
+func extractOutputPaths(dep android.Module) (android.Paths, error) {
var paths android.Paths
if sourceFileProducer, ok := dep.(android.SourceFileProducer); ok {
paths = sourceFileProducer.Srcs()
+ return paths, nil
} else {
- return android.OptionalPath{}, fmt.Errorf("module %q does not produce source files", dep)
- }
- if len(paths) != 1 {
- return android.OptionalPath{}, fmt.Errorf("expected one path from %q, got %q", dep, paths)
+ return nil, fmt.Errorf("module %q does not produce source files", dep)
}
- return android.OptionalPathForPath(paths[0]), nil
}
func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error {
- outputPath, err := extractSingleOptionalOutputPath(dep)
- paths.latestApiPath = outputPath
+ outputPaths, err := extractOutputPaths(dep)
+ paths.latestApiPaths = outputPaths
return err
}
func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error {
- outputPath, err := extractSingleOptionalOutputPath(dep)
- paths.latestRemovedApiPath = outputPath
+ outputPaths, err := extractOutputPaths(dep)
+ paths.latestRemovedApiPaths = outputPaths
return err
}
@@ -755,7 +899,30 @@ type commonToSdkLibraryAndImportProperties struct {
type commonSdkLibraryAndImportModule interface {
android.Module
- BaseModuleName() string
+ // Returns the name of the root java_sdk_library that creates the child stub libraries
+ // This is the `name` as it appears in Android.bp, and not the name in Soong's build graph
+ // (with the prebuilt_ prefix)
+ //
+ // e.g. in the following java_sdk_library_import
+ // java_sdk_library_import {
+ // name: "framework-foo.v1",
+ // source_module_name: "framework-foo",
+ // }
+ // the values returned by
+ // 1. Name(): prebuilt_framework-foo.v1 # unique
+ // 2. BaseModuleName(): framework-foo # the source
+ // 3. RootLibraryName: framework-foo.v1 # the undecordated `name` from Android.bp
+ RootLibraryName() string
+}
+
+func (m *SdkLibrary) RootLibraryName() string {
+ return m.BaseModuleName()
+}
+
+func (m *SdkLibraryImport) RootLibraryName() string {
+ // m.BaseModuleName refers to the source of the import
+ // use moduleBase.Name to get the name of the module as it appears in the .bp file
+ return m.ModuleBase.Name()
}
// Common code between sdk library and sdk library import
@@ -773,6 +940,14 @@ type commonToSdkLibraryAndImport struct {
// Functionality related to this being used as a component of a java_sdk_library.
EmbeddableSdkLibraryComponent
+
+ // Path to the header jars of the implementation library
+ // 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
}
func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
@@ -794,7 +969,7 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android
return false
}
- namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ namePtr := proptools.StringPtr(c.module.RootLibraryName())
c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
// Only track this sdk library if this can be used as a shared library.
@@ -819,29 +994,60 @@ func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.Mod
c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
}
+func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library {
+ return c.implLibraryModule
+}
+
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.module.BaseModuleName() + ".impl"
+ return c.module.RootLibraryName() + ".impl"
}
// Module name of the XML file for the lib
func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.module.BaseModuleName() + sdkXmlFileSuffix
+ return c.module.RootLibraryName() + sdkXmlFileSuffix
}
// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
}
+// Name of the java_library module that compiles the exportable stubs source.
+func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName)
+}
+
// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
- baseName := c.module.BaseModuleName()
+ baseName := c.module.RootLibraryName()
return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
}
+// Name of the java_api_library module that generates the from-text stubs source
+// and compiles to a jar file.
+func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return c.namingScheme.apiLibraryModuleName(apiScope, baseName)
+}
+
+// Name of the java_library module that compiles the stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
+}
+
// The component names for different outputs of the java_sdk_library.
//
// They are similar to the names used for the child modules it creates
@@ -877,57 +1083,26 @@ var tagSplitter = func() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
}()
-// For OutputFileProducer interface
-//
-// .<scope>.<component name>, for all ComponentNames (for example: .public.removed-api.txt)
-func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) {
- if groups := tagSplitter.FindStringSubmatch(tag); groups != nil {
- scopeName := groups[1]
- component := groups[2]
-
- if scope, ok := scopeByName[scopeName]; ok {
- paths := c.findScopePaths(scope)
- if paths == nil {
- return nil, fmt.Errorf("%q does not provide api scope %s", c.module.BaseModuleName(), scopeName)
- }
-
- switch component {
- case stubsSourceComponentName:
- if paths.stubsSrcJar.Valid() {
- return android.Paths{paths.stubsSrcJar.Path()}, nil
- }
-
- case apiTxtComponentName:
- if paths.currentApiFilePath.Valid() {
- return android.Paths{paths.currentApiFilePath.Path()}, nil
- }
-
- case removedApiTxtComponentName:
- if paths.removedApiFilePath.Valid() {
- return android.Paths{paths.removedApiFilePath.Path()}, nil
- }
-
- case annotationsComponentName:
- if paths.annotationsZip.Valid() {
- return android.Paths{paths.annotationsZip.Path()}, nil
- }
- }
-
- return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName)
- } else {
- return nil, fmt.Errorf("unknown scope %s in %s", scope, tag)
+func (module *commonToSdkLibraryAndImport) setOutputFiles(ctx android.ModuleContext) {
+ if module.doctagPaths != nil {
+ ctx.SetOutputFiles(module.doctagPaths, ".doctags")
+ }
+ for _, scopeName := range android.SortedKeys(scopeByName) {
+ paths := module.findScopePaths(scopeByName[scopeName])
+ if paths == nil {
+ continue
}
-
- } else {
- switch tag {
- case ".doctags":
- if c.doctagPaths != nil {
- return c.doctagPaths, nil
- } else {
- return nil, fmt.Errorf("no doctag_files specified on %s", c.module.BaseModuleName())
+ componentToOutput := map[string]android.OptionalPath{
+ stubsSourceComponentName: paths.stubsSrcJar,
+ apiTxtComponentName: paths.currentApiFilePath,
+ removedApiTxtComponentName: paths.removedApiFilePath,
+ annotationsComponentName: paths.annotationsZip,
+ }
+ for _, component := range android.SortedKeys(componentToOutput) {
+ if componentToOutput[component].Valid() {
+ ctx.SetOutputFiles(android.Paths{componentToOutput[component].Path()}, "."+scopeName+"."+component)
}
}
- return nil, nil
}
}
@@ -970,7 +1145,7 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.
// If a specific numeric version has been requested then use prebuilt versions of the sdk.
if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.module.BaseModuleName(), sdkVersion)
+ return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion)
}
paths := c.selectScopePaths(ctx, sdkVersion.Kind)
@@ -992,12 +1167,12 @@ func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleCon
paths := c.findClosestScopePath(apiScope)
if paths == nil {
var scopes []string
- for _, s := range allApiScopes {
+ for _, s := range AllApiScopes {
if c.findScopePaths(s) != nil {
scopes = append(scopes, s.name)
}
}
- ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.BaseModuleName(), scopes)
+ ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.RootLibraryName(), scopes)
return nil
}
@@ -1033,6 +1208,16 @@ func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleCon
}
// to satisfy SdkLibraryDependency interface
+func (c *commonToSdkLibraryAndImport) SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
+ paths := c.selectScopePaths(ctx, kind)
+ if paths == nil {
+ return makeUnsetDexJarPath()
+ }
+
+ return paths.exportableStubsDexJarPath
+}
+
+// to satisfy SdkLibraryDependency interface
func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath {
apiScope := sdkKindToApiScope(kind)
paths := c.findScopePaths(apiScope)
@@ -1049,7 +1234,7 @@ func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() in
SdkLibraryToImplicitlyTrack *string
}{}
- namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ namePtr := proptools.StringPtr(c.module.RootLibraryName())
componentProps.SdkLibraryName = namePtr
if c.sharedLibrary() {
@@ -1143,35 +1328,36 @@ type SdkLibraryDependency interface {
// class changes but it does not contain and implementation or JavaDoc.
SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
- // Get the implementation jars appropriate for the supplied sdk version.
- //
- // These are either the implementation jar for the whole sdk library or the implementation
- // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
- // they are identical to the corresponding header jars.
- SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
-
- // SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
- // tool which processes dex files.
+ // SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
+ // java_sdk_library_import module. It is needed by the hiddenapi processing tool which
+ // processes dex files.
SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+ // SdkApiExportableStubDexJar returns the exportable dex jar for the stubs for
+ // java_sdk_library module. It is needed by the hiddenapi processing tool which processes
+ // dex files.
+ SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+
// SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
// sharedLibrary returns true if this can be used as a shared library.
sharedLibrary() bool
+
+ getImplLibraryModule() *Library
}
type SdkLibrary struct {
Library
- android.BazelModuleBase
-
sdkLibraryProperties sdkLibraryProperties
// Map from api scope to the scope specific property structure.
scopeToProperties map[*apiScope]*ApiScopeProperties
commonToSdkLibraryAndImport
+
+ builtInstalledForApex []dexpreopterInstall
}
var _ SdkLibraryDependency = (*SdkLibrary)(nil)
@@ -1180,11 +1366,25 @@ func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
return module.sdkLibraryProperties.Generate_system_and_test_apis
}
+func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if module.implLibraryModule != nil {
+ return module.implLibraryModule.DexJarBuildPath(ctx)
+ }
+ return makeUnsetDexJarPath()
+}
+
+func (module *SdkLibrary) DexJarInstallPath() android.Path {
+ if module.implLibraryModule != nil {
+ return module.implLibraryModule.DexJarInstallPath()
+ }
+ return nil
+}
+
func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) apiScopes {
// Check to see if any scopes have been explicitly enabled. If any have then all
// must be.
anyScopesExplicitlyEnabled := false
- for _, scope := range allApiScopes {
+ for _, scope := range AllApiScopes {
scopeProperties := module.scopeToProperties[scope]
if scopeProperties.Enabled != nil {
anyScopesExplicitlyEnabled = true
@@ -1194,7 +1394,7 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
var generatedScopes apiScopes
enabledScopes := make(map[*apiScope]struct{})
- for _, scope := range allApiScopes {
+ for _, scope := range AllApiScopes {
scopeProperties := module.scopeToProperties[scope]
// If any scopes are explicitly enabled then ignore the legacy enabled status.
// This is to ensure that any new usages of this module type do not rely on legacy
@@ -1214,7 +1414,7 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
// Now check to make sure that any scope that is extended by an enabled scope is also
// enabled.
- for _, scope := range allApiScopes {
+ for _, scope := range AllApiScopes {
if _, ok := enabledScopes[scope]; ok {
extends := scope.extends
if extends != nil {
@@ -1231,6 +1431,10 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
+ CheckMinSdkVersion(ctx, &module.Library)
+}
+
+func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
isExternal := !module.depIsInSameApex(ctx, child)
@@ -1263,14 +1467,27 @@ func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
+var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{}
+
+// To satisfy the CopyDirectlyInAnyApexTag interface. Implementation library of the sdk library
+// in an apex is considered to be directly in the apex, as if it was listed in java_libs.
+func (t sdkLibraryComponentTag) CopyDirectlyInAnyApex() {}
+
+var _ android.CopyDirectlyInAnyApexTag = implLibraryTag
+
+func (t sdkLibraryComponentTag) InstallDepNeeded() bool {
+ return t.name == "xml-permissions-file" || t.name == "impl-library"
+}
+
// Add the dependencies on the child modules in the component deps mutator.
func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
for _, apiScope := range module.getGeneratedApiScopes(ctx) {
// Add dependencies to the stubs library
stubModuleName := module.stubsLibraryModuleName(apiScope)
- // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable
- stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName)
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, stubModuleName)
+ ctx.AddVariationDependencies(nil, apiScope.everythingStubsTag, stubModuleName)
+
+ exportableStubModuleName := module.exportableStubsLibraryModuleName(apiScope)
+ ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName)
// Add a dependency on the stubs source in order to access both stubs source and api information.
ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
@@ -1326,37 +1543,21 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
m += "Please see the documentation of the prebuilt_apis module type (and a usage example in prebuilts/sdk) for a convenient way to generate these."
ctx.ModuleErrorf(m)
}
- if module.requiresRuntimeImplementationLibrary() {
- // Only add the deps for the library if it is actually going to be built.
- module.Library.deps(ctx)
- }
-}
-
-func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
- paths, err := module.commonOutputFiles(tag)
- if paths != nil || err != nil {
- return paths, err
- }
- if module.requiresRuntimeImplementationLibrary() {
- return module.Library.OutputFiles(tag)
- }
- if tag == "" {
- return nil, nil
- }
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if proptools.String(module.deviceProperties.Min_sdk_version) != "" {
- module.CheckMinSdkVersion(ctx)
+ if disableSourceApexVariant(ctx) {
+ // Prebuilts are active, do not create the installation rules for the source javalib.
+ // Even though the source javalib is not used, we need to hide it to prevent duplicate installation rules.
+ // TODO (b/331665856): Implement a principled solution for this.
+ module.HideFromMake()
}
module.generateCommonBuildActions(ctx)
- // Only build an implementation library if required.
- if module.requiresRuntimeImplementationLibrary() {
- module.Library.GenerateAndroidBuildActions(ctx)
- }
+ module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName())
+
+ module.provideHiddenAPIPropertyInfo(ctx)
// Collate the components exported by this module. All scope specific modules are exported but
// the impl and xml component modules are not.
@@ -1379,11 +1580,56 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
}
+
+ if tag == implLibraryTag {
+ if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
+ module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
+ module.implLibraryModule = to.(*Library)
+ android.SetProvider(ctx, JavaInfoProvider, dep)
+ }
+ }
})
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
+ module.hideApexVariantFromMake = true
+ }
+
+ if module.implLibraryModule != 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.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
+
+ // 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
+ module.linter.outputs.depSets = module.implLibraryModule.LintDepSets()
+
+ if !module.Host() {
+ module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile
+ }
+
+ 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.
exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)}
- ctx.SetProvider(android.ExportedComponentsInfoProvider, exportedComponentInfo)
+ android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo)
// Provide additional information for inclusion in an sdk's generated .info file.
additionalSdkInfo := map[string]interface{}{}
@@ -1396,14 +1642,26 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
scopes[scope.name] = scopeInfo
scopeInfo["current_api"] = scope.snapshotRelativeCurrentApiTxtPath(baseModuleName)
scopeInfo["removed_api"] = scope.snapshotRelativeRemovedApiTxtPath(baseModuleName)
- if p := scopePaths.latestApiPath; p.Valid() {
- scopeInfo["latest_api"] = p.Path().String()
+ if p := scopePaths.latestApiPaths; len(p) > 0 {
+ // The last path in the list is the one that applies to this scope, the
+ // preceding ones, if any, are for the scope(s) that it extends.
+ scopeInfo["latest_api"] = p[len(p)-1].String()
}
- if p := scopePaths.latestRemovedApiPath; p.Valid() {
- scopeInfo["latest_removed_api"] = p.Path().String()
+ if p := scopePaths.latestRemovedApiPaths; len(p) > 0 {
+ // The last path in the list is the one that applies to this scope, the
+ // preceding ones, if any, are for the scope(s) that it extends.
+ scopeInfo["latest_removed_api"] = p[len(p)-1].String()
}
}
- ctx.SetProvider(android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
+ android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
+ module.setOutputFiles(ctx)
+ if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil {
+ setOutputFiles(ctx, module.implLibraryModule.Module)
+ }
+}
+
+func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
+ return module.builtInstalledForApex
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1411,8 +1669,9 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
return nil
}
entriesList := module.Library.AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.Required = append(entries.Required, module.implLibraryModuleName())
if module.sharedLibrary() {
- entries := &entriesList[0]
entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
}
return entriesList
@@ -1453,12 +1712,16 @@ func latestPrebuiltApiModuleName(name string, apiScope *apiScope) string {
return PrebuiltApiModuleName(name, apiScope.name, "latest")
}
+func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string {
+ return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest")
+}
+
func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
return ":" + module.latestApiModuleName(apiScope)
}
func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string {
- return latestPrebuiltApiModuleName(module.distStem(), apiScope)
+ return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope)
}
func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
@@ -1466,7 +1729,7 @@ func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) stri
}
func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string {
- return latestPrebuiltApiModuleName(module.distStem()+"-removed", apiScope)
+ return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope)
}
func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
@@ -1477,6 +1740,34 @@ func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope)
return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope)
}
+func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool {
+ _, exists := c.GetApiLibraries()[module.Name()]
+ return exists
+}
+
+// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the
+// api surface that the module contribute to. For example, the public droidstubs and java_library
+// do not contribute to the public api surface, but contributes to the core platform api surface.
+// This method returns the full api surface stub lib that
+// the generated java_api_library should depend on.
+func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string {
+ if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
+ return val.FullApiSurfaceStubLib
+ }
+ return ""
+}
+
+// The listed modules' stubs contents do not match the corresponding txt files,
+// but require additional api contributions to generate the full stubs.
+// This method returns the name of the additional api contribution module
+// for corresponding sdk_library modules.
+func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string {
+ if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
+ return val.AdditionalApiContribution
+ }
+ return ""
+}
+
func childModuleVisibility(childVisibility []string) []string {
if childVisibility == nil {
// No child visibility set. The child will use the visibility of the sdk_library.
@@ -1497,24 +1788,22 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
props := struct {
Name *string
Visibility []string
- Instrument bool
Libs []string
Static_libs []string
Apex_available []string
+ Stem *string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
Visibility: visibility,
- // Set the instrument property to ensure it is instrumented when instrumentation is required.
- Instrument: true,
- // Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
- // addition of &module.properties below.
- Libs: module.sdkLibraryProperties.Impl_only_libs,
- // Set the impl_only static libs. Note that the module's "static_libs" get appended as well, via the
- // addition of &module.properties below.
- Static_libs: module.sdkLibraryProperties.Impl_only_static_libs,
+
+ Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
+
+ Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...),
// Pass the apex_available settings down so that the impl library can be statically
// embedded within a library that is added to an APEX. Needed for updatable-media.
Apex_available: module.ApexAvailable(),
+
+ Stem: proptools.StringPtr(module.Name()),
}
properties := []interface{}{
@@ -1524,48 +1813,49 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
&module.dexProperties,
&module.dexpreoptProperties,
&module.linter.properties,
+ &module.overridableProperties,
&props,
module.sdkComponentPropertiesForChildLibrary(),
}
mctx.CreateModule(LibraryFactory, properties...)
}
-// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- System_modules *string
- Patch_module *string
- Libs []string
- Static_libs []string
- Compile_dex *bool
- Java_version *string
- Openjdk9 struct {
- Srcs []string
- Javacflags []string
- }
- Dist struct {
- Targets []string
- Dest *string
- Dir *string
- Tag *string
- }
- }{}
-
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
- props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+type libraryProperties struct {
+ Name *string
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ System_modules *string
+ Patch_module *string
+ Libs []string
+ Static_libs []string
+ Compile_dex *bool
+ Java_version *string
+ Openjdk9 struct {
+ Srcs []string
+ Javacflags []string
+ }
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
+ Is_stubs_module *bool
+}
+
+func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+ props := libraryProperties{}
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
// sources are generated from the droiddoc
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
props.System_modules = module.deviceProperties.System_modules
props.Patch_module = module.properties.Patch_module
props.Installable = proptools.BoolPtr(false)
props.Libs = module.sdkLibraryProperties.Stub_only_libs
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
// The stub-annotations library contains special versions of the annotations
// with CLASS retention policy, so that they're kept.
@@ -1577,21 +1867,26 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
// interop with older developer tools that don't support 1.9.
props.Java_version = proptools.StringPtr("1.8")
+ props.Is_stubs_module = proptools.BoolPtr(true)
- // The imports need to be compiled to dex if the java_sdk_library requests it.
- compileDex := module.dexProperties.Compile_dex
- if module.stubLibrariesCompiledForDex() {
- compileDex = proptools.BoolPtr(true)
- }
- props.Compile_dex = compileDex
+ return props
+}
- // Dist the class jar artifact for sdk builds.
- if !Bool(module.sdkLibraryProperties.No_dist) {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
- props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
- props.Dist.Tag = proptools.StringPtr(".jar")
- }
+// Creates a static java library that has API stubs
+func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Create a static java library that compiles the "exportable" stubs
+func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}
mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -1617,6 +1912,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
Merge_inclusion_annotations_dirs []string
Generate_stubs *bool
Previous_api *string
+ Aconfig_declarations []string
Check_api struct {
Current ApiToCheck
Last_released ApiToCheck
@@ -1653,6 +1949,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
props.Libs = module.properties.Libs
props.Libs = append(props.Libs, module.properties.Static_libs...)
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
props.Java_version = module.properties.Java_version
@@ -1660,26 +1957,22 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
+ props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
droidstubsArgs := []string{}
if len(module.sdkLibraryProperties.Api_packages) != 0 {
droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
}
- if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
- droidstubsArgs = append(droidstubsArgs,
- android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
- }
droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
- disabledWarnings := []string{
- "BroadcastBehavior",
- "DeprecationMismatch",
- "HiddenSuperclass",
- "HiddenTypeParameter",
- "MissingPermission",
- "SdkConstant",
- "Todo",
- "Typo",
- "UnavailableSymbol",
+ disabledWarnings := []string{"HiddenSuperclass"}
+ if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
+ disabledWarnings = append(disabledWarnings,
+ "BroadcastBehavior",
+ "DeprecationMismatch",
+ "MissingPermission",
+ "SdkConstant",
+ "Todo",
+ )
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
@@ -1739,23 +2032,153 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
if !Bool(module.sdkLibraryProperties.No_dist) {
// Dist the api txt and removed api txt artifacts for sdk builds.
distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+ stubsTypeTagPrefix := ""
+ if mctx.Config().ReleaseHiddenApiExportableStubs() {
+ stubsTypeTagPrefix = ".exportable"
+ }
for _, p := range []struct {
tag string
pattern string
}{
- {tag: ".api.txt", pattern: "%s.txt"},
- {tag: ".removed-api.txt", pattern: "%s-removed.txt"},
+ // "exportable" api files are copied to the dist directory instead of the
+ // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
+ // is set. Otherwise, the "everything" api files are copied to the dist directory.
+ {tag: "%s.api.txt", pattern: "%s.txt"},
+ {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
} {
props.Dists = append(props.Dists, android.Dist{
Targets: []string{"sdk", "win_sdk"},
Dir: distDir,
Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
- Tag: proptools.StringPtr(p.tag),
+ Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
})
}
}
- mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx)
+ mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
+}
+
+func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) {
+ props := struct {
+ Name *string
+ Visibility []string
+ Api_contributions []string
+ Libs []string
+ Static_libs []string
+ Full_api_surface_stub *string
+ System_modules *string
+ Enable_validation *bool
+ Stubs_type *string
+ }{}
+
+ props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
+
+ apiContributions := []string{}
+
+ // Api surfaces are not independent of each other, but have subset relationships,
+ // and so does the api files. To generate from-text stubs for api surfaces other than public,
+ // all subset api domains' api_contriubtions must be added as well.
+ scope := apiScope
+ for scope != nil {
+ apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
+ scope = scope.extends
+ }
+ if apiScope == apiScopePublic {
+ additionalApiContribution := module.apiLibraryAdditionalApiContribution()
+ if additionalApiContribution != "" {
+ apiContributions = append(apiContributions, additionalApiContribution)
+ }
+ }
+
+ props.Api_contributions = apiContributions
+ props.Libs = module.properties.Libs
+ props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
+ props.Libs = append(props.Libs, "stub-annotations")
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
+ props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName())
+ if alternativeFullApiSurfaceStub != "" {
+ props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub)
+ }
+
+ // android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
+ // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
+ if apiScope.kind == android.SdkModule {
+ props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
+ }
+
+ // java_sdk_library modules that set sdk_version as none does not depend on other api
+ // domains. Therefore, java_api_library created from such modules should not depend on
+ // full_api_surface_stubs but create and compile stubs by the java_api_library module
+ // itself.
+ if module.SdkVersion(mctx).Kind == android.SdkNone {
+ props.Full_api_surface_stub = nil
+ }
+
+ props.System_modules = module.deviceProperties.System_modules
+ props.Enable_validation = proptools.BoolPtr(true)
+ props.Stubs_type = proptools.StringPtr("everything")
+
+ mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
+ props := libraryProperties{}
+
+ props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
+
+ props.System_modules = module.deviceProperties.System_modules
+
+ // The imports need to be compiled to dex if the java_sdk_library requests it.
+ compileDex := module.dexProperties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
+
+ if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
+
+ return props
+}
+
+func (module *SdkLibrary) createTopLevelStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
+
+ // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
+ doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+
+ // Add the stub compiling java_library/java_api_library as static lib based on build config
+ staticLib := module.sourceStubsLibraryModuleName(apiScope)
+ if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
+ staticLib = module.apiLibraryModuleName(apiScope)
+ }
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
+ doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
+
+ staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
@@ -1768,6 +2191,9 @@ func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep an
if depTag == xmlPermissionsFileTag {
return true
}
+ if dep.Name() == module.implLibraryModuleName() {
+ return true
+ }
return module.Library.DepIsInSameApex(mctx, dep)
}
@@ -1776,6 +2202,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)
@@ -1792,6 +2222,7 @@ func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Lib_name: proptools.StringPtr(module.BaseModuleName()),
@@ -1801,6 +2232,7 @@ func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -1838,12 +2270,12 @@ func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkS
// If either this or the other module are on the platform then this will return
// false.
func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- otherApexInfo := ctx.OtherModuleProvider(other, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider)
return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
}
-func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
+func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
// If the client doesn't set sdk_version, but if this library prefers stubs over
// the impl library, let's provide the widest API surface possible. To do so,
// force override sdk_version to module_current so that the closest possible API
@@ -1860,11 +2292,7 @@ func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion andr
// * No sdk_version specified on the referencing module.
// * The referencing module is in the same apex as this.
if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
- if headerJars {
- return module.HeaderJars()
- } else {
- return module.ImplementationJars()
- }
+ return module.implLibraryHeaderJars
}
}
@@ -1873,12 +2301,7 @@ func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion andr
// to satisfy SdkLibraryDependency interface
func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- return module.sdkJars(ctx, sdkVersion, true /*headerJars*/)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
+ return module.sdkJars(ctx, sdkVersion)
}
var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
@@ -1898,7 +2321,7 @@ func (module *SdkLibrary) getApiDir() string {
// once for public API level and once for system API level
func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
// If the module has been disabled then don't create any child modules.
- if !module.Enabled() {
+ if !module.Enabled(mctx) {
return
}
@@ -1954,6 +2377,19 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
module.createStubsLibrary(mctx, scope)
+ module.createExportableStubsLibrary(mctx, scope)
+
+ alternativeFullApiSurfaceStubLib := ""
+ if scope == apiScopePublic {
+ alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib()
+ }
+ contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != ""
+ if contributesToApiSurface {
+ module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib)
+ }
+
+ module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
+ module.createTopLevelExportableStubsLibrary(mctx, scope)
}
if module.requiresRuntimeImplementationLibrary() {
@@ -2006,6 +2442,14 @@ type sdkLibraryComponentNamingScheme interface {
stubsLibraryModuleName(scope *apiScope, baseName string) string
stubsSourceModuleName(scope *apiScope, baseName string) string
+
+ apiLibraryModuleName(scope *apiScope, baseName string) string
+
+ sourceStubsLibraryModuleName(scope *apiScope, baseName string) string
+
+ exportableStubsLibraryModuleName(scope *apiScope, baseName string) string
+
+ exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string
}
type defaultNamingScheme struct {
@@ -2019,27 +2463,53 @@ func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName st
return scope.stubsSourceModuleName(baseName)
}
+func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.apiLibraryModuleName(baseName)
+}
+
+func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.sourceStubLibraryModuleName(baseName)
+}
+
+func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.exportableStubsLibraryModuleName(baseName)
+}
+
+func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.exportableSourceStubsLibraryModuleName(baseName)
+}
+
var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
+func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool {
+ return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) ||
+ strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix())
+}
+
func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
+ name = strings.TrimSuffix(name, ".from-source")
+
// This suffix-based approach is fragile and could potentially mis-trigger.
// TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
- if strings.HasSuffix(name, apiScopePublic.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopePublic) {
if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
// Due to a previous bug, these modules were not considered stubs, so we retain that.
return false, javaPlatform
}
return true, javaSdk
}
- if strings.HasSuffix(name, apiScopeSystem.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeSystem) {
return true, javaSystem
}
- if strings.HasSuffix(name, apiScopeModuleLib.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeModuleLib) {
return true, javaModule
}
- if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeTest) {
return true, javaSystem
}
+ if hasStubsLibrarySuffix(name, apiScopeSystemServer) {
+ return true, javaSystemServer
+ }
return false, javaPlatform
}
@@ -2060,7 +2530,7 @@ func SdkLibraryFactory() android.Module {
// Initialize the map from scope to scope specific properties.
scopeToProperties := make(map[*apiScope]*ApiScopeProperties)
- for _, scope := range allApiScopes {
+ for _, scope := range AllApiScopes {
scopeToProperties[scope] = scope.scopeSpecificProperties(module)
}
module.scopeToProperties = scopeToProperties
@@ -2087,48 +2557,9 @@ func SdkLibraryFactory() android.Module {
module.CreateInternalModules(ctx)
}
})
- android.InitBazelModule(module)
return module
}
-type bazelSdkLibraryAttributes struct {
- Public bazel.StringAttribute
- System bazel.StringAttribute
- Test bazel.StringAttribute
- Module_lib bazel.StringAttribute
- System_server bazel.StringAttribute
-}
-
-// java_sdk_library bp2build converter
-func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() != "java_sdk_library" {
- return
- }
-
- nameToAttr := make(map[string]bazel.StringAttribute)
-
- for _, scope := range module.getGeneratedApiScopes(ctx) {
- apiSurfaceFile := path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt")
- var scopeStringAttribute bazel.StringAttribute
- scopeStringAttribute.SetValue(apiSurfaceFile)
- nameToAttr[scope.name] = scopeStringAttribute
- }
-
- attrs := bazelSdkLibraryAttributes{
- Public: nameToAttr["public"],
- System: nameToAttr["system"],
- Test: nameToAttr["test"],
- Module_lib: nameToAttr["module-lib"],
- System_server: nameToAttr["system-server"],
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_sdk_library",
- Bzl_load_location: "//build/bazel/rules/java:sdk_library.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
-}
-
//
// SDK library prebuilts
//
@@ -2165,6 +2596,11 @@ type sdkLibraryImportProperties struct {
// If not empty, classes are restricted to the specified packages and their sub-packages.
Permitted_packages []string
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
type SdkLibraryImport struct {
@@ -2183,16 +2619,13 @@ type SdkLibraryImport struct {
commonToSdkLibraryAndImport
- // 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 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
+ dexJarFile OptionalDexJarPath
+ dexJarFileErr error
// Expected install file path of the source module(sdk_library)
// or dex implementation jar obtained from the prebuilt_apex, if any.
@@ -2214,7 +2647,7 @@ var allScopeStructType = createAllScopePropertiesStructType()
// Dynamically create a structure type for each apiscope in allApiScopes.
func createAllScopePropertiesStructType() reflect.Type {
var fields []reflect.StructField
- for _, apiScope := range allApiScopes {
+ for _, apiScope := range AllApiScopes {
field := reflect.StructField{
Name: apiScope.fieldName,
Type: reflect.TypeOf(sdkLibraryScopeProperties{}),
@@ -2232,7 +2665,7 @@ func createPropertiesInstance() (interface{}, map[*apiScope]*sdkLibraryScopeProp
allScopePropertiesStruct := allScopePropertiesPtr.Elem()
scopeProperties := make(map[*apiScope]*sdkLibraryScopeProperties)
- for _, apiScope := range allApiScopes {
+ for _, apiScope := range AllApiScopes {
field := allScopePropertiesStruct.FieldByName(apiScope.fieldName)
scopeProperties[apiScope] = field.Addr().Interface().(*sdkLibraryScopeProperties)
}
@@ -2277,6 +2710,10 @@ func (module *SdkLibraryImport) Name() string {
return module.prebuilt.Name(module.ModuleBase.Name())
}
+func (module *SdkLibraryImport) BaseModuleName() string {
+ return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
+}
+
func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
@@ -2294,6 +2731,10 @@ func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHo
if len(scopeProperties.Stub_srcs) > 0 {
module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
}
+
+ if scopeProperties.Current_api != nil {
+ module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties)
+ }
}
javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -2305,15 +2746,20 @@ func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHo
func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
// Creates a java import for the jar with ".stubs" suffix
props := struct {
- Name *string
- Sdk_version *string
- Libs []string
- Jars []string
- Compile_dex *bool
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ Compile_dex *bool
+ Is_stubs_module *bool
android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
props.Sdk_version = scopeProperties.Sdk_version
// Prepend any of the libs from the legacy public properties to the libs for each of the
// scopes to avoid having to duplicate them in each scope.
@@ -2329,24 +2775,52 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl
compileDex = proptools.BoolPtr(true)
}
props.Compile_dex = compileDex
+ props.Is_stubs_module = proptools.BoolPtr(true)
mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
props := struct {
- Name *string
- Srcs []string
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Srcs []string
android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
props.Srcs = scopeProperties.Stub_srcs
// The stubs source is preferred if the java_sdk_library_import is preferred.
props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
- mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ api_file := scopeProperties.Current_api
+ api_surface := &apiScope.name
+
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Api_surface *string
+ Api_file *string
+ Visibility []string
+ }{}
+
+ props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Api_surface = api_surface
+ props.Api_file = api_file
+ props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+ mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
// Add the dependencies on the child module in the component deps mutator so that it
@@ -2358,7 +2832,7 @@ func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutator
}
// Add dependencies to the prebuilt stubs library
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
+ ctx.AddVariationDependencies(nil, apiScope.prebuiltStubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
if len(scopeProperties.Stub_srcs) > 0 {
// Add dependencies to the prebuilt stubs source library
@@ -2382,14 +2856,6 @@ func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext)
}
}
-func (module *SdkLibraryImport) AndroidMkEntries() []android.AndroidMkEntries {
- // For an SDK library imported from a prebuilt APEX, we don't need a Make module for itself, as we
- // don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
- // is preopted.
- dexpreoptEntries := module.dexpreopter.AndroidMkEntriesForApex()
- return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
-}
-
var _ android.ApexModule = (*SdkLibraryImport)(nil)
// Implements android.ApexModule
@@ -2423,18 +2889,6 @@ func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) an
var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
-func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
- paths, err := module.commonOutputFiles(tag)
- if paths != nil || err != nil {
- return paths, err
- }
- if module.implLibraryModule != nil {
- return module.implLibraryModule.OutputFiles(tag)
- } else {
- return nil, nil
- }
-}
-
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.generateCommonBuildActions(ctx)
@@ -2483,14 +2937,18 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
if ctx.Device() {
// If this is a variant created for a prebuilt_apex then use the dex implementation jar
// obtained from the associated deapexer module.
- ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module.
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
- return // An error has been reported by FindDeapexerProviderForModule.
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call DexJarBuildPath
+ module.dexJarFileErr = err
+ module.initHiddenAPIError(err)
+ return
}
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName())
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
module.dexJarFile = dexJarFile
@@ -2499,16 +2957,13 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
module.installFile = installPath
module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
- module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath)
+ module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
module.dexpreopter.isSDKLibrary = true
- module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter)
+ module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter)
if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
module.dexpreopter.inputProfilePathOnHost = profilePath
}
-
- // Dexpreopting.
- module.dexpreopt(ctx, dexOutputPath)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
@@ -2516,6 +2971,11 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
}
}
}
+
+ module.setOutputFiles(ctx)
+ if module.implLibraryModule != nil {
+ setOutputFiles(ctx, module.implLibraryModule.Module)
+ }
}
func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
@@ -2540,23 +3000,20 @@ func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdk
return module.sdkJars(ctx, sdkVersion, true)
}
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- // This module is just a wrapper for the stubs.
- return module.sdkJars(ctx, sdkVersion, false)
-}
-
// to satisfy UsesLibraryDependency interface
-func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath {
+func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
// The dex implementation jar extracted from the .apex file should be used in preference to the
// source.
+ if module.dexJarFileErr != nil {
+ ctx.ModuleErrorf(module.dexJarFileErr.Error())
+ }
if module.dexJarFile.IsSet() {
return module.dexJarFile
}
if module.implLibraryModule == nil {
return makeUnsetDexJarPath()
} else {
- return module.implLibraryModule.DexJarBuildPath()
+ return module.implLibraryModule.DexJarBuildPath(ctx)
}
}
@@ -2639,6 +3096,10 @@ func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseMo
return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
}
+func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// java_sdk_library_xml
type sdkLibraryXml struct {
android.ModuleBase
@@ -2688,6 +3149,11 @@ type sdkLibraryXmlProperties struct {
//
// This value comes from the ApiLevel of the MinSdkVersion property.
Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared library requires to work correctly.
+ //
+ // This will add dependency="foo:bar" to the <library> section.
+ Uses_libs_dependencies []string
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -2719,10 +3185,7 @@ func (module *sdkLibraryXml) SubDir() string {
return "permissions"
}
-// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) OutputFile() android.OutputPath {
- return module.outputFilePath
-}
+var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
@@ -2745,11 +3208,11 @@ func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleConte
// File path to the runtime implementation library
func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
implName := proptools.String(module.properties.Lib_name)
- if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
// In most cases, this works fine. But when apex_name is set or override_apex is used
// this can be wrong.
- return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName)
+ return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
}
partition := "system"
if module.SocSpecific() {
@@ -2793,7 +3256,14 @@ func formattedOptionalAttribute(attrName string, value *string) string {
if value == nil {
return ""
}
- return fmt.Sprintf(` %s=\"%s\"\n`, attrName, *value)
+ return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
+}
+
+func formattedDependenciesAttribute(dependencies []string) string {
+ if dependencies == nil {
+ return ""
+ }
+ return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
}
func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
@@ -2805,32 +3275,33 @@ func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) stri
implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
// <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
// similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
var libraryTag string
if module.properties.Min_device_sdk != nil {
- libraryTag = ` <apex-library\n`
+ libraryTag = " <apex-library\n"
} else {
- libraryTag = ` <library\n`
+ libraryTag = " <library\n"
}
return strings.Join([]string{
- `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n`,
- `<!-- Copyright (C) 2018 The Android Open Source Project\n`,
- `\n`,
- ` Licensed under the Apache License, Version 2.0 (the \"License\");\n`,
- ` you may not use this file except in compliance with the License.\n`,
- ` You may obtain a copy of the License at\n`,
- `\n`,
- ` http://www.apache.org/licenses/LICENSE-2.0\n`,
- `\n`,
- ` Unless required by applicable law or agreed to in writing, software\n`,
- ` distributed under the License is distributed on an \"AS IS\" BASIS,\n`,
- ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n`,
- ` See the License for the specific language governing permissions and\n`,
- ` limitations under the License.\n`,
- `-->\n`,
- `<permissions>\n`,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
+ "<!-- Copyright (C) 2018 The Android Open Source Project\n",
+ "\n",
+ " Licensed under the Apache License, Version 2.0 (the \"License\");\n",
+ " you may not use this file except in compliance with the License.\n",
+ " You may obtain a copy of the License at\n",
+ "\n",
+ " http://www.apache.org/licenses/LICENSE-2.0\n",
+ "\n",
+ " Unless required by applicable law or agreed to in writing, software\n",
+ " distributed under the License is distributed on an \"AS IS\" BASIS,\n",
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
+ " See the License for the specific language governing permissions and\n",
+ " limitations under the License.\n",
+ "-->\n",
+ "<permissions>\n",
libraryTag,
libNameAttr,
filePathAttr,
@@ -2838,26 +3309,27 @@ func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) stri
implicitUntilAttr,
minSdkAttr,
maxSdkAttr,
- ` />\n`,
- `</permissions>\n`}, "")
+ dependenciesAttr,
+ " />\n",
+ "</permissions>\n",
+ }, "")
}
func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
libName := proptools.String(module.properties.Lib_name)
module.selfValidate(ctx)
xmlContent := module.permissionsContents(ctx)
module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Text("/bin/bash -c \"echo -e '" + xmlContent + "'\" > ").
- Output(module.outputFilePath)
-
- rule.Build("java_sdk_xml", "Permission XML")
+ android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+ ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
+
+ ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
@@ -3065,7 +3537,7 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe
s.Stem = sdk.distStem()
s.Scopes = make(map[*apiScope]*scopeProperties)
- for _, apiScope := range allApiScopes {
+ for _, apiScope := range AllApiScopes {
paths := sdk.findScopePaths(apiScope)
if paths == nil {
continue
@@ -3101,7 +3573,8 @@ 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
- if sdk.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+ implLibrary := sdk.getImplLibraryModule()
+ if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
s.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
}
@@ -3126,7 +3599,7 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo
stem := s.Stem
- for _, apiScope := range allApiScopes {
+ for _, apiScope := range AllApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 1d0c13d4b..a8a1494ee 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -35,6 +35,14 @@ func TestJavaSdkLibrary(t *testing.T) {
"29": {"foo"},
"30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
}),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
@@ -71,6 +79,8 @@ func TestJavaSdkLibrary(t *testing.T) {
name: "quuz",
public: {
jars: ["c.jar"],
+ current_api: "api/current.txt",
+ removed_api: "api/removed.txt",
},
}
java_sdk_library_import {
@@ -121,18 +131,22 @@ func TestJavaSdkLibrary(t *testing.T) {
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", "")
- exportedComponentsInfo := result.ModuleProvider(foo.Module(), android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
+ exportedComponentsInfo, _ := android.SingletonModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
expectedFooExportedComponents := []string{
- "foo-removed.api.public.latest",
- "foo-removed.api.system.latest",
- "foo.api.public.latest",
- "foo.api.system.latest",
+ "foo-removed.api.combined.public.latest",
+ "foo-removed.api.combined.system.latest",
+ "foo.api.combined.public.latest",
+ "foo.api.combined.system.latest",
"foo.stubs",
+ "foo.stubs.exportable",
+ "foo.stubs.exportable.system",
+ "foo.stubs.exportable.test",
"foo.stubs.source",
"foo.stubs.source.system",
"foo.stubs.source.test",
@@ -169,13 +183,16 @@ func TestJavaSdkLibrary(t *testing.T) {
android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
}
- fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
- // tests if kotlinc generated files are NOT excluded from output of foo.
- android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ // test if quuz have created the api_contribution module
+ result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
+
+ fooImplDexJar := result.ModuleForTests("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")
- barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8")
- // tests if kotlinc generated files are excluded from output of bar.
- android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+ barImplDexJar := result.ModuleForTests("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) {
@@ -210,19 +227,21 @@ func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
`)
// test that updatability attributes are passed on correctly
- fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Rule("java_sdk_xml")
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-since=\"U\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-before=\"V\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min-device-sdk=\"W\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `max-device-sdk=\"X\"`)
+ fooUpdatable := result.ModuleForTests("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"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `min-device-sdk="W"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `max-device-sdk="X"`)
// 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").Rule("java_sdk_xml")
- android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-since`)
- android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-before`)
- android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `min-device-sdk`)
- android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `max-device-sdk`)
+ fooPermissions := result.ModuleForTests("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`)
+ android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `min-device-sdk`)
+ android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `max-device-sdk`)
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) {
@@ -353,9 +372,10 @@ func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) {
}
`)
// test that updatability attributes are passed on correctly
- fooUpdatable := result.ModuleForTests("foo.xml", "android_common").Rule("java_sdk_xml")
- android.AssertStringDoesContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<apex-library`)
- android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<library`)
+ fooUpdatable := result.ModuleForTests("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) {
@@ -407,10 +427,9 @@ func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
}
for _, expectation := range expectations {
- verify("sdklib", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
- stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
+ stubName := apiScopePublic.sourceStubLibraryModuleName("sdklib")
verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
}
}
@@ -473,7 +492,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": path dependency ":foo{.public.annotations.zip}": annotations.zip not available for api scope public`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".public.annotations.zip"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -498,7 +517,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"foo" does not provide api scope system`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".system.stubs.source"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -521,6 +540,11 @@ func TestJavaSdkLibrary_Deps(t *testing.T) {
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -535,10 +559,11 @@ func TestJavaSdkLibrary_Deps(t *testing.T) {
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`dex2oatd`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
@@ -581,7 +606,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("stubs.source", func(t *testing.T) {
prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`stubs.source not available for api scope public`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.stubs.source"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",
@@ -596,7 +621,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("api.txt", func(t *testing.T) {
prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`api.txt not available for api scope public`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.api.txt"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",
@@ -610,7 +635,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("removed-api.txt", func(t *testing.T) {
prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`removed-api.txt not available for api scope public`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.removed-api.txt"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",
@@ -911,6 +936,11 @@ func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -933,15 +963,17 @@ func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`dex2oatd`,
`prebuilt_sdklib`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`prebuilt_sdklib.stubs`,
`sdklib.impl`,
// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
@@ -957,6 +989,11 @@ func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer an
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
preparer,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -1005,15 +1042,17 @@ func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer an
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`prebuilt_sdklib`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source`,
@@ -1046,18 +1085,131 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
t.Run("prefer", func(t *testing.T) {
testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer)
})
+}
- t.Run("use_source_config_var", func(t *testing.T) {
- testJavaSdkLibraryImport_Preferred(t,
- "use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"},",
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.VendorVars = map[string]map[string]string{
- "acme": {
- "use_source": "false",
- },
- }
- }))
- })
+// 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",
+ ],
+ }
+ 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.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) {
@@ -1078,7 +1230,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType string
fromPartition string
toPartition string
- enforceVendorInterface bool
enforceProductInterface bool
enforceJavaSdkLibraryCheck bool
allowList []string
@@ -1113,9 +1264,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
android.FixtureWithRootAndroidBp(bpFile),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
- if info.enforceVendorInterface {
- variables.DeviceVndkVersion = proptools.StringPtr("current")
- }
variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
variables.InterPartitionJavaLibraryAllowList = info.allowList
}),
@@ -1143,7 +1291,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: false,
}, "")
@@ -1152,7 +1299,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: false,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1161,7 +1307,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1170,7 +1315,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1179,7 +1323,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
allowList: []string{"bar"},
@@ -1189,7 +1332,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "product",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1198,7 +1340,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_sdk_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1207,7 +1348,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_sdk_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1216,7 +1356,6 @@ func TestJavaSdkLibraryEnforce(t *testing.T) {
libraryType: "java_sdk_library",
fromPartition: "vendor",
toPartition: "product",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1232,6 +1371,11 @@ func TestJavaSdkLibraryDist(t *testing.T) {
"sdklib_group_foo",
"sdklib_owner_foo",
"foo"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib_no_group",
@@ -1288,7 +1432,7 @@ func TestJavaSdkLibraryDist(t *testing.T) {
for _, tt := range testCases {
t.Run(tt.module, func(t *testing.T) {
- m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library)
+ m := result.ModuleForTests(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))
@@ -1313,11 +1457,11 @@ func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) {
preparer.RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
- srcs: ["a.java"],
- static_libs: ["util"],
- min_sdk_version: "30",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
unsafe_ignore_missing_latest_api: true,
- }
+ }
java_library {
name: "util",
@@ -1412,3 +1556,351 @@ func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) {
fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
}
+
+func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ libs: ["bar-lib"],
+ },
+ }
+
+ java_library {
+ name: "bar-lib",
+ srcs: ["b.java"],
+ }
+ `)
+
+ // The foo.stubs.source should depend on bar-lib
+ fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+ android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+}
+
+func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ }
+ `)
+
+ testCases := []struct {
+ scope *apiScope
+ apiContributions []string
+ fullApiSurfaceStub string
+ }{
+ {
+ scope: apiScopePublic,
+ apiContributions: []string{"foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_stubs_current",
+ },
+ {
+ scope: apiScopeSystem,
+ apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_system_stubs_current",
+ },
+ {
+ scope: apiScopeTest,
+ apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_test_stubs_current",
+ },
+ {
+ scope: apiScopeModuleLib,
+ apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
+ fullApiSurfaceStub: "android_module_lib_stubs_current_full.from-text",
+ },
+ }
+
+ for _, c := range testCases {
+ m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
+ android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions)
+ android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub)
+ }
+}
+
+func TestStaticDepStubLibrariesVisibility(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "A.java": nil,
+ "dir/Android.bp": []byte(
+ `
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ libs: ["foo.stubs.from-source"],
+ }
+ `),
+ "dir/A.java": nil,
+ },
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `module "bar" variant "android_common": depends on //.:foo.stubs.from-source which is not visible to this module`)),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["A.java"],
+ }
+ `)
+}
+
+func TestSdkLibraryDependency(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"bar", "foo"},
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["c.java", "b.java"],
+ libs: [
+ "foo",
+ ],
+ uses_libs: [
+ "foo",
+ ],
+ }
+`)
+
+ barPermissions := result.ModuleForTests("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) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ exportableStubsLibraryModuleName := apiScopePublic.exportableStubsLibraryModuleName("foo")
+ exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo")
+
+ // Check modules generation
+ topLevelModule := result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
+ result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common")
+
+ // Check static lib dependency
+ android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+
+ "exportable source stubs library module", true,
+ CheckModuleHasDependency(t, result.TestContext, exportableStubsLibraryModuleName,
+ "android_common", exportableSourceStubsLibraryModuleName),
+ )
+ android.AssertArrayString(t, "exportable source stub library is a static lib of the"+
+ "top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
+ topLevelModule.Module().(*Library).properties.Static_libs)
+}
+
+// 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) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: ["sdklib"], // source is selected using apex_contributions, but prebuilt is selected using prefer
+ }
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ prefer: true, // Set prefer explicitly on the prebuilt. We will assert that rdep gets source in a test case.
+ }
+ // rdeps
+ java_library {
+ name: "mymodule",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ libs: ["sdklib",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
+ }
+ `
+
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ // We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ )
+
+ 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")
+ 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")
+}
+
+// test that rdep gets resolved to the correct version of a java_sdk_library (source or a specific prebuilt)
+func TestMultipleSdkLibraryPrebuilts(t *testing.T) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: ["%s"],
+ }
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib.v1", //prebuilt
+ source_module_name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+ java_sdk_library_import {
+ name: "sdklib.v2", //prebuilt
+ source_module_name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+ // rdeps
+ java_library {
+ name: "mymodule",
+ srcs: ["a.java"],
+ libs: ["sdklib.stubs",],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedStubPath string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "sdklib",
+ expectedStubPath: "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_sdklib.v1",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v1.stubs/android_common/combined/sdklib.stubs.jar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_sdklib.v2",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v2.stubs/android_common/combined/sdklib.stubs.jar",
+ },
+ }
+
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib", "sdklib.v1", "sdklib.v2"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ )
+
+ for _, tc := range testCases {
+ 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")
+ rule := public.Output("javac/mymodule.jar")
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, tc.expectedStubPath)
+ }
+}
diff --git a/java/sdk_version_test.go b/java/sdk_version_test.go
new file mode 100644
index 000000000..88351d2ef
--- /dev/null
+++ b/java/sdk_version_test.go
@@ -0,0 +1,66 @@
+// Copyright 2024 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 (
+ "testing"
+
+ "android/soong/android"
+)
+
+func stringPtr(v string) *string {
+ return &v
+}
+
+func TestSystemSdkFromVendor(t *testing.T) {
+ fixtures := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = intPtr(34)
+ variables.Platform_sdk_codename = stringPtr("VanillaIceCream")
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ variables.Platform_systemsdk_versions = []string{"33", "34", "VanillaIceCream"}
+ variables.DeviceSystemSdkVersions = []string{"VanillaIceCream"}
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "33": {},
+ "34": {},
+ "35": {},
+ }),
+ )
+
+ fixtures.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("incompatible sdk version")).
+ RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ vendor: true,
+ sdk_version: "system_35",
+ }`)
+
+ result := fixtures.RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ vendor: true,
+ sdk_version: "system_current",
+ }`)
+ fooModule := result.ModuleForTests("foo", "android_common")
+ fooClasspath := fooModule.Rule("javac").Args["classpath"]
+
+ android.AssertStringDoesContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/34/system/android.jar")
+ android.AssertStringDoesNotContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/35/system/android.jar")
+ android.AssertStringDoesNotContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/current/system/android.jar")
+}
diff --git a/java/support_libraries.go b/java/support_libraries.go
index af7c3c2a0..c483fc17a 100644
--- a/java/support_libraries.go
+++ b/java/support_libraries.go
@@ -32,7 +32,7 @@ func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) {
dir := ctx.ModuleDir(module)
switch {
case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"),
- dir == "prebuilts/sdk/current/androidx",
+ strings.HasPrefix(dir, "prebuilts/sdk/current/androidx"),
dir == "prebuilts/sdk/current/car",
dir == "prebuilts/sdk/current/optional",
dir == "prebuilts/sdk/current/support":
diff --git a/java/system_modules.go b/java/system_modules.go
index 0efa1a41c..8e2d5d8ff 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -19,6 +19,7 @@ import (
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
)
@@ -55,13 +56,15 @@ var (
`${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
// Note: The version of the java.base module created must match the version
// of the jlink tool which consumes it.
- `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform android ` +
+ // Use LINUX-OTHER to be compatible with JDK 21+ (b/294137077)
+ `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform LINUX-OTHER ` +
` --class-path ${workDir}/module.jar ${workDir}/jmod/java.base.jmod && ` +
`${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules java.base --output ${outDir} ` +
// Note: The system-modules jlink plugin is disabled because (a) it is not
// useful on Android, and (b) it causes errors with later versions of jlink
// when the jdk.internal.module is absent from java.base (as it is here).
` --disable-plugin system-modules && ` +
+ `rm -rf ${workDir} && ` +
`cp ${config.JrtFsJar} ${outDir}/lib/`,
CommandDeps: []string{
"${moduleInfoJavaPath}",
@@ -159,7 +162,7 @@ func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleConte
var jars android.Paths
ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
- dep, _ := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
jars = append(jars, dep.HeaderJars...)
})
@@ -209,7 +212,7 @@ func (system *SystemModules) AndroidMk() android.AndroidMkData {
// type and the one to use is selected at runtime.
func systemModulesImportFactory() android.Module {
module := &systemModulesImport{}
- module.AddProperties(&module.properties)
+ module.AddProperties(&module.properties, &module.prebuiltProperties)
android.InitPrebuiltModule(module, &module.properties.Libs)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
@@ -218,13 +221,39 @@ func systemModulesImportFactory() android.Module {
type systemModulesImport struct {
SystemModules
- prebuilt android.Prebuilt
+ prebuilt android.Prebuilt
+ prebuiltProperties prebuiltSystemModulesProperties
+}
+
+type prebuiltSystemModulesProperties struct {
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
func (system *systemModulesImport) Name() string {
return system.prebuilt.Name(system.ModuleBase.Name())
}
+// BaseModuleName returns the source module that will get shadowed by this prebuilt
+// e.g.
+//
+// java_system_modules_import {
+// name: "my_system_modules.v1",
+// source_module_name: "my_system_modules",
+// }
+//
+// java_system_modules_import {
+// name: "my_system_modules.v2",
+// source_module_name: "my_system_modules",
+// }
+//
+// `BaseModuleName` for both will return `my_system_modules`
+func (system *systemModulesImport) BaseModuleName() string {
+ return proptools.StringDefault(system.prebuiltProperties.Source_module_name, system.ModuleBase.Name())
+}
+
func (system *systemModulesImport) Prebuilt() *android.Prebuilt {
return &system.prebuilt
}
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 7b5a3867e..336dd2134 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -24,7 +25,7 @@ func getModuleHeaderJarsAsRelativeToTopPaths(result *android.TestResult, moduleN
paths := []string{}
for _, moduleName := range moduleNames {
module := result.Module(moduleName, "android_common")
- info := result.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ info, _ := android.SingletonModuleProvider(result, module, JavaInfoProvider)
paths = append(paths, info.HeaderJars.RelativeToTop().Strings()...)
}
return paths
@@ -111,3 +112,85 @@ func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
expectedPrebuiltPaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "prebuilt_system-module1", "prebuilt_system-module2")
android.AssertArrayString(t, "prebuilt system modules inputs", expectedPrebuiltPaths, prebuiltInputs.RelativeToTop().Strings())
}
+
+func TestMultipleSystemModulesPrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ sdk_version: "none",
+ system_modules: "my_system_modules",
+ }
+
+ // multiple variations of java_system_modules
+ // source
+ java_system_modules {
+ name: "my_system_modules",
+ libs: ["bar"],
+ }
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_system_modules_import {
+ name: "my_system_modules.v1",
+ source_module_name: "my_system_modules",
+ libs: ["bar.v1"],
+ }
+ java_import {
+ name: "bar.v1",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+ // prebuilt "v2"
+ java_system_modules_import {
+ name: "my_system_modules.v2",
+ source_module_name: "my_system_modules",
+ libs: ["bar.v2"],
+ }
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v2.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ }{
+ {
+ desc: "Source system_modules is selected using apex_contributions",
+ selectedDependencyName: "my_system_modules",
+ },
+ {
+ desc: "Prebuilt system_modules v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_my_system_modules.v1",
+ },
+ {
+ desc: "Prebuilt system_modules v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_my_system_modules.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ res := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // check that rdep gets the correct variation of system_modules
+ hasDep := CheckModuleHasDependency(t, res.TestContext, "foo", "android_common", tc.selectedDependencyName)
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from foo to %s\n", tc.selectedDependencyName), true, hasDep)
+ }
+}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 17d301b70..bad2cf1cf 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -69,6 +69,7 @@ func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx an
configuredJars = configuredJars.AppendList(&standaloneConfiguredJars)
classpathJars = append(classpathJars, standaloneClasspathJars...)
p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+ p.classpathFragmentBase().installClasspathProto(ctx)
}
func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
@@ -87,9 +88,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 +127,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 {
@@ -195,7 +190,7 @@ func (b systemServerClasspathFragmentContentDependencyTag) SdkMemberType(child a
return javaSdkLibrarySdkMemberType
}
- return javaSystemserverLibsSdkMemberType
+ return JavaSystemserverLibsSdkMemberType
}
func (b systemServerClasspathFragmentContentDependencyTag) ExportMember() bool {
@@ -242,7 +237,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 {
@@ -320,6 +314,10 @@ func (module *prebuiltSystemServerClasspathModule) RequiredFilesFromPrebuiltApex
return nil
}
+func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil)
func prebuiltSystemServerClasspathModuleFactory() android.Module {
diff --git a/java/test_spec_test.go b/java/test_spec_test.go
new file mode 100644
index 000000000..4144dad69
--- /dev/null
+++ b/java/test_spec_test.go
@@ -0,0 +1,122 @@
+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 := runTestSpecTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module-name", "")
+
+ // Check that the provider has the right contents
+ data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.TestSpecProviderKey)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ metadata := android.ContentFromFileRuleForTests(t, result.TestContext,
+ module.Output(data.IntermediatePath.String()))
+
+ 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)
+ expectedMetadata := string(protoData)
+
+ if metadata != expectedMetadata {
+ t.Errorf(
+ "Retrieved metadata: %s doesn't contain 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 runTestSpecTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents,
+ PrepareForIntegrationTestWithJava,
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/testing.go b/java/testing.go
index 6671bf0c7..5ae326d93 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -71,7 +71,17 @@ var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers(
// Needed for framework
defaultJavaDir + "/framework/aidl": nil,
// Needed for various deps defined in GatherRequiredDepsForTest()
- defaultJavaDir + "/a.java": nil,
+ defaultJavaDir + "/a.java": nil,
+ defaultJavaDir + "/api/current.txt": nil,
+ defaultJavaDir + "/api/removed.txt": nil,
+ defaultJavaDir + "/api/system-current.txt": nil,
+ defaultJavaDir + "/api/system-removed.txt": nil,
+ defaultJavaDir + "/api/test-current.txt": nil,
+ defaultJavaDir + "/api/test-removed.txt": nil,
+ defaultJavaDir + "/api/module-lib-current.txt": nil,
+ defaultJavaDir + "/api/module-lib-removed.txt": nil,
+ defaultJavaDir + "/api/system-server-current.txt": nil,
+ defaultJavaDir + "/api/system-server-removed.txt": nil,
// Needed for R8 rules on apps
"build/make/core/proguard.flags": nil,
@@ -108,8 +118,6 @@ var PrepareForTestWithDexpreoptWithoutFakeDex2oatd = android.GroupFixturePrepare
dexpreopt.PrepareForTestByEnablingDexpreopt,
)
-var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents)
-
// Prepare a fixture to use all java module types, mutators and singletons fully.
//
// This should only be used by tests that want to run with as much of the build enabled as possible.
@@ -220,6 +228,29 @@ func FixtureWithPrebuiltApisAndExtensions(apiLevel2Modules map[string][]string,
)
}
+func FixtureWithPrebuiltIncrementalApis(apiLevel2Modules map[string][]string) android.FixturePreparer {
+ mockFS := android.MockFS{}
+ path := "prebuilts/sdk/Android.bp"
+
+ bp := fmt.Sprintf(`
+ prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["%s"],
+ allow_incremental_platform_api: true,
+ imports_sdk_version: "none",
+ imports_compile_dex: true,
+ }
+ `, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`))
+
+ for release, modules := range apiLevel2Modules {
+ mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
+ }
+ return android.GroupFixturePreparers(
+ android.FixtureAddTextFile(path, bp),
+ android.FixtureMergeMockFs(mockFS),
+ )
+}
+
func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte {
libs := append([]string{"android"}, modules...)
@@ -352,6 +383,7 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterSystemModulesBuildComponents(ctx)
registerSystemserverClasspathBuildComponents(ctx)
registerLintBuildComponents(ctx)
+ android.RegisterApexContributionsBuildComponents(ctx)
}
// gatherRequiredDepsForTest gathers the module definitions used by
@@ -375,11 +407,22 @@ func gatherRequiredDepsForTest() string {
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
+ "android_stubs_current_exportable",
+ "android_system_stubs_current_exportable",
+ "android_test_stubs_current_exportable",
+ "android_module_lib_stubs_current_exportable",
+ "android_system_server_stubs_current_exportable",
+ "core.current.stubs.exportable",
+ "legacy.core.platform.api.stubs.exportable",
+
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
"kotlin-annotations",
"stub-annotations",
+
+ "aconfig-annotations-lib",
+ "unsupportedappusage",
}
for _, extra := range extraModules {
@@ -394,26 +437,98 @@ func gatherRequiredDepsForTest() string {
`, extra)
}
- extraApiLibraryModules := map[string]string{
- "android_stubs_current.from-text": "api/current.txt",
- "android_system_stubs_current.from-text": "api/system-current.txt",
- "android_test_stubs_current.from-text": "api/test-current.txt",
- "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt",
- "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt",
- "android_system_server_stubs_current.from-text": "api/system-server-current.txt",
- "core.current.stubs.from-text": "api/current.txt",
- "legacy.core.platform.api.stubs.from-text": "api/current.txt",
- "stable.core.platform.api.stubs.from-text": "api/current.txt",
- "core-lambda-stubs.from-text": "api/current.txt",
+ type droidstubsStruct struct {
+ name string
+ apiSurface string
+ apiFile string
+ removedFile string
+ }
+
+ var publicDroidstubs = droidstubsStruct{
+ name: "api-stubs-docs-non-updatable",
+ apiSurface: "public",
+ apiFile: "api/current.txt",
+ removedFile: "api/removed.txt",
+ }
+ var systemDroidstubs = droidstubsStruct{
+ name: "system-api-stubs-docs-non-updatable",
+ apiSurface: "system",
+ apiFile: "api/system-current.txt",
+ removedFile: "api/system-removed.txt",
+ }
+ var testDroidstubs = droidstubsStruct{
+ name: "test-api-stubs-docs-non-updatable",
+ apiSurface: "test",
+ apiFile: "api/test-current.txt",
+ removedFile: "api/test-removed.txt",
+ }
+ var moduleLibDroidstubs = droidstubsStruct{
+ name: "module-lib-api-stubs-docs-non-updatable",
+ apiSurface: "module-lib",
+ apiFile: "api/module-lib-current.txt",
+ removedFile: "api/module-lib-removed.txt",
+ }
+ var systemServerDroidstubs = droidstubsStruct{
+ // This module does not exist but is named this way for consistency
+ name: "system-server-api-stubs-docs-non-updatable",
+ apiSurface: "system-server",
+ apiFile: "api/system-server-current.txt",
+ removedFile: "api/system-server-removed.txt",
+ }
+ var droidstubsStructs = []droidstubsStruct{
+ publicDroidstubs,
+ systemDroidstubs,
+ testDroidstubs,
+ moduleLibDroidstubs,
+ systemServerDroidstubs,
}
- for libName, apiFile := range extraApiLibraryModules {
+ extraApiLibraryModules := map[string]droidstubsStruct{
+ "android_stubs_current.from-text": publicDroidstubs,
+ "android_system_stubs_current.from-text": systemDroidstubs,
+ "android_test_stubs_current.from-text": testDroidstubs,
+ "android_module_lib_stubs_current.from-text": moduleLibDroidstubs,
+ "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs,
+ "android_system_server_stubs_current.from-text": systemServerDroidstubs,
+ "core.current.stubs.from-text": publicDroidstubs,
+ "legacy.core.platform.api.stubs.from-text": publicDroidstubs,
+ "stable.core.platform.api.stubs.from-text": publicDroidstubs,
+ "core-lambda-stubs.from-text": publicDroidstubs,
+ "android-non-updatable.stubs.from-text": publicDroidstubs,
+ "android-non-updatable.stubs.system.from-text": systemDroidstubs,
+ "android-non-updatable.stubs.test.from-text": testDroidstubs,
+ "android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs,
+ "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs,
+ }
+
+ for _, droidstubs := range droidstubsStructs {
bp += fmt.Sprintf(`
- java_api_library {
- name: "%s",
- api_files: ["%s"],
- }
- `, libName, apiFile)
+ droidstubs {
+ name: "%s",
+ api_surface: "%s",
+ check_api: {
+ current: {
+ api_file: "%s",
+ removed_api_file: "%s",
+ }
+ }
+ }
+ `,
+ droidstubs.name,
+ droidstubs.apiSurface,
+ droidstubs.apiFile,
+ droidstubs.removedFile,
+ )
+ }
+
+ for libName, droidstubs := range extraApiLibraryModules {
+ bp += fmt.Sprintf(`
+ java_api_library {
+ name: "%s",
+ api_contributions: ["%s"],
+ stubs_type: "everything",
+ }
+ `, libName, droidstubs.name+".api.contribution")
}
bp += `
@@ -465,10 +580,15 @@ func gatherRequiredDepsForTest() string {
}
`
+ bp += `
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+`
return bp
}
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string {
t.Helper()
module := ctx.ModuleForTests(name, variant).Module()
deps := []string{}
@@ -477,11 +597,29 @@ func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, varia
})
sort.Strings(deps)
+ return 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) {
+ deps := getModuleDependencies(t, ctx, name, variant)
+
if actual := deps; !reflect.DeepEqual(expected, actual) {
t.Errorf("expected %#q, found %#q", expected, actual)
}
}
+// CheckModuleHasDependency returns true if the module depends on the expected dependency.
+func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, variant string, expected string) bool {
+ for _, dep := range getModuleDependencies(t, ctx, name, variant) {
+ if dep == expected {
+ return true
+ }
+ }
+ return false
+}
+
// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
// the platform-bootclasspath module.
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
@@ -494,7 +632,7 @@ func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult,
func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) {
t.Helper()
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
- info := result.ModuleProvider(p, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo)
+ info, _ := android.SingletonModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider)
android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated)
android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String())
@@ -514,7 +652,7 @@ func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module
func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
name := module.Name()
var apex string
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
apex = "platform"
} else {
@@ -573,7 +711,7 @@ var PrepareForTestWithFakeApexMutator = android.GroupFixturePreparers(
func registerFakeApexMutator(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex", fakeApexMutator).Parallel()
+ ctx.Transition("apex", &fakeApexMutator{})
})
}
@@ -588,16 +726,30 @@ var _ apexModuleBase = (*SdkLibrary)(nil)
// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex",
// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for
// testing without dealing with all the complexities in the real mutator.
-func fakeApexMutator(mctx android.BottomUpMutatorContext) {
- switch mctx.Module().(type) {
+type fakeApexMutator struct{}
+
+func (f *fakeApexMutator) Split(ctx android.BaseModuleContext) []string {
+ switch ctx.Module().(type) {
case *Library, *SdkLibrary:
- if len(mctx.Module().(apexModuleBase).ApexAvailable()) > 0 {
- modules := mctx.CreateVariations("", "apex1000")
- apexInfo := android.ApexInfo{
- ApexVariationName: "apex1000",
- }
- mctx.SetVariationProvider(modules[1], android.ApexInfoProvider, apexInfo)
+ return []string{"", "apex1000"}
+ }
+ return []string{""}
+}
+
+func (f *fakeApexMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (f *fakeApexMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ return incomingVariation
+}
+
+func (f *fakeApexMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if variation != "" {
+ apexInfo := android.ApexInfo{
+ ApexVariationName: "apex1000",
}
+ android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
}
}
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}
}