summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorHaamed Gheibi <haamed@google.com>2021-07-16 22:06:52 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-07-16 22:06:52 +0000
commitf0dd5152a12c045deb95609ef47da5e6cd7c13be (patch)
tree8a151da47606af4442fd95f3d62c68326fcd516a /java
parente64464306404bb00c04190e2e44cb0952e824646 (diff)
parentd4fd974eb42fa9bc991011d544a48157aa8e95a7 (diff)
Merge "Merge SP1A.210709.002" into s-keystone-qcom-dev
Diffstat (limited to 'java')
-rw-r--r--java/base.go1
-rw-r--r--java/bootclasspath.go12
-rw-r--r--java/bootclasspath_fragment.go137
-rw-r--r--java/bootclasspath_fragment_test.go27
-rw-r--r--java/classpath_fragment.go23
-rw-r--r--java/dexpreopt_bootjars.go85
-rw-r--r--java/hiddenapi_modular.go565
-rw-r--r--java/lint.go64
-rw-r--r--java/lint_test.go75
-rw-r--r--java/platform_bootclasspath.go19
-rw-r--r--java/sdk.go18
-rw-r--r--java/sdk_library.go41
-rw-r--r--java/sdk_test.go4
-rw-r--r--java/systemserver_classpath_fragment.go18
-rw-r--r--java/testing.go1
15 files changed, 779 insertions, 311 deletions
diff --git a/java/base.go b/java/base.go
index 34514ffc3..df70efb44 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1275,6 +1275,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.linter.minSdkVersion = lintSDKVersionString(j.MinSdkVersion(ctx))
j.linter.targetSdkVersion = lintSDKVersionString(j.TargetSdkVersion(ctx))
j.linter.compileSdkVersion = lintSDKVersionString(j.SdkVersion(ctx))
+ j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index eddcc838b..d754fe6aa 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -225,13 +225,13 @@ type BootclasspathAPIProperties struct {
Core_platform_api BootclasspathNestedAPIProperties
}
-// sdkKindToStubLibs calculates the stub library modules for each relevant android.SdkKind from the
+// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope from the
// Stub_libs properties.
-func (p BootclasspathAPIProperties) sdkKindToStubLibs() map[android.SdkKind][]string {
- m := map[android.SdkKind][]string{}
- for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
- m[kind] = p.Api.Stub_libs
+func (p BootclasspathAPIProperties) apiScopeToStubLibs() map[*HiddenAPIScope][]string {
+ m := map[*HiddenAPIScope][]string{}
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ m[apiScope] = p.Api.Stub_libs
}
- m[android.SdkCorePlatform] = p.Core_platform_api.Stub_libs
+ m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs
return m
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 03faf3495..358c72b99 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -121,8 +121,18 @@ type bootclasspathFragmentProperties struct {
BootclasspathFragmentCoverageAffectedProperties
Coverage BootclasspathFragmentCoverageAffectedProperties
+ // Hidden API related properties.
Hidden_api HiddenAPIFlagFileProperties
+ // The list of additional stub libraries which this fragment's contents use but which are not
+ // provided by another bootclasspath_fragment.
+ //
+ // Note, "android-non-updatable" is treated specially. While no such module exists it is treated
+ // as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced
+ // with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system
+ // stubs are needed and so on.
+ Additional_stubs []string
+
// Properties that allow a fragment to depend on other fragments. This is needed for hidden API
// processing as it needs access to all the classes used by a fragment including those provided
// by other fragments.
@@ -149,11 +159,12 @@ type commonBootclasspathFragment interface {
// versioned sdk.
produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
- // produceBootImageFiles produces the boot image (i.e. .art, .oat and .vdex) files for each of the
- // required android.ArchType values in the returned map.
+ // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
+ // predefined in the bootImageConfig.
//
- // It must return nil if the boot image files cannot be produced for whatever reason.
- produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch
+ // 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) bootImageFilesByArch
}
var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -375,7 +386,16 @@ func (b *BootclasspathFragmentModule) ComponentDepsMutator(ctx android.BottomUpM
func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto all the modules that provide the API stubs for classes on this
// bootclasspath fragment.
- hiddenAPIAddStubLibDependencies(ctx, b.properties.sdkKindToStubLibs())
+ hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs())
+
+ for _, additionalStubModule := range b.properties.Additional_stubs {
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ // Add a dependency onto a possibly scope specific stub library.
+ scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule)
+ tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true}
+ ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency)
+ }
+ }
if SkipDexpreoptBootJars(ctx) {
return
@@ -429,9 +449,13 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
if imageConfig != nil {
// Delegate the production of the boot image files to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig, contents)
+ bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig)
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, bootImageFilesByArch)
+
// Copy the dex jars of this fragment's content modules to their predefined locations.
copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
}
@@ -506,27 +530,18 @@ func (b *BootclasspathFragmentModule) ClasspathFragmentToConfiguredJarList(ctx a
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range b.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, bootclasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable boot jars must be part of the
// platform_bootclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- jars := global.UpdatableBootJars.Filter(stems)
+ jars := global.UpdatableBootJars.Filter(possibleUpdatableModules)
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in UpdatableBootJars. Instead,
// we should check if we are creating a config for apex_test via ApexInfo and amend the values.
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
- if android.InList("test_framework-sdkextensions", stems) {
+ if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
}
return jars
@@ -557,25 +572,9 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
// Create hidden API input structure.
input := b.createHiddenAPIFlagInput(ctx, contents, fragments)
- var output *HiddenAPIOutput
-
- // Hidden API processing is conditional as a temporary workaround as not all
- // bootclasspath_fragments provide the appropriate information needed for hidden API processing
- // which leads to breakages of the build.
- // TODO(b/179354495): Stop hidden API processing being conditional once all bootclasspath_fragment
- // modules have been updated to support it.
- if input.canPerformHiddenAPIProcessing(ctx, b.properties) {
- // Delegate the production of the hidden API all-flags.csv file to a module type specific method.
- common := ctx.Module().(commonBootclasspathFragment)
- output = common.produceHiddenAPIOutput(ctx, contents, input)
- } else {
- // As hidden API processing cannot be performed fall back to trying to retrieve the legacy
- // encoded boot dex files, i.e. those files encoded by the individual libraries and returned
- // from the DexJarBuildPath() method.
- output = &HiddenAPIOutput{
- EncodedBootDexFilesByModule: retrieveLegacyEncodedBootDexFiles(ctx, contents),
- }
- }
+ // Delegate the production of the hidden API all-flags.csv file to a module type specific method.
+ common := ctx.Module().(commonBootclasspathFragment)
+ output := common.produceHiddenAPIOutput(ctx, contents, input)
// Initialize a HiddenAPIInfo structure.
hiddenAPIInfo := HiddenAPIInfo{
@@ -588,7 +587,7 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
// Other bootclasspath_fragments that depend on this need the transitive set of stub dex jars
// from this to resolve any references from their code to classes provided by this fragment
// and the fragments this depends upon.
- TransitiveStubDexJarsByKind: input.transitiveStubDexJarsByKind(),
+ TransitiveStubDexJarsByScope: input.transitiveStubDexJarsByScope(),
}
// The monolithic hidden API processing also needs access to all the output files produced by
@@ -632,8 +631,8 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul
// Populate with flag file paths from the properties.
input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)
- // Store the stub dex jars from this module's fragment dependencies.
- input.DependencyStubDexJarsByKind = dependencyHiddenApiInfo.TransitiveStubDexJarsByKind
+ // Add the stub dex jars from this module's fragment dependencies.
+ input.DependencyStubDexJarsByScope.addStubDexJarsByModule(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope)
return input
}
@@ -647,55 +646,49 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
}
// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if SkipDexpreoptBootJars(ctx) {
return nil
}
- // 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)
-
// Only generate the boot image if the configuration does not skip it.
- if !b.generateBootImageBuildActions(ctx, contents, imageConfig) {
- return nil
- }
-
- // Only make the files available to an apex if they were actually generated.
- files := bootImageFilesByArch{}
- for _, variant := range imageConfig.apexVariants() {
- files[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
- }
-
- return files
+ return b.generateBootImageBuildActions(ctx, imageConfig)
}
// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
// module.
//
-// Returns true if the boot image is created, false otherwise.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, contents []android.Module, imageConfig *bootImageConfig) bool {
+// 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) bootImageFilesByArch {
global := dexpreopt.GetGlobalConfig(ctx)
if !shouldBuildBootImages(ctx.Config(), global) {
- return false
+ return nil
}
// 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 false
+ return nil
}
// Bootclasspath fragment modules that are versioned do not produce a boot image.
if android.IsModuleInVersionedSdk(ctx.Module()) {
- return false
+ return nil
}
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
- buildBootImage(ctx, imageConfig, profile)
- return true
+ // Build boot image files for the host variants.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
+
+ // Build boot image files for the android variants.
+ androidBootImageFilesByArch := 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 androidBootImageFilesByArch
}
type bootclasspathFragmentMemberType struct {
@@ -908,7 +901,7 @@ func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
}
// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) bootImageFilesByArch {
+func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
return nil
}
@@ -930,6 +923,7 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and
}
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
+ files := bootImageFilesByArch{}
for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType
for _, toPath := range variant.imagesDeps {
@@ -937,6 +931,10 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and
// Get the path to the file that the deapexer extracted from the prebuilt apex file.
fromPath := di.PrebuiltExportPath(apexRelativePath)
+ // Return the toPath as the calling code expects the paths in the returned map to be the
+ // paths predefined in the bootImageConfig.
+ files[arch] = append(files[arch], toPath)
+
// Copy the file to the predefined location.
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
@@ -946,10 +944,13 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and
}
}
- // The returned files will be made available to APEXes that include a bootclasspath_fragment.
- // However, as a prebuilt_bootclasspath_fragment can never contribute to an APEX there is no point
- // in returning any files.
- return nil
+ // Build the boot image files for the host variants. These are 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, nil)
+
+ return files
}
var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index fba7d1a71..3d0e1558f 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -197,7 +197,7 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
],
},
core_platform_api: {
- stub_libs: ["mycoreplatform"],
+ stub_libs: ["mycoreplatform.stubs"],
},
}
@@ -245,17 +245,34 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
// Check that SdkPublic uses public stubs for all sdk libraries.
- android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkPublic])
+ android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
// Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
// as it does not provide system stubs.
- android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkSystem])
+ android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(SystemHiddenAPIScope))
// Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
// and public stubs for myothersdklibrary as it does not provide test stubs either.
- android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkTest])
+ android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(TestHiddenAPIScope))
// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
- android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByKind[android.SdkCorePlatform])
+ android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(CorePlatformHiddenAPIScope))
+
+ // Check the widest stubs.. The list contains the widest stub dex jar provided by each module.
+ expectedWidestPaths := []string{
+ // mycoreplatform's widest API is core platform.
+ corePlatformStubsJar,
+
+ // myothersdklibrary's widest API is public.
+ otherPublicStubsJar,
+
+ // sdklibrary's widest API is system.
+ systemStubsJar,
+
+ // mystublib's only provides one API and so it must be the widest.
+ stubsJar,
+ }
+
+ android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
}
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 0e14d24f2..ecfdfb7e5 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -89,6 +89,29 @@ type classpathJar struct {
maxSdkVersion int32
}
+// gatherPossibleUpdatableModuleNamesAndStems returns a set of module and stem names from the
+// supplied contents that may be in the updatable boot jars.
+//
+// The module names are included because sometimes the stem is set to just change the name of
+// the installed file and it expects the configuration to still use the actual module name.
+//
+// The stem names are included because sometimes the stem is set to change the effective name of the
+// module that is used in the configuration as well,e .g. when a test library is overriding an
+// actual boot jar
+func gatherPossibleUpdatableModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
+ set := map[string]struct{}{}
+ for _, name := range contents {
+ dep := ctx.GetDirectDepWithTag(name, tag)
+ set[name] = struct{}{}
+ if m, ok := dep.(ModuleWithStem); ok {
+ set[m.Stem()] = struct{}{}
+ } else {
+ ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
+ }
+ }
+ return android.SortedStringKeys(set)
+}
+
// Converts android.ConfiguredJarList into a list of classpathJars for each given classpathType.
func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, classpaths ...classpathType) []classpathJar {
paths := configuredJars.DevicePaths(ctx.Config(), android.Android)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index bb857845a..19c65cac7 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -502,32 +502,72 @@ func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJars
}
}
-// buildBootImage takes a bootImageConfig, and creates rules to build it.
-func buildBootImage(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) {
- var zipFiles android.Paths
+// buildBootImageVariantsForAndroidOs generates rules to build the boot image variants for the
+// android.Android OsType and returns a map from the architectures to the paths of the generated
+// boot image files.
+//
+// The paths are returned because they are needed elsewhere in Soong, e.g. for populating an APEX.
+func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch {
+ return buildBootImageForOsType(ctx, image, profile, android.Android)
+}
+
+// buildBootImageVariantsForBuildOs generates rules to build the boot image variants for the
+// android.BuildOs OsType, i.e. the type of OS on which the build is being running.
+//
+// The files need to be generated into their predefined location because they are used from there
+// both within Soong and outside, e.g. for ART based host side testing and also for use by some
+// cloud based tools. However, they are not needed by callers of this function and so the paths do
+// not need to be returned from this func, unlike the buildBootImageVariantsForAndroidOs func.
+func buildBootImageVariantsForBuildOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) {
+ buildBootImageForOsType(ctx, image, profile, android.BuildOs)
+}
+
+// buildBootImageForOsType takes a bootImageConfig, a profile file and an android.OsType
+// boot image files are required for and it creates rules to build the boot image
+// files for all the required architectures for them.
+//
+// It returns a map from android.ArchType to the predefined paths of the boot image files.
+func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageFilesByArch {
+ filesByArch := bootImageFilesByArch{}
for _, variant := range image.variants {
- files := buildBootImageVariant(ctx, variant, profile)
- if variant.target.Os == android.Android {
- zipFiles = append(zipFiles, files.Paths()...)
+ if variant.target.Os == requiredOsType {
+ buildBootImageVariant(ctx, variant, profile)
+ filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
}
}
- if image.zip != nil {
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("soong_zip").
- FlagWithOutput("-o ", image.zip).
- FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
- FlagWithInputList("-f ", zipFiles, " -f ")
+ return filesByArch
+}
- rule.Build("zip_"+image.name, "zip "+image.name+" image")
+// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files.
+//
+// The supplied filesByArch is nil when the boot image files have not been generated. Otherwise, it
+// is a map from android.ArchType to the predefined locations.
+func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *bootImageConfig, filesByArch bootImageFilesByArch) {
+ if filesByArch == nil {
+ return
+ }
+
+ // Compute the list of files from all the architectures.
+ zipFiles := android.Paths{}
+ for _, archType := range android.ArchTypeList() {
+ zipFiles = append(zipFiles, filesByArch[archType]...)
}
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("soong_zip").
+ FlagWithOutput("-o ", image.zip).
+ FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
+ FlagWithInputList("-f ", zipFiles, " -f ")
+
+ rule.Build("zip_"+image.name, "zip "+image.name+" image")
}
// Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) android.WritablePaths {
+func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) {
- globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
arch := image.target.Arch.ArchType
@@ -641,11 +681,8 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls
- var zipFiles android.WritablePaths
-
for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") {
cmd.ImplicitOutput(artOrOat)
- zipFiles = append(zipFiles, artOrOat)
// Install the .oat and .art files
rule.Install(artOrOat, filepath.Join(installDir, artOrOat.Base()))
@@ -653,7 +690,6 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
for _, vdex := range image.moduleFiles(ctx, outputDir, ".vdex") {
cmd.ImplicitOutput(vdex)
- zipFiles = append(zipFiles, vdex)
// Note that the vdex files are identical between architectures.
// Make rules will create symlinks to share them between architectures.
@@ -675,8 +711,6 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
image.installs = rule.Installs()
image.vdexInstalls = vdexInstalls
image.unstrippedInstalls = unstrippedInstalls
-
- return zipFiles
}
const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -684,7 +718,7 @@ 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 {
- globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
if global.DisableGenerateProfile {
@@ -884,8 +918,9 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
}
- imageLocationsOnHost, _ := current.getAnyAndroidVariant().imageLocations()
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocationsOnHost, ":"))
+ imageLocationsOnHost, imageLocationsOnDevice := current.getAnyAndroidVariant().imageLocations()
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_HOST"+current.name, strings.Join(imageLocationsOnHost, ":"))
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 6e2261480..654ebb743 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -20,14 +20,164 @@ import (
"android/soong/android"
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
// Contains support for processing hiddenAPI in a modular fashion.
+// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
+// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
+// not provide the information needed by hidden API processing.
+type HiddenAPIScope struct {
+ // The name of the scope, used for debug purposes.
+ name string
+
+ // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
+ sdkKind android.SdkKind
+
+ // The option needed to passed to "hiddenapi list".
+ hiddenAPIListOption string
+
+ // The name sof the source stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatableSourceModule string
+
+ // The names of the prebuilt stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatablePrebuiltModule string
+}
+
+// initHiddenAPIScope initializes the scope.
+func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
+ sdkKind := apiScope.sdkKind
+ // The platform does not provide a core platform API.
+ if sdkKind != android.SdkCorePlatform {
+ kindAsString := sdkKind.String()
+ var insert string
+ if sdkKind == android.SdkPublic {
+ insert = ""
+ } else {
+ insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
+ }
+
+ nonUpdatableModule := "android-non-updatable"
+
+ // Construct the name of the android-non-updatable source module for this scope.
+ apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
+
+ prebuiltModuleName := func(name string, kind string) string {
+ return fmt.Sprintf("sdk_%s_current_%s", kind, name)
+ }
+
+ // Construct the name of the android-non-updatable prebuilt module for this scope.
+ apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
+ }
+
+ return apiScope
+}
+
+// android-non-updatable takes the name of a module and returns a possibly scope specific name of
+// the module.
+func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
+ // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
+ // each scope.
+ // TODO(b/192067200): Remove special handling of android-non-updatable.
+ if name == "android-non-updatable" {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ return l.nonUpdatablePrebuiltModule
+ } else {
+ return l.nonUpdatableSourceModule
+ }
+ } else {
+ // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
+ // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
+ // have the same stub jar for each scope.
+ return name
+ }
+}
+
+func (l *HiddenAPIScope) String() string {
+ return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
+}
+
+var (
+ PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "public",
+ sdkKind: android.SdkPublic,
+ hiddenAPIListOption: "--public-stub-classpath",
+ })
+ SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "system",
+ sdkKind: android.SdkSystem,
+ hiddenAPIListOption: "--system-stub-classpath",
+ })
+ TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "test",
+ sdkKind: android.SdkTest,
+ hiddenAPIListOption: "--test-stub-classpath",
+ })
+ ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "module-lib",
+ sdkKind: android.SdkModule,
+ })
+ CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+ name: "core-platform",
+ sdkKind: android.SdkCorePlatform,
+ hiddenAPIListOption: "--core-platform-stub-classpath",
+ })
+
+ // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
+ // API processing.
+ //
+ // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
+ // with the biggest API surface, e.g. test is wider than system is wider than public.
+ //
+ // Core platform is considered wider than system/module-lib because those modules that provide
+ // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
+ // because the core platform API is being converted to system/module-lib APIs. In either case the
+ // system/module-lib APIs are subsets of the core platform API.
+ //
+ // This is not strictly in order from narrowest to widest as the Test API is wider than system but
+ // is neither wider or narrower than the module-lib or core platform APIs. However, this works
+ // well enough at the moment.
+ // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
+ hiddenAPIScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ ModuleLibHiddenAPIScope,
+ CorePlatformHiddenAPIScope,
+ }
+
+ // The HiddenAPIScope instances that are supported by a java_sdk_library.
+ //
+ // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
+ // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
+ hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ ModuleLibHiddenAPIScope,
+ }
+
+ // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
+ hiddenAPIFlagScopes = []*HiddenAPIScope{
+ PublicHiddenAPIScope,
+ SystemHiddenAPIScope,
+ TestHiddenAPIScope,
+ CorePlatformHiddenAPIScope,
+ }
+)
+
type hiddenAPIStubsDependencyTag struct {
blueprint.BaseDependencyTag
- sdkKind android.SdkKind
+
+ // The api scope for which this dependency was added.
+ apiScope *HiddenAPIScope
+
+ // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
+ // but is an additional API provided by a module that is not part of the current bootclasspath
+ // fragment.
+ fromAdditionalDependency bool
}
func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
@@ -38,6 +188,11 @@ func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
}
func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+ // Do not add additional dependencies to the sdk.
+ if b.fromAdditionalDependency {
+ return nil
+ }
+
// If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
// property, otherwise treat if it was specified in the java_header_libs property.
if javaSdkLibrarySdkMemberType.IsInstance(child) {
@@ -65,24 +220,9 @@ var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
-// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
-// API processing.
-//
-// These are in order from narrowest API surface to widest. Widest means the API stubs with the
-// biggest API surface, e.g. test is wider than system is wider than public. Core platform is
-// considered wider than test even though it has no relationship with test because the libraries
-// that provide core platform API don't provide test. While the core platform API is being converted
-// to a system API the system API is still a subset of core platform.
-var hiddenAPIRelevantSdkKinds = []android.SdkKind{
- android.SdkPublic,
- android.SdkSystem,
- android.SdkTest,
- android.SdkCorePlatform,
-}
-
// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
// needed to produce the hidden API monolithic stub flags file.
-func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
+func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
var publicStubModules []string
var systemStubModules []string
var testStubModules []string
@@ -115,22 +255,22 @@ func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android
testStubModules = append(testStubModules, "jacoco-stubs")
}
- m := map[android.SdkKind][]string{}
- m[android.SdkPublic] = publicStubModules
- m[android.SdkSystem] = systemStubModules
- m[android.SdkTest] = testStubModules
- m[android.SdkCorePlatform] = corePlatformStubModules
+ m := map[*HiddenAPIScope][]string{}
+ m[PublicHiddenAPIScope] = publicStubModules
+ m[SystemHiddenAPIScope] = systemStubModules
+ m[TestHiddenAPIScope] = testStubModules
+ m[CorePlatformHiddenAPIScope] = corePlatformStubModules
return m
}
// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
-// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
-// identify the source of the dependency.
-func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
+// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
+// tag to identify the source of the dependency.
+func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
module := ctx.Module()
- for _, sdkKind := range hiddenAPIRelevantSdkKinds {
- modules := sdkKindToStubLibModules[sdkKind]
- ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
+ for _, apiScope := range hiddenAPIScopes {
+ modules := apiScopeToStubLibModules[apiScope]
+ ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
}
}
@@ -153,33 +293,21 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
return dexJar
}
-var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
- android.SdkPublic: "public-stub-classpath",
- android.SdkSystem: "system-stub-classpath",
- android.SdkTest: "test-stub-classpath",
- android.SdkCorePlatform: "core-platform-stub-classpath",
-}
-
-// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
+// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
-func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
+func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, moduleStubFlagsPaths android.Paths) {
// Singleton rule which applies hiddenapi on all boot class path dex files.
rule := android.NewRuleBuilder(pctx, ctx)
tempPath := tempPathForRestat(ctx, outputPath)
// Find the widest API stubs provided by the fragments on which this depends, if any.
- var dependencyStubDexJars android.Paths
- for i := len(hiddenAPIRelevantSdkKinds) - 1; i >= 0; i-- {
- kind := hiddenAPIRelevantSdkKinds[i]
- stubsForKind := input.DependencyStubDexJarsByKind[kind]
- if len(stubsForKind) != 0 {
- dependencyStubDexJars = stubsForKind
- break
- }
- }
+ dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
+
+ // Add widest API stubs from the additional dependencies of this, if any.
+ dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
command := rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
@@ -187,24 +315,46 @@ func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath
FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
FlagForEachInput("--boot-dex=", bootDexJars)
- // Iterate over the sdk kinds in a fixed order.
- for _, sdkKind := range hiddenAPIRelevantSdkKinds {
- // Merge in the stub dex jar paths for this kind from the fragments on which it depends. They
- // will be needed to resolve dependencies from this fragment's stubs to classes in the other
- // fragment's APIs.
- dependencyPaths := input.DependencyStubDexJarsByKind[sdkKind]
- paths := append(dependencyPaths, input.StubDexJarsByKind[sdkKind]...)
+ // If no module stub flags paths are provided then this must be being called for a
+ // bootclasspath_fragment and not the whole platform_bootclasspath.
+ if moduleStubFlagsPaths == nil {
+ // This is being run on a fragment of the bootclasspath.
+ command.Flag("--fragment")
+ }
+
+ // Iterate over the api scopes in a fixed order.
+ for _, apiScope := range hiddenAPIFlagScopes {
+ // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
+ // They will be needed to resolve dependencies from this fragment's stubs to classes in the
+ // other fragment's APIs.
+ var paths android.Paths
+ paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
+ paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
+ paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
if len(paths) > 0 {
- option := sdkKindToHiddenapiListOption[sdkKind]
- command.FlagWithInputList("--"+option+"=", paths, ":")
+ option := apiScope.hiddenAPIListOption
+ command.FlagWithInputList(option+"=", paths, ":")
}
}
// Add the output path.
command.FlagWithOutput("--out-api-flags=", tempPath)
+ // If there are stub flag files that have been generated by fragments on which this depends then
+ // use them to validate the stub flag file generated by the rules created by this method.
+ if len(moduleStubFlagsPaths) > 0 {
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, moduleStubFlagsPaths)
+
+ // Add the file that indicates that the file generated by this is valid.
+ //
+ // This will cause the validation rule above to be run any time that the output of this rule
+ // changes but the validation will run in parallel with other rules that depend on this file.
+ command.Validation(validFile)
+ }
+
commitChangeForRestat(rule, tempPath, outputPath)
- return rule
+
+ rule.Build(name, desc)
}
// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
@@ -377,8 +527,9 @@ type HiddenAPIInfo struct {
// that category.
FlagFilesByCategory FlagFilesByCategory
- // The paths to the stub dex jars for each of the android.SdkKind in hiddenAPIRelevantSdkKinds.
- TransitiveStubDexJarsByKind StubDexJarsByKind
+ // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
+ // this fragment and the fragments on which this depends.
+ TransitiveStubDexJarsByScope StubDexJarsByModule
// The output from the hidden API processing needs to be made available to other modules.
HiddenAPIFlagOutput
@@ -386,8 +537,8 @@ type HiddenAPIInfo struct {
func newHiddenAPIInfo() *HiddenAPIInfo {
info := HiddenAPIInfo{
- FlagFilesByCategory: FlagFilesByCategory{},
- TransitiveStubDexJarsByKind: StubDexJarsByKind{},
+ FlagFilesByCategory: FlagFilesByCategory{},
+ TransitiveStubDexJarsByScope: StubDexJarsByModule{},
}
return &info
}
@@ -398,34 +549,126 @@ func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragmen
for _, fragment := range fragments {
if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
- i.TransitiveStubDexJarsByKind.append(info.TransitiveStubDexJarsByKind)
+ i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
}
}
-
- // Dedup and sort paths.
- i.TransitiveStubDexJarsByKind.dedupAndSort()
}
var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
-// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
-// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
-type StubDexJarsByKind map[android.SdkKind]android.Paths
+// ModuleStubDexJars contains the stub dex jars provided by a single module.
+//
+// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
+// hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
+type ModuleStubDexJars map[*HiddenAPIScope]android.Path
-// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
+// stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
// map.
-func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
- for _, kind := range hiddenAPIRelevantSdkKinds {
- s[kind] = append(s[kind], other[kind]...)
+//
+// The relative width of APIs is determined by their order in hiddenAPIScopes.
+func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
+ for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
+ apiScope := hiddenAPIScopes[i]
+ if stubsForAPIScope, ok := s[apiScope]; ok {
+ return stubsForAPIScope
+ }
+ }
+
+ return nil
+}
+
+// StubDexJarsByModule contains the stub dex jars provided by a set of modules.
+//
+// It maps a module name to the path to the stub dex jars provided by that module.
+type StubDexJarsByModule map[string]ModuleStubDexJars
+
+// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
+func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+
+ // Each named module provides one dex jar for each scope. However, in some cases different API
+ // versions of a single classes are provided by separate modules. e.g. the core platform
+ // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
+ // public version is provided by the art.module.public.api module. In those cases it is necessary
+ // to treat all those modules as they were the same name, otherwise it will result in multiple
+ // definitions of a single class being passed to hidden API processing which will cause an error.
+ if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
+ // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
+ // java_sdk_library.
+ // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
+ name = "android-non-updatable"
+ } else if name == "legacy.art.module.platform.api" {
+ // Treat legacy.art.module.platform.api as if it was an API scope provided by the
+ // art.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "art.module.public.api"
+ } else if name == "legacy.i18n.module.platform.api" {
+ // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
+ // i18n.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "i18n.module.public.api"
+ } else if name == "conscrypt.module.platform.api" {
+ // Treat conscrypt.module.platform.api as if it was an API scope provided by the
+ // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
+ // migrated to a module_lib API.
+ name = "conscrypt.module.public.api"
+ } else if d, ok := module.(SdkLibraryComponentDependency); ok {
+ sdkLibraryName := d.SdkLibraryName()
+ if sdkLibraryName != nil {
+ // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
+ // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
+ // use `foo` as the name.
+ name = *sdkLibraryName
+ }
+ }
+ stubDexJarsByScope := s[name]
+ if stubDexJarsByScope == nil {
+ stubDexJarsByScope = ModuleStubDexJars{}
+ s[name] = stubDexJarsByScope
+ }
+ stubDexJarsByScope[scope] = stubDexJar
+}
+
+// addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
+func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
+ for module, stubDexJarsByScope := range other {
+ s[module] = stubDexJarsByScope
}
}
-// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
-// deterministic order.
-func (s StubDexJarsByKind) dedupAndSort() {
- for kind, paths := range s {
- s[kind] = android.SortedUniquePaths(paths)
+// StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
+// provided by each module.
+//
+// The relative width of APIs is determined by their order in hiddenAPIScopes.
+func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
+ stubDexJars := android.Paths{}
+ modules := android.SortedStringKeys(s)
+ for _, module := range modules {
+ stubDexJarsByScope := s[module]
+
+ stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
}
+
+ return stubDexJars
+}
+
+// StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
+// module for the specified scope.
+//
+// If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
+// the returned list.
+func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
+ stubDexJars := android.Paths{}
+ modules := android.SortedStringKeys(s)
+ for _, module := range modules {
+ stubDexJarsByScope := s[module]
+ // Not every module will have the same set of
+ if jars, ok := stubDexJarsByScope[scope]; ok {
+ stubDexJars = append(stubDexJars, jars)
+ }
+ }
+
+ return stubDexJars
}
// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
@@ -435,14 +678,21 @@ type HiddenAPIFlagInput struct {
// from the stub dex files.
FlagFilesByCategory FlagFilesByCategory
- // StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
+ // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
// the initial flags for each dex member.
- StubDexJarsByKind StubDexJarsByKind
+ StubDexJarsByScope StubDexJarsByModule
- // DependencyStubDexJarsByKind contains the stub dex jars provided by the fragments on which this
- // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByKind from each
+ // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
+ // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
// fragment on which this depends.
- DependencyStubDexJarsByKind StubDexJarsByKind
+ DependencyStubDexJarsByScope StubDexJarsByModule
+
+ // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
+ // the ones that are obtained from fragments on which this depends.
+ //
+ // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
+ // as there are not propagated transitively to other fragments that depend on this.
+ AdditionalStubDexJarsByScope StubDexJarsByModule
// RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
// specified in the bootclasspath_fragment's stub_libs and contents properties.
@@ -452,62 +702,29 @@ type HiddenAPIFlagInput struct {
// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
func newHiddenAPIFlagInput() HiddenAPIFlagInput {
input := HiddenAPIFlagInput{
- FlagFilesByCategory: FlagFilesByCategory{},
- StubDexJarsByKind: StubDexJarsByKind{},
+ FlagFilesByCategory: FlagFilesByCategory{},
+ StubDexJarsByScope: StubDexJarsByModule{},
+ DependencyStubDexJarsByScope: StubDexJarsByModule{},
+ AdditionalStubDexJarsByScope: StubDexJarsByModule{},
}
return input
}
-// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
-//
-// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
-// appropriate information needed for hidden API processing breaking the build.
-// TODO(b/179354495): Remove this workaround.
-func (i *HiddenAPIFlagInput) canPerformHiddenAPIProcessing(ctx android.ModuleContext, properties bootclasspathFragmentProperties) bool {
- // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
- // required as the whole point of adding something to the bootclasspath fragment is to add it to
- // the bootclasspath in order to be used by something else in the system. Without any stubs it
- // cannot do that.
- if len(i.StubDexJarsByKind) == 0 {
- return false
- }
-
- // Hidden API processing is always enabled in tests.
- if ctx.Config().TestProductVariables != nil {
- return true
- }
-
- // A module that has fragments should have access to the information it needs in order to perform
- // hidden API processing.
- if len(properties.Fragments) != 0 {
- return true
- }
-
- // The art bootclasspath fragment does not depend on any other fragments but already supports
- // hidden API processing.
- imageName := proptools.String(properties.Image_name)
- if imageName == "art" {
- return true
- }
-
- // Disable it for everything else.
- return false
-}
-
// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
// dependencies added in hiddenAPIAddStubLibDependencies.
//
// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
- addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
- dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+ addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
+ sdkKind := apiScope.sdkKind
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
if dexJar != nil {
- i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
+ i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
}
if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
- removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, kind)
+ removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
}
}
@@ -515,11 +732,9 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten
// If the contents includes any java_sdk_library modules then add them to the stubs.
for _, module := range contents {
if _, ok := module.(SdkLibraryDependency); ok {
- // Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
- // as the java_sdk_library does not have special support for core_platform API, instead it is
- // implemented as a customized form of SdkPublic.
- for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
- addFromModule(ctx, module, kind)
+ // Add information for every possible API scope needed by hidden API.
+ for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+ addFromModule(ctx, module, apiScope)
}
}
}
@@ -527,13 +742,19 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
- kind := hiddenAPIStubsTag.sdkKind
- addFromModule(ctx, module, kind)
+ apiScope := hiddenAPIStubsTag.apiScope
+ if hiddenAPIStubsTag.fromAdditionalDependency {
+ dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
+ if dexJar != nil {
+ i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
+ }
+ } else {
+ addFromModule(ctx, module, apiScope)
+ }
}
})
// Normalize the paths, i.e. remove duplicates and sort.
- i.StubDexJarsByKind.dedupAndSort()
i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
}
@@ -546,9 +767,9 @@ func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleCo
}
}
-func (i *HiddenAPIFlagInput) transitiveStubDexJarsByKind() StubDexJarsByKind {
- transitive := i.DependencyStubDexJarsByKind
- transitive.append(i.StubDexJarsByKind)
+func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
+ transitive := i.DependencyStubDexJarsByScope
+ transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
return transitive
}
@@ -637,28 +858,6 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
- // The file which is used to record that the flags file is valid.
- var validFile android.WritablePath
-
- // If there are flag files that have been generated by fragments on which this depends then use
- // them to validate the flag file generated by the rules created by this method.
- if len(allFlagsPaths) > 0 {
- // The flags file generated by the rule created by this method needs to be validated to ensure
- // that it is consistent with the flag files generated by the individual fragments.
-
- validFile = pathForValidation(ctx, outputPath)
-
- // Create a rule to validate the output from the following rule.
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("verify_overlaps").
- Input(outputPath).
- Inputs(allFlagsPaths).
- // If validation passes then update the file that records that.
- Text("&& touch").Output(validFile)
- rule.Build(name+"Validation", desc+" validation")
- }
-
// Create the rule that will generate the flag files.
tempPath := tempPathForRestat(ctx, outputPath)
rule := android.NewRuleBuilder(pctx, ctx)
@@ -684,7 +883,11 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
commitChangeForRestat(rule, tempPath, outputPath)
- if validFile != nil {
+ // If there are flag files that have been generated by fragments on which this depends then use
+ // them to validate the flag file generated by the rules created by this method.
+ if len(allFlagsPaths) > 0 {
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
+
// Add the file that indicates that the file generated by this is valid.
//
// This will cause the validation rule above to be run any time that the output of this rule
@@ -695,6 +898,25 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
rule.Build(name, desc)
}
+// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
+// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
+func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
+ // The file which is used to record that the flags file is valid.
+ validFile := pathForValidation(ctx, monolithicFilePath)
+
+ // Create a rule to validate the output from the following rule.
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("verify_overlaps").
+ Input(monolithicFilePath).
+ Inputs(modularFilePaths).
+ // If validation passes then update the file that records that.
+ Text("&& touch").Output(validFile)
+ rule.Build(name+"Validation", desc+" validation")
+
+ return validFile
+}
+
// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
// bootclasspath and then encode the flags into the boot dex files.
//
@@ -718,8 +940,7 @@ func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents
// Generate the stub-flags.csv.
stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input)
- rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
// Extract the classes jars from the contents.
classesJars := extractClassesJarsFromModules(contents)
@@ -903,6 +1124,14 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
return true
}
+ // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
+ // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
+ // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
+ // failures missing boot dex jars need to be deferred.
+ if android.IsModuleInVersionedSdk(ctx.Module()) {
+ return true
+ }
+
// This is called for both platform_bootclasspath and bootclasspath_fragment modules.
//
// A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
@@ -939,6 +1168,14 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
//
// TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
if android.IsModulePrebuilt(module) {
+ // An inactive source module can still contribute to the APEX but an inactive prebuilt module
+ // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
+ // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
+ // built Ninja should never use the dex jar file.
+ if !isActiveModule(module) {
+ return true
+ }
+
if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if apexInfo.IsForPlatform() {
@@ -947,14 +1184,6 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
}
}
- // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there
- // is no equivalently versioned prebuilt APEX file from which it can be obtained. However,
- // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build
- // failures missing boot dex jars need to be deferred.
- if android.IsModuleInVersionedSdk(ctx.Module()) {
- return true
- }
-
return false
}
diff --git a/java/lint.go b/java/lint.go
index 1511cfe26..fe3218e90 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -78,6 +78,7 @@ type linter struct {
minSdkVersion string
targetSdkVersion string
compileSdkVersion string
+ compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
outputs lintOutputs
@@ -389,13 +390,26 @@ func (l *linter) lint(ctx android.ModuleContext) {
rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
+ var apiVersionsName, apiVersionsPrebuilt string
+ if l.compileSdkKind == android.SdkModule || l.compileSdkKind == android.SdkSystemServer {
+ // When compiling an SDK module (or system server) we use the filtered
+ // database because otherwise lint's
+ // NewApi check produces too many false positives; This database excludes information
+ // about classes created in mainline modules hence removing those false positives.
+ apiVersionsName = "api_versions_public_filtered.xml"
+ apiVersionsPrebuilt = "prebuilts/sdk/current/public/data/api-versions-filtered.xml"
+ } else {
+ apiVersionsName = "api_versions.xml"
+ apiVersionsPrebuilt = "prebuilts/sdk/current/public/data/api-versions.xml"
+ }
+
var annotationsZipPath, apiVersionsXMLPath android.Path
if ctx.Config().AlwaysUsePrebuiltSdks() {
annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
- apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
+ apiVersionsXMLPath = android.PathForSource(ctx, apiVersionsPrebuilt)
} else {
annotationsZipPath = copiedAnnotationsZipPath(ctx)
- apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
+ apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx, apiVersionsName)
}
cmd := rule.Command()
@@ -487,23 +501,27 @@ func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) {
l.copyLintDependencies(ctx)
}
-func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
- if ctx.Config().AlwaysUsePrebuiltSdks() {
- return
- }
-
- var frameworkDocStubs android.Module
+func findModuleOrErr(ctx android.SingletonContext, moduleName string) android.Module {
+ var res android.Module
ctx.VisitAllModules(func(m android.Module) {
- if ctx.ModuleName(m) == "framework-doc-stubs" {
- if frameworkDocStubs == nil {
- frameworkDocStubs = m
+ if ctx.ModuleName(m) == moduleName {
+ if res == nil {
+ res = m
} else {
- ctx.Errorf("lint: multiple framework-doc-stubs modules found: %s and %s",
- ctx.ModuleSubDir(m), ctx.ModuleSubDir(frameworkDocStubs))
+ ctx.Errorf("lint: multiple %s modules found: %s and %s", moduleName,
+ ctx.ModuleSubDir(m), ctx.ModuleSubDir(res))
}
}
})
+ return res
+}
+func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ return
+ }
+
+ frameworkDocStubs := findModuleOrErr(ctx, "framework-doc-stubs")
if frameworkDocStubs == nil {
if !ctx.Config().AllowMissingDependencies() {
ctx.Errorf("lint: missing framework-doc-stubs")
@@ -511,6 +529,14 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
return
}
+ filteredDb := findModuleOrErr(ctx, "api-versions-xml-public-filtered")
+ if filteredDb == nil {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.Errorf("lint: missing api-versions-xml-public-filtered")
+ }
+ return
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
@@ -520,7 +546,13 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
- Output: copiedAPIVersionsXmlPath(ctx),
+ Output: copiedAPIVersionsXmlPath(ctx, "api_versions.xml"),
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: android.OutputFileForModule(ctx, filteredDb, ""),
+ Output: copiedAPIVersionsXmlPath(ctx, "api_versions_public_filtered.xml"),
})
}
@@ -528,8 +560,8 @@ func copiedAnnotationsZipPath(ctx android.PathContext) android.WritablePath {
return android.PathForOutput(ctx, "lint", "annotations.zip")
}
-func copiedAPIVersionsXmlPath(ctx android.PathContext) android.WritablePath {
- return android.PathForOutput(ctx, "lint", "api_versions.xml")
+func copiedAPIVersionsXmlPath(ctx android.PathContext, name string) android.WritablePath {
+ return android.PathForOutput(ctx, "lint", name)
}
func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
diff --git a/java/lint_test.go b/java/lint_test.go
index 6d64de7e9..456e6ba73 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -219,3 +219,78 @@ func TestJavaLintStrictUpdatabilityLinting(t *testing.T) {
t.Error("did not restrict baselining NewApi")
}
}
+
+func TestJavaLintDatabaseSelectionFull(t *testing.T) {
+ testCases := []string{
+ "current", "core_platform", "system_current", "S", "30", "10000",
+ }
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "XXX",
+ lint: {
+ strict_updatability_linting: true,
+ },
+ }
+`
+ for _, testCase := range testCases {
+ thisBp := strings.Replace(bp, "XXX", testCase, 1)
+
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"foo"},
+ "10000": {"foo"},
+ })).
+ RunTestWithBp(t, thisBp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions_public_filtered.xml") {
+ t.Error("used public-filtered lint api database for case", testCase)
+ }
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions.xml") {
+ t.Error("did not use full api database for case", testCase)
+ }
+ }
+
+}
+
+func TestJavaLintDatabaseSelectionPublicFiltered(t *testing.T) {
+ testCases := []string{
+ "module_current", "system_server_current",
+ }
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "module_current",
+ lint: {
+ strict_updatability_linting: true,
+ },
+ }
+`
+ for _, testCase := range testCases {
+ thisBp := strings.Replace(bp, "XXX", testCase, 1)
+ result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules).
+ RunTestWithBp(t, thisBp)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions_public_filtered.xml") {
+ t.Error("did not use public-filtered lint api database for case", testCase)
+ }
+ if strings.Contains(*sboxProto.Commands[0].Command,
+ "/api_versions.xml") {
+ t.Error("used full api database for case", testCase)
+ }
+ }
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 7b651baff..10739b015 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -119,8 +119,8 @@ func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpM
}
// Add dependencies onto the stub lib modules.
- sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
- hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules)
+ apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+ hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
}
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -287,7 +287,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
// the fragments will have already provided the flags that are needed.
classesJars := monolithicInfo.ClassesJars
- // Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
+ // Create the input to pass to buildRuleToGenerateHiddenAPIStubFlagsFile
input := newHiddenAPIFlagInput()
// Gather stub library information from the dependencies on modules provided by
@@ -299,8 +299,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
// Generate the monolithic stub-flags.csv file.
stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
- rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJarByModule.bootDexJars(), input)
- rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags", stubFlags, bootDexJarByModule.bootDexJars(), input, monolithicInfo.StubFlagsPaths)
// Generate the annotation-flags.csv file from all the module annotations.
annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags-from-classes.csv")
@@ -422,7 +421,15 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.
// Build a profile for the image config and then use that to build the boot image.
profile := bootImageProfileRule(ctx, imageConfig)
- buildBootImage(ctx, imageConfig, profile)
+
+ // Build boot image files for the android variants.
+ androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+
+ // Zip the android variant boot image files up.
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFilesByArch)
+
+ // Build boot image files for the host variants. There are use directly by ART host side tests.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
dumpOatRules(ctx, imageConfig)
}
diff --git a/java/sdk.go b/java/sdk.go
index cbd873d33..d1b899e48 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -175,10 +175,24 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext)
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
+ return sdkDep{
+ useModule: true,
+ bootclasspath: []string{"android_module_lib_stubs_current", config.DefaultLambdaStubsLibrary},
+ systemModules: "core-module-lib-stubs-system-modules",
+ java9Classpath: []string{"android_module_lib_stubs_current"},
+ frameworkResModule: "framework-res",
+ aidl: android.OptionalPathForPath(nonUpdatableFrameworkAidlPath(ctx)),
+ }
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return sdkDep{
+ useModule: true,
+ bootclasspath: []string{"android_system_server_stubs_current", config.DefaultLambdaStubsLibrary},
+ systemModules: "core-module-lib-stubs-system-modules",
+ java9Classpath: []string{"android_system_server_stubs_current"},
+ frameworkResModule: "framework-res",
+ aidl: android.OptionalPathForPath(sdkFrameworkAidlPath(ctx)),
+ }
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 409a41fd7..1064f7c7f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -675,15 +675,27 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android
return false
}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
+
// Only track this sdk library if this can be used as a shared library.
if c.sharedLibrary() {
// Use the name specified in the module definition as the owner.
- c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr
}
return true
}
+// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations
+// method.
+func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool {
+ // A java_sdk_library that is a shared library produces an XML file that makes the shared library
+ // usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of
+ // the APEX and so it needs a unique variation per APEX.
+ return c.sharedLibrary()
+}
+
func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
}
@@ -913,15 +925,19 @@ func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleCo
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
componentProps := &struct {
+ SdkLibraryName *string
SdkLibraryToImplicitlyTrack *string
}{}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ componentProps.SdkLibraryName = namePtr
+
if c.sharedLibrary() {
// Mark the stubs library as being components of this java_sdk_library so that
// any app that includes code which depends (directly or indirectly) on the stubs
// library will have the appropriate <uses-library> invocation inserted into its
// manifest if necessary.
- componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
+ componentProps.SdkLibraryToImplicitlyTrack = namePtr
}
return componentProps
@@ -940,6 +956,8 @@ func (c *commonToSdkLibraryAndImport) stubLibrariesCompiledForDex() bool {
// Properties related to the use of a module as an component of a java_sdk_library.
type SdkLibraryComponentProperties struct {
+ // The name of the java_sdk_library/_import module.
+ SdkLibraryName *string `blueprint:"mutated"`
// The name of the java_sdk_library/_import to add to a <uses-library> entry
// in the AndroidManifest.xml of any Android app that includes code that references
@@ -958,6 +976,11 @@ func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.M
}
// to satisfy SdkLibraryComponentDependency
+func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
+ return e.sdkLibraryComponentProperties.SdkLibraryName
+}
+
+// to satisfy SdkLibraryComponentDependency
func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() *string {
return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
}
@@ -973,6 +996,9 @@ func (e *EmbeddableSdkLibraryComponent) OptionalSdkLibraryImplementation() *stri
type SdkLibraryComponentDependency interface {
UsesLibraryDependency
+ // SdkLibraryName returns the name of the java_sdk_library/_import module.
+ SdkLibraryName() *string
+
// The optional name of the sdk library that should be implicitly added to the
// AndroidManifest of an app that contains code which references the sdk library.
//
@@ -1528,6 +1554,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
mctx.CreateModule(DroidstubsFactory, &props)
}
+// Implements android.ApexModule
func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
depTag := mctx.OtherModuleDependencyTag(dep)
if depTag == xmlPermissionsFileTag {
@@ -1536,6 +1563,11 @@ func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep an
return module.Library.DepIsInSameApex(mctx, dep)
}
+// Implements android.ApexModule
+func (module *SdkLibrary) UniqueApexVariations() bool {
+ return module.uniqueApexVariations()
+}
+
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
props := struct {
@@ -2090,6 +2122,11 @@ func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleCo
return nil
}
+// Implements android.ApexModule
+func (module *SdkLibraryImport) UniqueApexVariations() bool {
+ return module.uniqueApexVariations()
+}
+
func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
return module.commonOutputFiles(tag)
}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 2b1846592..bb595a54e 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -219,7 +219,7 @@ func TestClasspath(t *testing.T) {
name: "module_current",
properties: `sdk_version: "module_current",`,
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_module_lib_stubs_current"},
aidl: "-pout/soong/framework_non_updatable.aidl",
},
@@ -227,7 +227,7 @@ func TestClasspath(t *testing.T) {
name: "system_server_current",
properties: `sdk_version: "system_server_current",`,
bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_system_server_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 7ffb05602..a2006b778 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -98,27 +98,23 @@ func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.Mo
func (s *SystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
global := dexpreopt.GetGlobalConfig(ctx)
- // Convert content names to their appropriate stems, in case a test library is overriding an actual boot jar
- var stems []string
- for _, name := range s.properties.Contents {
- dep := ctx.GetDirectDepWithTag(name, systemServerClasspathFragmentContentDepTag)
- if m, ok := dep.(ModuleWithStem); ok {
- stems = append(stems, m.Stem())
- } else {
- ctx.PropertyErrorf("contents", "%v is not a ModuleWithStem", name)
- }
- }
+ possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
// Only create configs for updatable boot jars. Non-updatable system server jars must be part of the
// platform_systemserverclasspath's classpath proto config to guarantee that they come before any
// updatable jars at runtime.
- return global.UpdatableSystemServerJars.Filter(stems)
+ return global.UpdatableSystemServerJars.Filter(possibleUpdatableModules)
}
type systemServerClasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
+// The systemserverclasspath_fragment contents must never depend on prebuilts.
+func (systemServerClasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool {
+ return false
+}
+
// Contents of system server fragments in an apex are considered to be directly in the apex, as if
// they were listed in java_libs.
func (systemServerClasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {}
diff --git a/java/testing.go b/java/testing.go
index 7b452f762..3ef51bd4d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -312,6 +312,7 @@ func gatherRequiredDepsForTest() string {
systemModules := []string{
"core-current-stubs-system-modules",
+ "core-module-lib-stubs-system-modules",
"legacy-core-platform-api-stubs-system-modules",
"stable-core-platform-api-stubs-system-modules",
}