diff options
Diffstat (limited to 'java')
50 files changed, 3304 insertions, 1038 deletions
diff --git a/java/Android.bp b/java/Android.bp index 4af2a14eb..4450c4275 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -48,6 +48,7 @@ bootstrap_go_package { "droidstubs.go", "fuzz.go", "gen.go", + "generated_java_library.go", "genrule.go", "hiddenapi.go", "hiddenapi_modular.go", @@ -79,6 +80,7 @@ bootstrap_go_package { ], testSrcs: [ "aar_test.go", + "android_manifest_test.go", "androidmk_test.go", "app_import_test.go", "app_set_test.go", @@ -92,6 +94,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", diff --git a/java/aar.go b/java/aar.go index f1b137de1..180e1d726 100644 --- a/java/aar.go +++ b/java/aar.go @@ -31,10 +31,9 @@ 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 } @@ -89,35 +88,49 @@ 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"` } 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 + transitiveAaptResourcePackages android.Paths + 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] } type split struct { @@ -138,20 +151,23 @@ func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) { } } +func (a *aapt) useResourceProcessorBusyBox() bool { + return BoolDefault(a.aaptProperties.Use_resource_processor, false) +} + 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,8 +191,6 @@ 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") - // Find implicit or explicit asset and resource dirs assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") @@ -291,7 +305,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string, enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) { - transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags := + staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedDeps, libFlags := aaptLibs(ctx, sdkContext, classLoaderContexts) // Exclude any libraries from the supplied list. @@ -314,13 +328,20 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion, }) + staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.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...) + // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import + // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies + // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of + // android_library_import modules. If this is fixed, staticManifestsDepSet can be dropped completely in favor of + // staticResourcesNodesDepSet.manifests() + transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...) + + if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) { + a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], transitiveManifestPaths[1:], a.isLibrary) 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 @@ -333,14 +354,27 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath) - rroDirs = append(rroDirs, staticRRODirs...) linkFlags = append(linkFlags, libFlags...) - linkDeps = append(linkDeps, libDeps...) + linkDeps = append(linkDeps, sharedDeps...) + linkDeps = append(linkDeps, staticDeps.resPackages()...) linkFlags = append(linkFlags, extraLinkFlags...) if a.isLibrary { linkFlags = append(linkFlags, "--static-lib") } + if a.isLibrary && a.useResourceProcessorBusyBox() { + // When building an android_library using ResourceProcessorBusyBox the resources are merged into + // package-res.apk with --merge-only, but --no-static-lib-packages is not used so that R.txt only + // contains resources from this library. + linkFlags = append(linkFlags, "--merge-only") + } else { + // When building and app or when building an android_library without ResourceProcessorBusyBox + // --no-static-lib-packages is used to put all the resources into the app. If ResourceProcessorBusyBox + // is used then the app's R.txt will be post-processed along with the R.txt files from dependencies to + // sort resources into the right packages in R.class. + linkFlags = append(linkFlags, "--no-static-lib-packages") + } + 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") @@ -348,6 +382,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon 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 compiledResDirs []android.Paths for _, dir := range resDirs { @@ -363,7 +398,27 @@ 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() { + // 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 _, 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. @@ -404,12 +459,18 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon }) } + // 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, extraPackages, - linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages) + linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages) // 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 +481,142 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon a.assetPackage = android.OptionalPathForPath(assets) } + if a.useResourceProcessorBusyBox() { + rJar := android.PathForModuleOut(ctx, "busybox/R.jar") + resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary) + transitiveRJars = append(transitiveRJars, rJar) + a.rJar = rJar + } + a.aaptSrcJar = srcJar + a.transitiveAaptRJars = transitiveRJars + a.transitiveAaptResourcePackages = staticDeps.resPackages() 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(), + }). + 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() +} + +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) { + + 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() + } 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") + } + + 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 +} + +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) ( - transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) { - - var sharedLibs android.Paths + staticResourcesNodes *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 +629,10 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa sharedLibs = append(sharedLibs, sdkDep.jars...) } + var resourcesNodeDepSets []*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) @@ -469,32 +655,28 @@ 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) - } + resourcesNodeDepSets = append(resourcesNodeDepSets, aarDep.ResourcesNodeDepSet()) + rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet()) + manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet()) } } addCLCFromDep(ctx, module, classLoaderContexts) }) - deps = append(deps, sharedLibs...) - deps = append(deps, transitiveStaticLibs...) + // 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. + staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil, + android.ReverseSliceInPlace(resourcesNodeDepSets)) - if len(transitiveStaticLibs) > 0 { + staticRRODirs = rroDirsDepSetBuilder.Build() + staticManifests = manifestsDepSetBuilder.Build() + + if len(staticResourcesNodes.ToList()) > 0 { flags = append(flags, "--auto-add-overlay") } @@ -502,10 +684,7 @@ 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, staticRRODirs, staticManifests, sharedLibs, flags } type AndroidLibrary struct { @@ -516,8 +695,6 @@ type AndroidLibrary struct { androidLibraryProperties androidLibraryProperties aarFile android.WritablePath - - exportedStaticPackages android.Paths } var _ android.OutputFileProducer = (*AndroidLibrary)(nil) @@ -532,10 +709,6 @@ func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) { } } -func (a *AndroidLibrary) ExportedStaticPackages() android.Paths { - return a.exportedStaticPackages -} - var _ AndroidLibraryDependency = (*AndroidLibrary)(nil) func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -554,9 +727,14 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() - ctx.CheckbuildFile(a.proguardOptionsFile) - ctx.CheckbuildFile(a.exportPackage) - ctx.CheckbuildFile(a.aaptSrcJar) + a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName()) + + ctx.CheckbuildFile(a.aapt.proguardOptionsFile) + ctx.CheckbuildFile(a.aapt.exportPackage) + ctx.CheckbuildFile(a.aapt.aaptSrcJar) + if a.useResourceProcessorBusyBox() { + ctx.CheckbuildFile(a.aapt.rJar) + } // apps manifests are handled by aapt, don't let Module see them a.properties.Manifest = nil @@ -568,7 +746,22 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile) - a.Module.compile(ctx, a.aaptSrcJar) + var extraSrcJars android.Paths + var extraCombinedJars android.Paths + var extraClasspathJars android.Paths + if a.useResourceProcessorBusyBox() { + // 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, extraSrcJars, extraClasspathJars, extraCombinedJars) a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar") var res android.Paths @@ -579,19 +772,15 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) 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) { @@ -674,14 +863,18 @@ type AARImport struct { properties AARImportProperties - classpathFile android.WritablePath - proguardFlags android.WritablePath - exportPackage android.WritablePath - extraAaptPackagesFile android.WritablePath - manifest android.WritablePath - assetsPackage android.WritablePath + classpathFile android.WritablePath + proguardFlags android.WritablePath + exportPackage android.WritablePath + transitiveAaptResourcePackages android.Paths + extraAaptPackagesFile android.WritablePath + manifest android.WritablePath + assetsPackage android.WritablePath + rTxt android.WritablePath + rJar android.WritablePath - exportedStaticPackages android.Paths + resourcesNodesDepSet *android.DepSet[*resourcesNode] + manifestsDepSet *android.DepSet[android.Path] hideApexVariantFromMake bool @@ -738,25 +931,20 @@ 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 @@ -852,12 +1040,13 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar") a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml") + aarRTxt := extractedAARDir.Join(ctx, "R.txt") a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip") ctx.Build(pctx, android.BuildParams{ Rule: unzipAAR, Input: a.aarPath, - Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage}, + Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, aarRTxt}, Description: "unzip AAR", Args: map[string]string{ "outDir": extractedAARDir.String(), @@ -877,46 +1066,70 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 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") + a.rTxt = 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", } linkFlags = append(linkFlags, "--manifest "+a.manifest.String()) linkDeps = append(linkDeps, a.manifest) - transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags := + staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags := aaptLibs(ctx, android.SdkContext(a), nil) - _ = staticLibManifests - _ = staticRRODirs + _ = staticRRODirsDepSet + staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList()) - linkDeps = append(linkDeps, libDeps...) + linkDeps = append(linkDeps, sharedLibs...) + linkDeps = append(linkDeps, staticDeps.resPackages()...) linkFlags = append(linkFlags, libFlags...) - overlayRes := append(android.Paths{flata}, transitiveStaticLibs...) + overlayRes := android.Paths{flata} - aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile, + // 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, srcJar, proguardOptionsFile, a.rTxt, a.extraAaptPackagesFile, linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil) - // 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 - } + a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar") + resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true) + + 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) + // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import + // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies + // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of + // android_library_import modules. If this is fixed, AndroidLibraryDependency.ManifestsDepSet can be dropped + // completely in favor of AndroidLibraryDependency.ResourceNodesDepSet.manifest + //manifestDepSetBuilder.Transitive(transitiveStaticDeps.manifests) + _ = staticManifestsDepSet + a.manifestsDepSet = manifestDepSetBuilder.Build() + + a.transitiveAaptResourcePackages = staticDeps.resPackages() a.collectTransitiveHeaderJars(ctx) ctx.SetProvider(JavaInfoProvider, JavaInfo{ @@ -925,6 +1138,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars, ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile), ImplementationJars: android.PathsIfNonNil(a.classpathFile), + // TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts }) if proptools.Bool(a.properties.Extract_jni) { @@ -1056,7 +1270,7 @@ func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "aar_import", - Bzl_load_location: "//build/bazel/rules/android:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:aar_import.bzl", }, android.CommonAttributes{Name: name}, &bazelAndroidLibraryImport{ @@ -1086,7 +1300,7 @@ func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties { return bazel.BazelTargetModuleProperties{ Rule_class: "android_library", - Bzl_load_location: "//build/bazel/rules/android:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:android_library.bzl", } } diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go new file mode 100644 index 000000000..b12d77896 --- /dev/null +++ b/java/android_manifest_test.go @@ -0,0 +1,103 @@ +// 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" + "testing" +) + +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 := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithOverlayBuildComponents, + ).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/direct_import/android_common/aar/AndroidManifest.xml", + // TODO(b/288358614): Soong has historically not merged manifests from dependencies of + // android_library_import modules. + + }, + manifestMergerRule.Implicits) +} diff --git a/java/androidmk.go b/java/androidmk.go index 9c21633fb..82505e9e3 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -123,6 +123,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.dexpreopter.configPath != nil { entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath) } + + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles().ToList()) }, }, }) @@ -220,6 +222,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries { entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile) 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 +247,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 }, }, }} @@ -265,10 +269,12 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries { entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile) entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile) entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage) + entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackages) 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 }, }, }} @@ -295,6 +301,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { if len(binary.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled) } + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles().ToList()) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -340,6 +347,9 @@ func (app *AndroidApp) AndroidMkEntries() []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 +378,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) } } @@ -432,6 +447,10 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { } entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports) + + if app.Name() != "framework-res" { + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles().ToList()) + } }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -450,11 +469,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,10 +522,12 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries { } entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.exportPackage) + entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", a.transitiveAaptResourcePackages) 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.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true) + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles().ToList()) }) return entriesList @@ -684,6 +700,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 +734,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 +752,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/app.go b/java/app.go index 706f99a83..224bc8867 100755 --- a/java/app.go +++ b/java/app.go @@ -18,6 +18,7 @@ package java // related module types, including their override variants. import ( + "fmt" "path/filepath" "strings" @@ -33,8 +34,17 @@ import ( 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") +) + func RegisterAppBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_app", AndroidAppFactory) ctx.RegisterModuleType("android_test", AndroidTestFactory) @@ -115,6 +125,9 @@ 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"` } // android_app properties that can be overridden by override_android_app @@ -179,6 +192,8 @@ type AndroidApp struct { android.ApexBundleDepsInfo javaApiUsedByOutputFile android.ModuleOutPath + + privAppAllowlist android.OptionalPath } func (a *AndroidApp) IsInstallable() bool { @@ -189,8 +204,8 @@ 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 +220,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 { @@ -269,6 +288,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 != "" { @@ -492,7 +521,23 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { a.dexpreopter.preventInstall = a.appProperties.PreventInstall if ctx.ModuleName() != "framework-res" { - a.Module.compile(ctx, a.aaptSrcJar) + var extraSrcJars android.Paths + var extraClasspathJars android.Paths + var extraCombinedJars android.Paths + if a.useResourceProcessorBusyBox() { + // 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) } return a.dexJarFile.PathOrNil() @@ -591,7 +636,6 @@ func processMainCert(m android.ModuleBase, certPropValue string, certificates [] } } - return mainCertificate, certificates } @@ -599,6 +643,35 @@ 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 @@ -609,8 +682,17 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { 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.overridableDeviceProperties.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.overridableDeviceProperties.Stem, a.Name())) if ctx.ModuleName() == "framework-res" { // framework-res.apk is installed as system/framework/framework-res.apk @@ -734,11 +816,21 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile) a.bundleFile = bundleFile + allowlist := a.createPrivappAllowlist(ctx) + if allowlist != nil { + a.privAppAllowlist = android.OptionalPathForPath(allowlist) + } + apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) // 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 for _, extra := range a.extraOutputFiles { @@ -925,6 +1017,10 @@ func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android. // For OutputFileProducer interface func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) { switch tag { + // In some instances, it can be useful to reference the aapt-generated flags from another + // target, e.g., system server implements services declared in the framework-res manifest. + case ".aapt.proguardOptionsFile": + return []android.Path{a.proguardOptionsFile}, nil case ".aapt.srcjar": return []android.Path{a.aaptSrcJar}, nil case ".export-package.apk": @@ -1327,10 +1423,15 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo } } -// 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()) + 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 } @@ -1462,10 +1563,8 @@ func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, man // 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 { +func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk 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 @@ -1490,14 +1589,16 @@ func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *An props := bazel.BazelTargetModuleProperties{ Rule_class: "android_app_certificate", - Bzl_load_location: "//build/bazel/rules/android:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:android_app_certificate.bzl", } ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) } type manifestValueAttribute struct { - MinSdkVersion *string + MinSdkVersion *string + MaxSdkVersion *string + TargetSdkVersion *string } type bazelAndroidAppAttributes struct { @@ -1527,12 +1628,25 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { // 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 { + if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil { manifestValues.MinSdkVersion = &minSdkStr } } + maxSdkVersion := a.MaxSdkVersion(ctx) + if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() { + if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil { + manifestValues.MaxSdkVersion = &maxSdkStr + } + } + + targetSdkVersion := a.TargetSdkVersion(ctx) + if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() { + if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil { + manifestValues.TargetSdkVersion = &targetSdkStr + } + } + appAttrs := &bazelAndroidAppAttributes{ // TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES Custom_package: a.overridableAppProperties.Package_name, @@ -1543,7 +1657,7 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { props := bazel.BazelTargetModuleProperties{ Rule_class: "android_binary", - Bzl_load_location: "//build/bazel/rules/android:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", } if !bp2BuildInfo.hasKotlin { @@ -1573,7 +1687,7 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { ctx.CreateBazelTargetModule( props, - android.CommonAttributes{Name: a.Name()}, + android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, appAttrs, ) diff --git a/java/app_builder.go b/java/app_builder.go index d20a6bfe4..d397ff7f5 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -225,8 +225,6 @@ func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePat }) } -const jniJarOutputPathString = "jniJarOutput.zip" - func TransformJniLibsToJar( ctx android.ModuleContext, outputFile android.WritablePath, @@ -258,7 +256,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 +267,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..ad1765e9d 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -17,6 +17,7 @@ package java // This file contains the module implementations for android_app_import and android_test_import. import ( + "fmt" "reflect" "github.com/google/blueprint" @@ -49,6 +50,28 @@ var ( CommandDeps: []string{"${config.Zip2ZipCmd}"}, Description: "Uncompress dex files", }) + + checkDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-dex-libs-are-uncompressed", blueprint.RuleParams{ + // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed + Command: "if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " + + "echo $in: Contains compressed JNI libraries and/or dex files >&2;" + + "exit 1; " + + "else " + + "touch $out; " + + "fi", + Description: "Check for compressed JNI libs or dex files", + }) + + checkJniLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-libs-are-uncompressed", blueprint.RuleParams{ + // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed + Command: "if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " + + "echo $in: Contains compressed JNI libraries >&2;" + + "exit 1; " + + "else " + + "touch $out; " + + "fi", + Description: "Check for compressed JNI libs or dex files", + }) ) func RegisterAppImportBuildComponents(ctx android.RegistrationContext) { @@ -73,8 +96,6 @@ type AndroidAppImport struct { usesLibrary usesLibrary - preprocessed bool - installPath android.InstallPath hideApexVariantFromMake bool @@ -128,6 +149,13 @@ 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 } func (a *AndroidAppImport) IsInstallable() bool { @@ -201,7 +229,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 +247,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 } @@ -297,7 +325,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) if a.usesLibrary.enforceUsesLibraries() { - srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk) + a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk) } a.dexpreopter.dexpreopt(ctx, jnisUncompressed) @@ -317,8 +345,22 @@ 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) { + var output android.WritablePath + if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) { + output = android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename) + a.validatePreprocessedApk(ctx, srcApk, output) + } else { + // If using the input APK unmodified, still make a copy of it so that the output filename has the + // right basename. + output = android.PathForModuleOut(ctx, apkFilename) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: srcApk, + Output: output, + }) + } + 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. @@ -352,6 +394,44 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // TODO: androidmk converter jni libs } +func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) { + var validations android.Paths + + alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp") + ctx.Build(pctx, android.BuildParams{ + Rule: checkZipAlignment, + Input: srcApk, + Output: alignmentStamp, + }) + + validations = append(validations, alignmentStamp) + jniCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "jni_compression.stamp") + ctx.Build(pctx, android.BuildParams{ + Rule: checkJniLibsAreUncompressedRule, + Input: srcApk, + Output: jniCompressionStamp, + }) + validations = append(validations, jniCompressionStamp) + + if a.Privileged() { + // It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides + dexCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "dex_compression.stamp") + ctx.Build(pctx, android.BuildParams{ + Rule: checkDexLibsAreUncompressedRule, + Input: srcApk, + Output: dexCompressionStamp, + }) + validations = append(validations, dexCompressionStamp) + } + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: srcApk, + Output: dstApk, + Validations: validations, + }) +} + func (a *AndroidAppImport) Prebuilt() *android.Prebuilt { return &a.prebuilt } @@ -364,6 +444,15 @@ func (a *AndroidAppImport) OutputFile() android.Path { return a.outputFile } +func (a *AndroidAppImport) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + return []android.Path{a.outputFile}, nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + func (a *AndroidAppImport) JacocoReportClassesFile() android.Path { return nil } @@ -376,6 +465,10 @@ func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath { return a.provenanceMetaDataFile } +func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath { + return android.OptionalPath{} +} + var dpiVariantGroupType reflect.Type var archVariantGroupType reflect.Type var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"} @@ -487,11 +580,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 +596,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,7 +616,6 @@ 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.processVariants(ctx) diff --git a/java/app_import_test.go b/java/app_import_test.go index 80930248e..bb8fab93b 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -657,6 +657,29 @@ func TestAndroidTestImport_Preprocessed(t *testing.T) { } } +func TestAndroidAppImport_Preprocessed(t *testing.T) { + ctx, _ := testJava(t, ` + android_app_import { + name: "foo", + apk: "prebuilts/apk/app.apk", + presigned: true, + preprocessed: true, + } + `) + + apkName := "foo.apk" + variant := ctx.ModuleForTests("foo", "android_common") + outputBuildParams := variant.Output("validated-prebuilt/" + apkName).BuildParams + if outputBuildParams.Rule.String() != android.Cp.String() { + t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String()) + } + + // Make sure compression and aligning were validated. + if len(outputBuildParams.Validations) != 2 { + t.Errorf("Expected compression/alignment validation rules, found %d validations", len(outputBuildParams.Validations)) + } +} + func TestAndroidTestImport_UncompressDex(t *testing.T) { testCases := []struct { name string diff --git a/java/app_test.go b/java/app_test.go index b154bc990..8474ea7d6 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -443,9 +443,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()) @@ -599,7 +599,7 @@ func TestLibraryAssets(t *testing.T) { android_library { name: "lib3", sdk_version: "current", - static_libs: ["lib4"], + static_libs: ["lib4", "import"], } android_library { @@ -607,6 +607,12 @@ func TestLibraryAssets(t *testing.T) { sdk_version: "current", asset_dirs: ["assets_b"], } + + android_library_import { + name: "import", + sdk_version: "current", + aars: ["import.aar"], + } ` testCases := []struct { @@ -616,11 +622,12 @@ func TestLibraryAssets(t *testing.T) { }{ { 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,10 +639,6 @@ 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", @@ -717,7 +720,514 @@ 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 + + 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 + }{ + { + // 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/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/direct/android_common/turbine-combined/direct.jar", + "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.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/aar/classes-combined.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/aar/classes-combined.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/aar/classes-combined.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, + + 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, + + 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/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/direct/android_common/turbine-combined/direct.jar", + "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + }, + appCombined: []string{ + "out/soong/.intermediates/app/android_common/busybox/R.jar", + "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/aar/classes-combined.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/transitive_import/android_common/busybox/R.jar", + "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar", + "out/soong/.intermediates/transitive/android_common/busybox/R.jar", + "out/soong/.intermediates/direct/android_common/busybox/R.jar", + "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", + "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.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/aar/classes-combined.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, + + 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/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/direct/android_common/turbine-combined/direct.jar", + "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + }, + appCombined: []string{ + "out/soong/.intermediates/app/android_common/busybox/R.jar", + "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/aar/classes-combined.jar", + }, + + dontVerifyDirect: true, + dontVerifyTransitive: 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/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/direct/android_common/turbine-combined/direct.jar", + "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.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/aar/classes-combined.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/transitive_import/android_common/busybox/R.jar", + "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar", + "out/soong/.intermediates/direct/android_common/busybox/R.jar", + "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", + "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.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/aar/classes-combined.jar", + }, + + dontVerifyTransitive: 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/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/direct/android_common/turbine-combined/direct.jar", + "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.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/aar/classes-combined.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/aar/classes-combined.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/aar/classes-combined.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, + + 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", + 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_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) + + fs := android.MockFS{ + "app/res/values/strings.xml": nil, + "direct/res/values/strings.xml": nil, + "transitive/res/values/strings.xml": nil, + } + + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithOverlayBuildComponents, + 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") + 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.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 @@ -943,7 +1453,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 +1742,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 +1875,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) } @@ -1456,7 +1966,7 @@ func TestJNISDK(t *testing.T) { 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 +2986,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++ { @@ -2645,7 +3155,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) @@ -2693,52 +3203,11 @@ func TestUsesLibraries(t *testing.T) { `--optional-uses-library baz ` 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/product_packages.txt") } func TestDexpreoptBcp(t *testing.T) { @@ -3547,3 +4016,124 @@ 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", + ) +} diff --git a/java/base.go b/java/base.go index 991132321..f5eb01c4b 100644 --- a/java/base.go +++ b/java/base.go @@ -20,6 +20,8 @@ import ( "strconv" "strings" + "android/soong/ui/metrics/bp2build_metrics_proto" + "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" @@ -79,6 +81,9 @@ 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"` @@ -184,6 +189,9 @@ 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"` } // Properties that are specific to device modules. Host module factories should not add these when @@ -493,6 +501,21 @@ 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 + + // Aconfig "cache files" that went directly into this module. Transitive ones are + // tracked via JavaInfo.TransitiveAconfigFiles + // TODO: Extract to something standalone to propagate tags via GeneratedJavaLibraryModule + aconfigIntermediates android.Paths + + // Aconfig files for all transitive deps. Also exposed via JavaInfo + transitiveAconfigFiles *android.DepSet[android.Path] } func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { @@ -724,6 +747,8 @@ 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. @@ -1036,7 +1061,11 @@ func (j *Module) AddJSONData(d *map[string]interface{}) { } -func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { +func (module *Module) addGeneratedSrcJars(path android.Path) { + module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path) +} + +func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) { j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs) deps := j.collectDeps(ctx) @@ -1074,16 +1103,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) @@ -1118,6 +1146,11 @@ 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...) + 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 @@ -1211,8 +1244,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. } + extraJars := append(android.CopyOf(extraCombinedJars), kotlinHeaderJars...) headerJarFileWithoutDepsOrJarjar, j.headerJarFile = - j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars) + j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars) if ctx.Failed() { return } @@ -1241,8 +1275,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) @@ -1362,6 +1397,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { jars = append(jars, servicesJar) } + jars = append(android.CopyOf(extraCombinedJars), jars...) + // Combine the classes built from sources, any manifests, and any static libraries into // classes.jar. If there is only one input jar this step will be skipped. var outputFile android.OutputPath @@ -1372,12 +1409,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 +1491,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) @@ -1592,6 +1643,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { ctx.CheckbuildFile(outputFile) + j.collectTransitiveAconfigFiles(ctx) + ctx.SetProvider(JavaInfoProvider, JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars, @@ -1606,6 +1659,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { ExportedPluginClasses: j.exportedPluginClasses, ExportedPluginDisableTurbine: j.exportedDisableTurbine, JacocoReportClassesFile: j.jacocoReportClassesFile, + TransitiveAconfigFiles: j.transitiveAconfigFiles, }) // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource @@ -1635,13 +1689,15 @@ 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() { extractionFile := android.PathForModuleOut(ctx, kzipName) @@ -1649,6 +1705,10 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i j.kytheFiles = append(j.kytheFiles, extractionFile) } + if len(flags.processorPath) > 0 { + j.annoSrcJars = append(j.annoSrcJars, annoSrcJar) + } + return classes } @@ -1734,24 +1794,24 @@ 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()) { @@ -1828,6 +1888,7 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { 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,7 +1926,10 @@ 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 { @@ -1876,6 +1940,34 @@ func (j *Module) IsInstallable() bool { return Bool(j.properties.Installable) } +func (j *Module) collectTransitiveAconfigFiles(ctx android.ModuleContext) { + // Aconfig files from this module + mine := j.aconfigIntermediates + + // Aconfig files from transitive dependencies + fromDeps := []*android.DepSet[android.Path]{} + ctx.VisitDirectDeps(func(module android.Module) { + dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) + if dep.TransitiveAconfigFiles != nil { + fromDeps = append(fromDeps, dep.TransitiveAconfigFiles) + } + }) + + // DepSet containing aconfig files myself and from dependencies + j.transitiveAconfigFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps) +} + +func (j *Module) AddAconfigIntermediate(path android.Path) { + j.aconfigIntermediates = append(j.aconfigIntermediates, path) +} + +func (j *Module) getTransitiveAconfigFiles() *android.DepSet[android.Path] { + if j.transitiveAconfigFiles == nil { + panic(fmt.Errorf("java.Moduile: getTransitiveAconfigFiles called before collectTransitiveAconfigFiles module=%s", j.Name())) + } + return j.transitiveAconfigFiles +} + type sdkLinkType int const ( @@ -1923,19 +2015,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 } @@ -2177,7 +2272,7 @@ var _ ModuleWithStem = (*Module)(nil) func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { switch ctx.ModuleType() { - case "java_library", "java_library_host", "java_library_static": + case "java_library", "java_library_host", "java_library_static", "tradefed_java_library_host": if lib, ok := ctx.Module().(*Library); ok { javaLibraryBp2Build(ctx, lib) } @@ -2185,5 +2280,11 @@ func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { if binary, ok := ctx.Module().(*Binary); ok { javaBinaryHostBp2Build(ctx, binary) } + case "java_test_host": + if testHost, ok := ctx.Module().(*TestHost); ok { + javaTestHostBp2Build(ctx, testHost) + } + default: + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") } } diff --git a/java/bootclasspath.go b/java/bootclasspath.go index f4cef7fa6..c7dc3afae 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}, @@ -185,6 +185,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..dcc2dece7 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -242,7 +242,7 @@ type BootclasspathFragmentModule struct { modulePaths []string // Path to the boot image profile. - profilePath android.Path + profilePath android.WritablePath } // 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 } @@ -295,9 +285,6 @@ func bootclasspathFragmentFactory() android.Module { return } } - - // Initialize the contents property from the image_name. - bootclasspathFragmentInitContentsFromImage(ctx, m) }) return m } @@ -308,9 +295,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 +317,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 +354,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{}) // 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 +371,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. @@ -479,8 +441,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) } @@ -505,7 +465,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // unused prebuilt that was created without instrumentation from breaking an instrumentation // build. if isActiveModule(ctx.Module()) { - b.bootclasspathImageNameContentsConsistencyCheck(ctx) + b.bootclasspathFragmentPropertyCheck(ctx) } // Generate classpaths.proto config @@ -525,34 +485,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 @@ -566,45 +507,37 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo } } -// 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 { - // 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 +// 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.Module()) { + 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 + // Bootclasspath fragment modules that are for the platform do not produce boot related files. + apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) + 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. @@ -625,12 +558,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) @@ -656,25 +589,6 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) return jars } -func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { - // Get a map of the image configs that are supported. - imageConfigs := genBootImageConfigs(ctx) - - // Retrieve the config for this image. - imageNamePtr := b.properties.Image_name - if imageNamePtr == nil { - return nil - } - - 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 - } - return imageConfig -} - // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { @@ -857,48 +771,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 +809,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 } @@ -1194,39 +1078,19 @@ 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{} +// 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 } di := android.FindDeapexerProviderForModule(ctx) if di == nil { - return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule. + return nil // An error has been reported by FindDeapexerProviderForModule. } - profile := (android.WritablePath)(nil) - if imageConfig.profileInstallPathInApex != "" { - profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex) - } - - // 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{} - } - // 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 { @@ -1241,14 +1105,10 @@ 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 } @@ -1264,9 +1124,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..888caad16 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, + } `) } diff --git a/java/builder.go b/java/builder.go index 462626712..debf49a00 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() }) @@ -246,6 +258,25 @@ var ( CommandDeps: []string{"${config.ZipAlign}"}, }, ) + + checkZipAlignment = pctx.AndroidStaticRule("checkzipalign", + blueprint.RuleParams{ + Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " + + "echo $in: Improper package alignment >&2; " + + "exit 1; " + + "else " + + "touch $out; " + + "fi", + CommandDeps: []string{"${config.ZipAlign}"}, + Description: "Check zip alignment", + }, + ) + + convertImplementationJarToHeaderJarRule = pctx.AndroidStaticRule("convertImplementationJarToHeaderJar", + blueprint.RuleParams{ + Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`, + CommandDeps: []string{"${config.Zip2ZipCmd}"}, + }) ) func init() { @@ -292,8 +323,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 +338,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 @@ -475,7 +512,7 @@ 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) { @@ -522,11 +559,12 @@ 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, @@ -537,6 +575,7 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab "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(), }, }) @@ -600,6 +639,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{ diff --git a/java/config/config.go b/java/config/config.go index b82a137e7..83c27d309 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -98,7 +98,7 @@ func init() { "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex", }, dexerJavaVmFlagsList...)) exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{ - "-JXmx2048M", + "-JXmx4096M", "-JDcom.android.tools.r8.emitRecordAnnotationsInDex", "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex", "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex", @@ -148,6 +148,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") diff --git a/java/config/makevars.go b/java/config/makevars.go index 273aca0b4..4e0919537 100644 --- a/java/config/makevars.go +++ b/java/config/makevars.go @@ -28,7 +28,8 @@ 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}") diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index 958f4cead..de9a82d09 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -33,19 +33,45 @@ 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", + dist: { + targets: dist_targets, + }, +} + +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", +} - dist: { - targets: dist_targets, +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", + ], + }, }, } @@ -120,12 +146,43 @@ 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 +192,6 @@ java_library { "conscrypt.module.public.api.stubs", "i18n.module.public.api.stubs", ], - sdk_version: "none", - system_modules: "none", - visibility: ["//visibility:private"], } // Produces a dist file that is used by the @@ -199,18 +253,46 @@ 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", 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_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 +315,38 @@ 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_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 diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp index 813187e54..c46f8b8ea 100644 --- a/java/core-libraries/TxtStubLibraries.bp +++ b/java/core-libraries/TxtStubLibraries.bp @@ -22,8 +22,6 @@ java_system_modules { 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 { @@ -36,8 +34,6 @@ java_library { "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 @@ -47,8 +43,6 @@ java_system_modules { 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 { @@ -61,26 +55,26 @@ java_library { "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 { +java_api_library { name: "core.module_lib.stubs.from-text", - static_libs: [ - "art.module.public.api.stubs.module_lib.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", - // Replace the following with the module-lib correspondence when Conscrypt or i18N module + // 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.from-text", - "i18n.module.public.api.stubs.from-text", + "conscrypt.module.public.api.stubs.source.api.contribution", + "i18n.module.public.api.stubs.source.api.contribution", + ], + libs: [ + "stub-annotations", ], - 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 @@ -91,8 +85,6 @@ java_system_modules { "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 { @@ -108,8 +100,6 @@ java_library { "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 @@ -120,8 +110,6 @@ java_system_modules { "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 { @@ -137,8 +125,6 @@ java_library { "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 { @@ -151,6 +137,4 @@ java_api_library { // 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..5460dc993 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -143,6 +143,8 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont ResourceJars: d.resourceJars, SrcJarArgs: d.srcJarArgs, SrcJarDeps: d.srcJarDeps, + // TODO: Not sure if aconfig flags that have been moved between device and host variants + // make sense. }) } diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go index 3c9a0f3f1..3413da03d 100644 --- a/java/device_host_converter_test.go +++ b/java/device_host_converter_test.go @@ -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(), ":") diff --git a/java/dex.go b/java/dex.go index 4d6aa3456..7e7da00fd 100644 --- a/java/dex.go +++ b/java/dex.go @@ -140,7 +140,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", `$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` + `--no-data-resources ` + `-printmapping ${outDict} ` + - `--pg-conf-output ${outConfig} ` + + `-printconfiguration ${outConfig} ` + `-printusage ${outUsage} ` + `--deps-file ${out}.d ` + `$r8Flags && ` + @@ -161,7 +161,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}"}, ExecStrategy: "${config.RER8ExecStrategy}", ToolchainInputs: []string{"${config.JavaCmd}"}, Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, @@ -399,13 +399,16 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam args["implicits"] = strings.Join(r8Deps.Strings(), ",") } ctx.Build(pctx, android.BuildParams{ - Rule: rule, - Description: "r8", - Output: javalibJar, - ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip}, - Input: dexParams.classesJar, - Implicits: r8Deps, - Args: args, + Rule: rule, + Description: "r8", + Output: javalibJar, + ImplicitOutputs: android.WritablePaths{ + proguardDictionary, + proguardUsageZip, + proguardConfiguration}, + Input: dexParams.classesJar, + Implicits: r8Deps, + Args: args, }) } else { d8Flags, d8Deps := d8Flags(dexParams.flags) diff --git a/java/dexpreopt.go b/java/dexpreopt.go index a96b31281..998730e08 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -16,6 +16,7 @@ package java import ( "path/filepath" + "sort" "strings" "android/soong/android" @@ -390,7 +391,37 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr 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", "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", "dexpreopt product_packages") + + dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( + ctx, globalSoong, global, dexpreoptConfig, appProductPackages) if err != nil { ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) return diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index f477f404e..003f2de22 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -16,7 +16,6 @@ package java import ( "path/filepath" - "sort" "strings" "android/soong/android" @@ -224,6 +223,11 @@ var artApexNames = []string{ "com.google.android.art.testing", } +var ( + dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"} + dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments") +) + func init() { RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext) } @@ -241,6 +245,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 +264,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 @@ -296,10 +299,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 +386,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 +460,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,39 +502,90 @@ 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. -} - -// 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) + } + + 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) + } +} + +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(child) { + return false + } + tag := ctx.OtherModuleDependencyTag(child) + if tag == platformBootclasspathDepTag { + return true + } + if tag == bootclasspathFragmentDepTag { + apexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo) + 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) + for _, name := range getImageNames() { + config := imageConfigs[name] + if config != d.defaultBootImage { d.otherImages = append(d.otherImages, config) } + if !config.isEnabled(ctx) { + continue + } + generateBootImage(ctx, config) + if config == d.defaultBootImage { + bootFrameworkProfileRule(ctx, config) + } } } +// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make. +func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) { + d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config") + writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake) +} + // shouldBuildBootImages determines whether boot images should be built. func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool { // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths @@ -537,6 +598,101 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig return true } +func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) { + 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 := bootImageProfileRule(ctx, imageConfig) + + // If dexpreopt of boot image jars should be skipped, stop after generating a profile. + if SkipDexpreoptBootJars(ctx) { + 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) + + // Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes. + dumpOatRules(ctx, imageConfig) +} + +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 { + encodedDexJarsByModuleName := bootDexJarByModule{} + for _, pair := range apexJarModulePairs { + var path android.Path + 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. + path = 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 := ctx.OtherModuleProvider(fragment, BootclasspathFragmentApexContentInfoProvider).(BootclasspathFragmentApexContentInfo) + jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule) + if err != nil { + ctx.ModuleErrorf("%s", err) + } + path = jar + } + encodedDexJarsByModuleName.addPath(pair.jarModule, path) + } + return encodedDexJarsByModuleName +} + // 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) { @@ -687,10 +843,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() @@ -712,36 +870,31 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p 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 { + fragment := getBootclasspathFragmentByApex(ctx, apex) + if fragment == nil { + ctx.ModuleErrorf("Boot image config '%[1]s' 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", + image.name, + apex) + return bootImageVariantOutputs{} + } + importedProfile := fragment.(commonBootclasspathFragment).getProfilePath() + 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 +942,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 +951,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,7 +973,7 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]) } - if global.EnableUffdGc { + if global.EnableUffdGc && image.target.Os == android.Android { cmd.Flag("--runtime-arg").Flag("-Xgc:CMC") } @@ -881,11 +1038,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,28 +1065,39 @@ 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) + rule.Build("bootJarsProfile_"+name, "profile boot jars "+name) + + return profile +} + +func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath { + if !image.isProfileGuided() { + return nil + } + + profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps) + if image == defaultBootImageConfig(ctx) { + rule := android.NewRuleBuilder(pctx, 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", "profile boot jars") - return profile } @@ -972,6 +1136,8 @@ func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) { var allPhonies android.Paths + name := image.name + global := dexpreopt.GetGlobalConfig(ctx) for _, image := range image.variants { arch := image.target.Arch.ArchType suffix := arch.String() @@ -980,36 +1146,39 @@ 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 global.EnableUffdGc && image.target.Os == android.Android { + cmd.Flag("--runtime-arg").Flag("-Xgc:CMC") + } + 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, }) } @@ -1044,11 +1213,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 +1236,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..7499481de 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 diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 9100e87c6..0f4bd9b34 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, 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,6 +198,18 @@ func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig { return genBootImageConfigs(ctx)[mainlineBootImageName] } +// 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 +} + // 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. @@ -218,8 +235,7 @@ var updatableBootConfigKey = android.NewOnceKey("apexBootConfig") 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") + dir := android.PathForOutput(ctx, getDexpreoptDirName(ctx), "apex_bootjars") dexPaths := apexBootJars.BuildPaths(ctx, dir) dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir) @@ -250,8 +266,6 @@ func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.Writa var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath") -var copyOf = android.CopyOf - func init() { android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars) } @@ -260,6 +274,11 @@ 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() +func getDexpreoptDirName(ctx android.PathContext) string { + prefix := "dexpreopt_" + targets := ctx.Config().Targets[android.Android] + if len(targets) > 0 { + return prefix+targets[0].Arch.ArchType.String() + } + return prefix+"unknown_target" } 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..176c251fd 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,6 +513,10 @@ 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, }, @@ -805,8 +898,8 @@ 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, } @@ -1136,7 +1229,6 @@ func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expe 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()) @@ -1195,10 +1287,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 +1299,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 +1315,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 +1330,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 +1344,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/droiddoc.go b/java/droiddoc.go index dbe021d00..d4ead12c8 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -608,6 +608,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")" `) diff --git a/java/droidstubs.go b/java/droidstubs.go index 8a521aabb..bb2388f96 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -525,8 +525,7 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":") } - cmd.Flag("--no-banner"). - Flag("--color"). + cmd.Flag("--color"). Flag("--quiet"). Flag("--format=v2"). FlagWithArg("--repeat-errors-max ", "10"). @@ -535,6 +534,14 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi // b/223382732 FlagWithArg("--hide ", "ChangedDefault") + // Force metalava to ignore classes on the classpath when an API file contains missing classes. + // See b/285140653 for more information. + cmd.FlagWithArg("--api-class-resolution ", "api") + + // Force metalava to sort overloaded methods by their order in the source code. + // See b/285312164 for more information. + cmd.FlagWithArg("--api-overloaded-method-order ", "source") + return cmd } diff --git a/java/fuzz.go b/java/fuzz.go index 2b9e22b8e..b3c2fd47c 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 { @@ -78,7 +82,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...) @@ -150,7 +165,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" } @@ -175,11 +192,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/generated_java_library.go b/java/generated_java_library.go new file mode 100644 index 000000000..f9baa85e4 --- /dev/null +++ b/java/generated_java_library.go @@ -0,0 +1,94 @@ +// 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 +} + +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 +} + +// 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) + android.InitBazelModule(module) + InitJavaModule(module, android.HostAndDeviceSupported) + if properties != nil { + module.AddProperties(properties) + } + return module +} + +func (module *GeneratedJavaLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) { + module.callbacks.DepsMutator(module, ctx) + 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) + // No additional libraries. The generator should add anything necessary automatically + // by returning something from ____ (TODO: Additional libraries aren't needed now, so + // these are just blocked). + checkPropertyEmpty(ctx, module, "libs", module.Library.properties.Libs) + checkPropertyEmpty(ctx, module, "static_libs", module.Library.properties.Static_libs) + // 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 := module.callbacks.GenerateSourceJarBuildActions(module, ctx) + module.Library.properties.Generated_srcjars = append(module.Library.properties.Generated_srcjars, srcJarPath) + module.Library.GenerateAndroidBuildActions(ctx) +} diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go new file mode 100644 index 000000000..7f52fd108 --- /dev/null +++ b/java/generated_java_library_test.go @@ -0,0 +1,66 @@ +// 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 { + module.AddAconfigIntermediate(android.PathForOutput(ctx, "aconfig_cache_file")) + return android.PathForOutput(ctx, "blah.srcjar") +} + +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/hiddenapi.go b/java/hiddenapi.go index d25096b15..4d08b8307 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -106,7 +106,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 } diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index c6176e67c..f31f5d1a8 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -236,9 +236,9 @@ 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)) + 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") @@ -1236,7 +1236,6 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix s rule := android.NewRuleBuilder(pctx, ctx) rule.Command(). BuiltTool("metalava"). - Flag("--no-banner"). Inputs(removedTxtFiles). FlagWithOutput("--dex-api ", output) rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix) diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 52934a327..8ec17971a 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 } @@ -166,7 +166,7 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu // 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/java.go b/java/java.go index 683e54682..f29f7383a 100644 --- a/java/java.go +++ b/java/java.go @@ -73,8 +73,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel() }) - ctx.RegisterSingletonType("logtags", LogtagsSingleton) - ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) + ctx.RegisterParallelSingletonType("logtags", LogtagsSingleton) + ctx.RegisterParallelSingletonType("kythe_java_extract", kytheExtractJavaFactory) } func RegisterJavaSdkMemberTypes() { @@ -231,10 +231,10 @@ type JavaInfo struct { HeaderJars 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. @@ -273,6 +273,15 @@ type JavaInfo struct { // JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be // instrumented by jacoco. JacocoReportClassesFile android.Path + + // set of aconfig flags for all transitive libs deps + // TODO(joeo): It would be nice if this were over in the aconfig package instead of here. + // In order to do that, generated_java_library would need a way doing + // collectTransitiveAconfigFiles with one of the callbacks, and having that automatically + // propagated. If we were to clean up more of the stuff on JavaInfo that's not part of + // core java rules (e.g. AidlIncludeDirs), then maybe adding more framework to do that would be + // worth it. + TransitiveAconfigFiles *android.DepSet[android.Path] } var JavaInfoProvider = blueprint.NewProvider(JavaInfo{}) @@ -456,7 +465,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...) @@ -672,6 +683,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.minSdkVersion = j.MinSdkVersion(ctx) j.maxSdkVersion = j.MaxSdkVersion(ctx) + j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName()) + apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) if !apexInfo.IsForPlatform() { j.hideApexVariantFromMake = true @@ -686,7 +699,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) } - j.compile(ctx, nil) + j.compile(ctx, nil, nil, nil) // Collect the module directory for IDE info in java/jdeps.go. j.modulePaths = append(j.modulePaths, ctx.ModuleDir()) @@ -724,6 +737,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { } }) j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles) + } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -813,7 +827,10 @@ 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()) + canonical, err := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String()) + if err != nil { + ctx.ModuleErrorf("%s", err) + } p.MinSdkVersion = proptools.StringPtr(canonical) } @@ -931,6 +948,10 @@ type TestOptions struct { // Extra <option> tags to add to the auto generated test xml file. The "key" // is optional in each of these. Tradefed_options []tradefed.Option + + // Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., AndroidJunitTest. + // The "key" is optional in each of these. + Test_runner_options []tradefed.Option } type testProperties struct { @@ -1213,6 +1234,7 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, TestSuites: j.testProperties.Test_suites, Config: configs, OptionsForAutogenerated: j.testProperties.Test_options.Tradefed_options, + TestRunnerOptions: j.testProperties.Test_options.Test_runner_options, AutoGenConfig: j.testProperties.Auto_gen_config, UnitTest: j.testProperties.Test_options.Unit_test, DeviceTemplate: "${JavaTestConfigTemplate}", @@ -1411,6 +1433,8 @@ func TestHostFactory() android.Module { nil, nil) + android.InitBazelModule(module) + InitJavaModuleMultiTargets(module, android.HostSupported) return module @@ -1454,6 +1478,8 @@ func (j *Binary) HostToolPath() android.OptionalPath { } func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName()) + if ctx.Arch().ArchType == android.Common { // Compile the jar if j.binaryProperties.Main_class != nil { @@ -1610,13 +1636,6 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon }) } -type JavaApiLibraryDepsInfo struct { - JavaInfo - StubsSrcJar android.Path -} - -var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{}) - type ApiLibrary struct { android.ModuleBase android.DefaultableModuleBase @@ -1645,7 +1664,7 @@ type JavaApiLibraryProperties struct { // 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 + Api_files []string `android:"path"` // List of flags to be passed to the javac compiler to generate jar file Javacflags []string @@ -1658,10 +1677,11 @@ 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 } func ApiLibraryFactory() android.Module { @@ -1708,8 +1728,7 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, 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"). @@ -1723,6 +1742,14 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, FlagWithArg("--hide ", "InvalidNullabilityOverride"). FlagWithArg("--hide ", "ChangedDefault") + // Force metalava to ignore classes on the classpath when an API file contains missing classes. + // See b/285140653 for more information. + cmd.FlagWithArg("--api-class-resolution ", "api") + + // Force metalava to sort overloaded methods by their order in the source code. + // See b/285312164 for more information. + cmd.FlagWithArg("--api-overloaded-method-order ", "source") + return cmd } @@ -1740,35 +1767,37 @@ 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. +// 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"). 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) { @@ -1778,8 +1807,8 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { } 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)) } } @@ -1801,14 +1830,14 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { var srcFiles android.Paths var classPaths android.Paths var staticLibs android.Paths - var depApiSrcsStubsSrcJar android.Path + var depApiSrcsStubsJar android.Path 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 { + if providerApiFile == nil && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name()) } srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String())) @@ -1819,20 +1848,17 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) staticLibs = append(staticLibs, provider.HeaderJars...) case depApiSrcsTag: - provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo) - classPaths = append(classPaths, provider.HeaderJars...) - depApiSrcsStubsSrcJar = provider.StubsSrcJar + provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) + depApiSrcsStubsJar = provider.HeaderJars[0] } }) // 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)) + srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api)) } - if srcFiles == nil { + if srcFiles == nil && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName()) } @@ -1841,31 +1867,33 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { al.stubsFlags(ctx, cmd, stubsDir) 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") - 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) - 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(). @@ -1896,13 +1924,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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, + // No aconfig libraries on api libraries }) } @@ -2224,6 +2246,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile), ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile), AidlIncludeDirs: j.exportAidlIncludeDirs, + // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts }) } @@ -2603,6 +2626,7 @@ func DefaultsFactory() android.Module { &appProperties{}, &appTestProperties{}, &overridableAppProperties{}, + &hostTestProperties{}, &testProperties{}, &ImportProperties{}, &AARImportProperties{}, @@ -2643,7 +2667,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, @@ -2700,11 +2724,29 @@ type javaResourcesAttributes struct { Resource_strip_prefix *string } +func (m *Library) javaResourcesGetSingleFilegroupStripPrefix(ctx android.TopDownMutatorContext) (string, bool) { + if otherM, ok := ctx.ModuleFromName(m.properties.Java_resources[0]); ok && len(m.properties.Java_resources) == 1 { + if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup { + return filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx)), true + } + } + return "", false +} + func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes { var resources bazel.LabelList var resourceStripPrefix *string + if m.properties.Java_resources != nil && len(m.properties.Java_resource_dirs) > 0 { + ctx.ModuleErrorf("bp2build doesn't support both java_resources and java_resource_dirs being set on the same module.") + } + if m.properties.Java_resources != nil { + if prefix, ok := m.javaResourcesGetSingleFilegroupStripPrefix(ctx); ok { + resourceStripPrefix = proptools.StringPtr(prefix) + } else { + resourceStripPrefix = proptools.StringPtr(ctx.ModuleDir()) + } resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources)) } @@ -2739,11 +2781,12 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte type javaCommonAttributes struct { *javaResourcesAttributes *kotlinAttributes - Srcs bazel.LabelListAttribute - Plugins bazel.LabelListAttribute - Javacopts bazel.StringListAttribute - Sdk_version bazel.StringAttribute - Java_version bazel.StringAttribute + Srcs bazel.LabelListAttribute + Plugins bazel.LabelListAttribute + Javacopts bazel.StringListAttribute + Sdk_version bazel.StringAttribute + Java_version bazel.StringAttribute + Errorprone_force_enable bazel.BoolAttribute } type javaDependencyLabels struct { @@ -2776,6 +2819,10 @@ type bp2BuildJavaInfo struct { hasKotlin bool } +func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string { + return xsd.JavaBp2buildTargetName() +} + // 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 @@ -2784,7 +2831,7 @@ type bp2BuildJavaInfo struct { func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) { var srcs bazel.LabelListAttribute var deps bazel.LabelListAttribute - var staticDeps bazel.LabelList + var staticDeps bazel.LabelListAttribute archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) for axis, configToProps := range archVariantProps { @@ -2799,6 +2846,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) javaSrcPartition := "java" protoSrcPartition := "proto" + xsdSrcPartition := "xsd" logtagSrcPartition := "logtag" aidlSrcPartition := "aidl" kotlinPartition := "kotlin" @@ -2807,6 +2855,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, protoSrcPartition: android.ProtoSrcLabelPartition, aidlSrcPartition: android.AidlSrcLabelPartition, + xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(javaXsdTargetName)}, kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}}, }) @@ -2814,6 +2863,8 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) kotlinSrcs := srcPartitions[kotlinPartition] javaSrcs.Append(kotlinSrcs) + staticDeps.Append(srcPartitions[xsdSrcPartition]) + if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" ctx.CreateBazelTargetModule( @@ -2836,7 +2887,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName) }) - apexAvailableTags := android.ApexAvailableTags(ctx.Module()) + apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module()) if !aidlSrcs.IsEmpty() { aidlLibName := m.Name() + "_aidl_library" @@ -2867,29 +2918,38 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) }, ) - staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName}) + staticDeps.Append(bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + javaAidlLibName})) } - var javacopts []string + var javacopts bazel.StringListAttribute //[]string + plugins := bazel.MakeLabelListAttribute( + android.BazelLabelForModuleDeps(ctx, m.properties.Plugins), + ) if m.properties.Javacflags != nil { - javacopts = append(javacopts, m.properties.Javacflags...) + javacopts = bazel.MakeStringListAttribute(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...) + epJavacflags := m.properties.Errorprone.Javacflags + var errorproneForceEnable bazel.BoolAttribute + if epEnabled == nil { + //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable + } else if *epEnabled { + plugins.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Errorprone.Extra_check_modules))) + javacopts.Append(bazel.MakeStringListAttribute(epJavacflags)) + errorproneForceEnable.Value = epEnabled + } else { + javacopts.Append(bazel.MakeStringListAttribute([]string{"-XepDisableAllChecks"})) } 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}, + Plugins: plugins, + Javacopts: javacopts, + Java_version: bazel.StringAttribute{Value: m.properties.Java_version}, + Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version}, + Errorprone_force_enable: errorproneForceEnable, } for axis, configToProps := range archVariantProps { @@ -2913,7 +2973,9 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) // 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) + if protoDepLabel != nil { + staticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel)) + } depLabels := &javaDependencyLabels{} depLabels.Deps = deps @@ -2928,7 +2990,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } } } - depLabels.StaticDeps.Value.Append(staticDeps) + depLabels.StaticDeps.Append(staticDeps) hasKotlin := !kotlinSrcs.IsEmpty() commonAttrs.kotlinAttributes = &kotlinAttributes{ @@ -2962,14 +3024,14 @@ type kotlinAttributes struct { func ktJvmLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties { return bazel.BazelTargetModuleProperties{ Rule_class: "kt_jvm_library", - Bzl_load_location: "//build/bazel/rules/kotlin:rules.bzl", + Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl", } } func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties { return bazel.BazelTargetModuleProperties{ Rule_class: "java_library", - Bzl_load_location: "//build/bazel/rules/java:rules.bzl", + Bzl_load_location: "//build/bazel/rules/java:library.bzl", } } @@ -3052,24 +3114,15 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { // 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 + jniLibPackages := []string{} + for _, jniLib := range m.binaryProperties.Jni_libs { + if jniLibModule, exists := ctx.ModuleFromName(jniLib); exists { + otherDir := ctx.OtherModuleDir(jniLibModule) + jniLibPackages = append(jniLibPackages, filepath.Join(otherDir, jniLib)) } } jniLibPaths := []string{} - for jniLibPackage, _ := range jniLibPackages { + for _, jniLibPackage := range jniLibPackages { // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage) } @@ -3078,7 +3131,7 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { props := bazel.BazelTargetModuleProperties{ Rule_class: "java_binary", - Bzl_load_location: "//build/bazel/rules/java:rules.bzl", + Bzl_load_location: "@rules_java//java:defs.bzl", } binAttrs := &javaBinaryHostAttributes{ Runtime_deps: runtimeDeps, @@ -3092,23 +3145,92 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { return } - libName := m.Name() + "_lib" + libInfo := libraryCreationInfo{ + deps: deps, + attrs: commonAttrs, + baseName: m.Name(), + hasKotlin: bp2BuildInfo.hasKotlin, + } + libName := createLibraryTarget(ctx, libInfo) + binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}}) + + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs) +} + +type javaTestHostAttributes struct { + *javaCommonAttributes + Srcs bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Runtime_deps bazel.LabelListAttribute +} + +// javaTestHostBp2Build is for java_test_host bp2build. +func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) { + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels + + deps := depLabels.Deps + deps.Append(depLabels.StaticDeps) + + var runtimeDeps bazel.LabelListAttribute + attrs := &javaTestHostAttributes{ + Runtime_deps: runtimeDeps, + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "java_test", + Bzl_load_location: "//build/bazel/rules/java:test.bzl", + } + + if commonAttrs.Srcs.IsEmpty() { + // if there are no sources, then the dependencies can only be used at runtime + attrs.Runtime_deps = deps + attrs.javaCommonAttributes = commonAttrs + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) + return + } + + libInfo := libraryCreationInfo{ + deps: deps, + attrs: commonAttrs, + baseName: m.Name(), + hasKotlin: bp2BuildInfo.hasKotlin, + } + libName := createLibraryTarget(ctx, libInfo) + + attrs.Srcs = commonAttrs.Srcs + attrs.Deps = deps + attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}}) + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) +} + +// libraryCreationInfo encapsulates the info needed to create java_library target from +// java_binary_host or java_test_host. +type libraryCreationInfo struct { + deps bazel.LabelListAttribute + attrs *javaCommonAttributes + baseName string + hasKotlin bool +} + +// helper function that creates java_library target from java_binary_host or java_test_host, +// and returns the library target name, +func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string { + libName := libInfo.baseName + "_lib" var libProps bazel.BazelTargetModuleProperties - if bp2BuildInfo.hasKotlin { + if libInfo.hasKotlin { libProps = ktJvmLibraryBazelTargetModuleProperties() } else { libProps = javaLibraryBazelTargetModuleProperties() } libAttrs := &javaLibraryAttributes{ - Deps: deps, - javaCommonAttributes: commonAttrs, + Deps: libInfo.deps, + javaCommonAttributes: libInfo.attrs, } 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) + return libName } type bazelJavaImportAttributes struct { @@ -3134,7 +3256,7 @@ func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } props := bazel.BazelTargetModuleProperties{ Rule_class: "java_import", - Bzl_load_location: "//build/bazel/rules/java:rules.bzl", + Bzl_load_location: "//build/bazel/rules/java:import.bzl", } name := android.RemoveOptionalPrebuiltPrefix(i.Name()) @@ -3191,7 +3313,8 @@ func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) { HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile), ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile), ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile), - //TODO(b/240308299) include AIDL information from Bazel + // TODO(b/240308299) include AIDL information from Bazel + // TODO: aconfig files? }) i.maybeInstall(ctx, jarName, outputFile) diff --git a/java/java_test.go b/java/java_test.go index 2a4913ecd..dd9867704 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2208,7 +2208,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { } } -func TestJavaApiLibraryDepApiSrcs(t *testing.T) { +func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { provider_bp_a := ` java_api_contribution { name: "foo1", @@ -2234,7 +2234,7 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) { name: "bar1", api_surface: "public", api_contributions: ["foo1"], - dep_api_srcs: "lib1", + full_api_surface_stub: "lib1", } `, map[string][]byte{ @@ -2247,9 +2247,30 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) { manifest := m.Output("metalava.sbox.textproto") sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) manifestCommand := sboxProto.Commands[0].GetCommand() + android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar") +} + +func TestJavaApiLibraryFilegroupInput(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + filegroup { + name: "default_current.txt", + srcs: ["current.txt"], + } - 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") + java_api_library { + name: "foo", + api_files: [":default_current.txt"], + } + `, + map[string][]byte{ + "current.txt": nil, + }) + + m := ctx.ModuleForTests("foo", "android_common") + outputs := fmt.Sprint(m.AllOutputs()) + if !strings.Contains(outputs, "foo/foo.jar") { + t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar") + } } func TestTradefedOptions(t *testing.T) { @@ -2275,3 +2296,77 @@ java_test_host { t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"]) } } + +func TestTestRunnerOptions(t *testing.T) { + result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` +java_test_host { + name: "foo", + test_options: { + test_runner_options: [ + { + name: "test-timeout", + value: "10m" + } + ] + } +} +`) + + buildOS := result.Config.BuildOS.String() + args := result.ModuleForTests("foo", buildOS+"_common"). + Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args + expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n ") + if args["extraTestRunnerConfigs"] != expected { + 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") + } +} diff --git a/java/jdeps.go b/java/jdeps.go index a52b86708..4c8c11c5d 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 { diff --git a/java/kotlin.go b/java/kotlin.go index 9bff5ea01..3637e2e71 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}", diff --git a/java/lint.go b/java/lint.go index 40ef48416..f84f1c065 100644 --- a/java/lint.go +++ b/java/lint.go @@ -117,18 +117,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), } } @@ -553,9 +553,9 @@ func (l *linter) lint(ctx android.ModuleContext) { } 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 @@ -705,7 +705,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/platform_bootclasspath.go b/java/platform_bootclasspath.go index 07fb92cfe..ade739552 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -26,7 +26,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 @@ -113,7 +113,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,15 +123,15 @@ 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) + 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 addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag) @@ -186,7 +186,6 @@ 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) } @@ -218,7 +217,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 @@ -275,10 +275,10 @@ 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") { + if ctx.Config().DisableHiddenApiChecks() { paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV} for _, path := range paths { ctx.Build(pctx, android.BuildParams{ @@ -399,78 +399,9 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make 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_compat_config.go b/java/platform_compat_config.go index d41729150..124827523 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -19,7 +19,10 @@ import ( "path/filepath" "android/soong/android" + "android/soong/bazel" + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) func init() { @@ -36,7 +39,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) @@ -54,6 +57,7 @@ type platformCompatConfigProperties struct { type platformCompatConfig struct { android.ModuleBase + android.BazelModuleBase properties platformCompatConfigProperties installDirPath android.InstallPath @@ -122,10 +126,29 @@ func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries { }} } +type bazelPlatformCompatConfigAttributes struct { + Src bazel.LabelAttribute +} + +func (p *platformCompatConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "platform_compat_config", + Bzl_load_location: "//build/bazel/rules/java:platform_compat_config.bzl", + } + attr := &bazelPlatformCompatConfigAttributes{ + Src: *bazel.MakeLabelAttribute( + android.BazelLabelForModuleSrcSingle(ctx, proptools.String(p.properties.Src)).Label), + } + ctx.CreateBazelTargetModule(props, android.CommonAttributes{ + Name: p.Name(), + }, attr) +} + func PlatformCompatConfigFactory() android.Module { module := &platformCompatConfig{} module.AddProperties(&module.properties) android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitBazelModule(module) return module } diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 206d99527..044802e4d 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -104,20 +104,51 @@ func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module) } +func hasBazelPrebuilt(module string) bool { + return module == "android" || module == "core-for-system-modules" +} + +func bazelPrebuiltApiModuleName(module, scope, version string) string { + bazelModule := module + switch module { + case "android": + bazelModule = "android_jar" + case "core-for-system-modules": + bazelModule = "core_jar" + } + bazelVersion := version + if version == "current" { + bazelVersion = strconv.Itoa(android.FutureApiLevelInt) + } + bazelScope := scope + switch scope { + case "module-lib": + bazelScope = "module" + case "system-server": + bazelScope = "system_server" + } + return fmt.Sprintf("//prebuilts/sdk:%s_%s_%s", bazelScope, bazelVersion, bazelModule) +} + func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) { props := struct { - Name *string - Jars []string - 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 *string + Jars []string + Sdk_version *string + Installable *bool + Compile_dex *bool + Bazel_module android.BazelModuleProperties + }{ + 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), + } + if hasBazelPrebuilt(module) { + props.Bazel_module = android.BazelModuleProperties{ + Label: proptools.StringPtr(bazelPrebuiltApiModuleName(module, scope, version))} + } mctx.CreateModule(ImportFactory, &props) } @@ -135,6 +166,19 @@ func createApiModule(mctx android.LoadHookContext, name string, path string) { mctx.CreateModule(genrule.GenRuleFactory, &genruleProps) } +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 @@ -233,9 +277,10 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) { type latestApiInfo struct { module, scope, path string version 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) @@ -245,16 +290,16 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) { key := module + "." + scope info, exists := m[key] if !exists || version > info.version { - m[key] = latestApiInfo{module, scope, f, version} + m[key] = latestApiInfo{module, scope, f, version, 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) } @@ -267,6 +312,12 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) { for _, k := range android.SortedKeys(latest) { 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) } diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go index 6d5960157..bf1b04d94 100644 --- a/java/resourceshrinker.go +++ b/java/resourceshrinker.go @@ -22,7 +22,8 @@ import ( var shrinkResources = pctx.AndroidStaticRule("shrinkResources", blueprint.RuleParams{ - Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`, + // Note that we suppress stdout to avoid successful log confirmations. + Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources >/dev/null`, CommandDeps: []string{"${config.ResourceShrinkerCmd}"}, }, "raw_resources") diff --git a/java/robolectric.go b/java/robolectric.go index 008b8b1c9..0041af429 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -144,29 +144,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,7 +185,10 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) // once the Make test runner is removed. roboTestConfigJar, r.outputFile, - instrumentedApp.implementationAndResourcesJar, + } + + if instrumentedApp != nil { + combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar) } handleLibDeps := func(dep android.Module) { @@ -213,21 +224,28 @@ 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.Paths - 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) @@ -281,7 +299,7 @@ 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) { @@ -340,7 +358,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/sdk.go b/java/sdk.go index 8b4918add..7c702c405 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -28,7 +28,7 @@ import ( func init() { android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory) - android.RegisterSingletonType("sdk", sdkSingletonFactory) + android.RegisterParallelSingletonType("sdk", sdkSingletonFactory) android.RegisterMakeVarsProvider(pctx, sdkMakeVars) } @@ -148,10 +148,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", @@ -193,20 +193,20 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext) noFrameworksLibs: true, } case android.SdkPublic, android.SdkSystem, android.SdkTest: - return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx)) + 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)) } @@ -269,9 +269,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 +286,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) diff --git a/java/sdk_library.go b/java/sdk_library.go index 103f1ace7..dbb2f0247 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -24,6 +24,8 @@ import ( "strings" "sync" + "android/soong/ui/metrics/bp2build_metrics_proto" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -156,6 +158,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 @@ -229,6 +234,14 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string { return ".stubs" + 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) stubsLibraryModuleName(baseName string) string { return baseName + scope.stubsLibraryModuleNameSuffix() } @@ -289,6 +302,7 @@ var ( return &module.sdkLibraryProperties.Public }, sdkVersion: "current", + kind: android.SdkPublic, }) apiScopeSystem = initApiScope(&apiScope{ name: "system", @@ -301,6 +315,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 +329,7 @@ var ( sdkVersion: "test_current", annotation: "android.annotation.TestApi", unstable: true, + kind: android.SdkTest, }) apiScopeModuleLib = initApiScope(&apiScope{ name: "module-lib", @@ -331,6 +347,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,6 +378,7 @@ var ( // com.android.* classes are okay in this interface" "--hide", "InternalClasses", }, + kind: android.SdkSystemServer, }) allApiScopes = apiScopes{ apiScopePublic, @@ -842,6 +860,20 @@ func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) 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.BaseModuleName() + return c.namingScheme.apiLibraryModuleName(apiScope, baseName) +} + +// Name of the java_library module that compiles the stubs +// generated from source Java files. +func (c *commonToSdkLibraryAndImport) sourceStubLibraryModuleName(apiScope *apiScope) string { + baseName := c.module.BaseModuleName() + return c.namingScheme.sourceStubLibraryModuleName(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 @@ -1268,8 +1300,7 @@ func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContex 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) // Add a dependency on the stubs source in order to access both stubs source and api information. @@ -1477,6 +1508,11 @@ 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 +} + func childModuleVisibility(childVisibility []string) []string { if childVisibility == nil { // No child visibility set. The child will use the visibility of the sdk_library. @@ -1556,7 +1592,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext } }{} - props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) + props.Name = proptools.StringPtr(module.sourceStubLibraryModuleName(apiScope)) props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) // sources are generated from the droiddoc props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} @@ -1578,21 +1614,6 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext // interop with older developer tools that don't support 1.9. props.Java_version = proptools.StringPtr("1.8") - // 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 - - // 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") - } - mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } @@ -1678,7 +1699,6 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC "MissingPermission", "SdkConstant", "Todo", - "Typo", "UnavailableSymbol", } droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) @@ -1758,6 +1778,93 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx) } +func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { + props := struct { + Name *string + Visibility []string + Api_contributions []string + Libs []string + Static_libs []string + Full_api_surface_stub *string + }{} + + props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) + + 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 + } + + props.Api_contributions = apiContributions + props.Libs = module.properties.Libs + props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_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() + ".from-text") + + // 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") + } + + mctx.CreateModule(ApiLibraryFactory, &props) +} + +func (module *SdkLibrary) createTopLevelStubsLibrary( + mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) { + props := struct { + Name *string + Visibility []string + Sdk_version *string + Static_libs []string + System_modules *string + Dist struct { + Targets []string + Dest *string + Dir *string + Tag *string + } + Compile_dex *bool + }{} + props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) + sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) + props.Sdk_version = proptools.StringPtr(sdkVersion) + + // Add the stub compiling java_library/java_api_library as static lib based on build config + staticLib := module.sourceStubLibraryModuleName(apiScope) + if mctx.Config().BuildFromTextStub() && contributesToApiSurface { + staticLib = module.apiLibraryModuleName(apiScope) + } + props.Static_libs = append(props.Static_libs, staticLib) + props.System_modules = module.deviceProperties.System_modules + + // 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") + } + + // 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 + + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) +} + func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool { return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) } @@ -1954,6 +2061,13 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs) module.createStubsLibrary(mctx, scope) + + contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) + if contributesToApiSurface { + module.createApiLibrary(mctx, scope) + } + + module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface) } if module.requiresRuntimeImplementationLibrary() { @@ -2006,6 +2120,10 @@ type sdkLibraryComponentNamingScheme interface { stubsLibraryModuleName(scope *apiScope, baseName string) string stubsSourceModuleName(scope *apiScope, baseName string) string + + apiLibraryModuleName(scope *apiScope, baseName string) string + + sourceStubLibraryModuleName(scope *apiScope, baseName string) string } type defaultNamingScheme struct { @@ -2019,9 +2137,19 @@ 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) sourceStubLibraryModuleName(scope *apiScope, baseName string) string { + return scope.sourceStubLibraryModuleName(baseName) +} + var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) 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()) { @@ -2040,6 +2168,9 @@ func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) { if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) { return true, javaSystem } + if strings.HasSuffix(name, apiScopeSystemServer.stubsLibraryModuleNameSuffix()) { + return true, javaSystemServer + } return false, javaPlatform } @@ -2102,6 +2233,7 @@ type bazelSdkLibraryAttributes struct { // java_sdk_library bp2build converter func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { if ctx.ModuleType() != "java_sdk_library" { + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") return } diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 1d0c13d4b..c22b9809b 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -35,6 +35,9 @@ 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"}) + }), ).RunTestWithBp(t, ` droiddoc_exported_dir { name: "droiddoc-templates-sdk", @@ -121,6 +124,7 @@ 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", "") @@ -407,10 +411,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) } } @@ -1412,3 +1415,62 @@ 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_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.from-text", + }, + { + scope: apiScopeSystem, + apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, + fullApiSurfaceStub: "android_system_stubs_current.from-text", + }, + { + 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.from-text", + }, + { + 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) + } +} diff --git a/java/testing.go b/java/testing.go index 6671bf0c7..3a238d76f 100644 --- a/java/testing.go +++ b/java/testing.go @@ -71,7 +71,12 @@ 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/system-current.txt": nil, + defaultJavaDir + "/api/test-current.txt": nil, + defaultJavaDir + "/api/module-lib-current.txt": nil, + defaultJavaDir + "/api/system-server-current.txt": nil, // Needed for R8 rules on apps "build/make/core/proguard.flags": nil, @@ -395,16 +400,20 @@ func gatherRequiredDepsForTest() string { } 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", + "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", + "android-non-updatable.stubs.from-text": "api/current.txt", + "android-non-updatable.stubs.system.from-text": "api/system-current.txt", + "android-non-updatable.stubs.test.from-text": "api/test-current.txt", + "android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt", } for libName, apiFile := range extraApiLibraryModules { |