diff options
author | Haamed Gheibi <haamed@google.com> | 2021-07-16 22:06:52 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-07-16 22:06:52 +0000 |
commit | f0dd5152a12c045deb95609ef47da5e6cd7c13be (patch) | |
tree | 8a151da47606af4442fd95f3d62c68326fcd516a /java | |
parent | e64464306404bb00c04190e2e44cb0952e824646 (diff) | |
parent | d4fd974eb42fa9bc991011d544a48157aa8e95a7 (diff) |
Merge "Merge SP1A.210709.002" into s-keystone-qcom-dev
Diffstat (limited to 'java')
-rw-r--r-- | java/base.go | 1 | ||||
-rw-r--r-- | java/bootclasspath.go | 12 | ||||
-rw-r--r-- | java/bootclasspath_fragment.go | 137 | ||||
-rw-r--r-- | java/bootclasspath_fragment_test.go | 27 | ||||
-rw-r--r-- | java/classpath_fragment.go | 23 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 85 | ||||
-rw-r--r-- | java/hiddenapi_modular.go | 565 | ||||
-rw-r--r-- | java/lint.go | 64 | ||||
-rw-r--r-- | java/lint_test.go | 75 | ||||
-rw-r--r-- | java/platform_bootclasspath.go | 19 | ||||
-rw-r--r-- | java/sdk.go | 18 | ||||
-rw-r--r-- | java/sdk_library.go | 41 | ||||
-rw-r--r-- | java/sdk_test.go | 4 | ||||
-rw-r--r-- | java/systemserver_classpath_fragment.go | 18 | ||||
-rw-r--r-- | java/testing.go | 1 |
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", } |