Add hidden API properties to java_sdk_library modules

Previously, hidden API properties were only allowed on
bootclasspath_fragment and platform_bootclasspath module types. This
change allows them to be specified on java_sdk_library modules too. It
involves the following changes:

1. Add the properties to the java.Module.
2. Populate and provide a HiddenAPIPropertyInfo struct from
   java_sdk_library modules.
3. Modify bootclasspath_fragment to merge information gathered from its
   content libraries as if it was specified on the fragment itself.

Bug: 240406019
Test: m nothing
      packages/modules/common/build/mainline_modules_sdks.sh
      # Ran the previous command with and without this change to make
      # sure that this change does not change the sdk snapshot
      # contents.
Change-Id: I64eb71c2039ddc14cf380689d0cec7ec221f5b88
This commit is contained in:
Paul Duffin
2022-07-27 16:27:42 +00:00
parent 1149c2c185
commit 3f1ae0b55a
6 changed files with 230 additions and 8 deletions

View File

@@ -267,6 +267,9 @@ type DeviceProperties struct {
// Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
// public stubs library.
SyspropPublicStub string `blueprint:"mutated"`
HiddenAPIPackageProperties
HiddenAPIFlagFileProperties
}
// Device properties that can be overridden by overriding module (e.g. override_android_app)
@@ -564,6 +567,20 @@ func (j *Module) addHostAndDeviceProperties() {
)
}
// provideHiddenAPIPropertyInfo populates a HiddenAPIPropertyInfo from hidden API properties and
// makes it available through the hiddenAPIPropertyInfoProvider.
func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) {
hiddenAPIInfo := newHiddenAPIPropertyInfo()
// Populate with flag file paths from the properties.
hiddenAPIInfo.extractFlagFilesFromProperties(ctx, &j.deviceProperties.HiddenAPIFlagFileProperties)
// Populate with package rules from the properties.
hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties)
ctx.SetProvider(hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":

View File

@@ -830,6 +830,8 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul
// Populate with package rules from the properties.
input.extractPackageRulesFromProperties(&b.sourceOnlyProperties.HiddenAPIPackageProperties)
input.gatherPropertyInfo(ctx, contents)
// Add the stub dex jars from this module's fragment dependencies.
input.DependencyStubDexJarsByScope.addStubDexJarsByModule(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope)

View File

@@ -15,6 +15,7 @@
package java
import (
"strings"
"testing"
"android/soong/android"
@@ -285,6 +286,119 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) {
android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
}
func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"),
FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"),
android.MockFS{
"my-blocked.txt": nil,
"my-max-target-o-low-priority.txt": nil,
"my-max-target-p.txt": nil,
"my-max-target-q.txt": nil,
"my-max-target-r-low-priority.txt": nil,
"my-removed.txt": nil,
"my-unsupported-packages.txt": nil,
"my-unsupported.txt": nil,
"my-new-max-target-q.txt": nil,
}.AddToFixture(),
android.FixtureWithRootAndroidBp(`
bootclasspath_fragment {
name: "mybootclasspathfragment",
apex_available: ["myapex"],
contents: ["mybootlib", "mynewlibrary"],
hidden_api: {
unsupported: [
"my-unsupported.txt",
],
removed: [
"my-removed.txt",
],
max_target_r_low_priority: [
"my-max-target-r-low-priority.txt",
],
max_target_q: [
"my-max-target-q.txt",
],
max_target_p: [
"my-max-target-p.txt",
],
max_target_o_low_priority: [
"my-max-target-o-low-priority.txt",
],
blocked: [
"my-blocked.txt",
],
unsupported_packages: [
"my-unsupported-packages.txt",
],
split_packages: ["sdklibrary"],
package_prefixes: ["sdklibrary.all.mine"],
single_packages: ["sdklibrary.mine"],
},
}
java_library {
name: "mybootlib",
apex_available: ["myapex"],
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
min_sdk_version: "1",
compile_dex: true,
permitted_packages: ["mybootlib"],
}
java_sdk_library {
name: "mynewlibrary",
apex_available: ["myapex"],
srcs: ["Test.java"],
min_sdk_version: "10",
compile_dex: true,
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
hidden_api: {
max_target_q: [
"my-new-max-target-q.txt",
],
split_packages: ["sdklibrary", "newlibrary"],
package_prefixes: ["newlibrary.all.mine"],
single_packages: ["newlibrary.mine"],
},
}
`),
).RunTest(t)
// Make sure that the library exports hidden API properties for use by the bootclasspath_fragment.
library := result.Module("mynewlibrary", "android_common")
info := result.ModuleProvider(library, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages)
android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes)
android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages)
for _, c := range HiddenAPIFlagFileCategories {
expectedMaxTargetQPaths := []string(nil)
if c.PropertyName == "max_target_q" {
expectedMaxTargetQPaths = []string{"my-new-max-target-q.txt"}
}
android.AssertPathsRelativeToTopEquals(t, c.PropertyName, expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
}
// Make sure that the signature-patterns.csv is passed all the appropriate package properties
// from the bootclasspath_fragment and its contents.
fragment := result.ModuleForTests("mybootclasspathfragment", "android_common")
rule := fragment.Output("modular-hiddenapi/signature-patterns.csv")
expectedCommand := strings.Join([]string{
"--split-package newlibrary",
"--split-package sdklibrary",
"--package-prefix newlibrary.all.mine",
"--package-prefix sdklibrary.all.mine",
"--single-package newlibrary.mine",
"--single-package sdklibrary",
}, " ")
android.AssertStringDoesContain(t, "signature patterns command", rule.RuleParams.Command, expectedCommand)
}
func TestBootclasspathFragment_Test(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,

View File

@@ -440,7 +440,18 @@ var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
},
}
var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory
func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory {
for _, category := range c {
if category.PropertyName == name {
return category
}
}
panic(fmt.Errorf("no category exists with property name %q in %v", name, c))
}
var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
// See HiddenAPIFlagFileProperties.Unsupported
{
PropertyName: "unsupported",
@@ -517,13 +528,20 @@ var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{
// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
// append appends the supplied flags files to the corresponding category in this map.
// append the supplied flags files to the corresponding category in this map.
func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
for _, category := range HiddenAPIFlagFileCategories {
s[category] = append(s[category], other[category]...)
}
}
// sort the paths for each category in this map.
func (s FlagFilesByCategory) sort() {
for category, value := range s {
s[category] = android.SortedUniquePaths(value)
}
}
// HiddenAPIInfo contains information provided by the hidden API processing.
//
// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
@@ -706,6 +724,8 @@ type HiddenAPIPropertyInfo struct {
SplitPackages []string
}
var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{})
// newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
return HiddenAPIPropertyInfo{
@@ -730,6 +750,24 @@ func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPa
i.SplitPackages = p.Hidden_api.Split_packages
}
func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
for _, module := range contents {
if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) {
info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
i.FlagFilesByCategory.append(info.FlagFilesByCategory)
i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
i.SplitPackages = append(i.SplitPackages, info.SplitPackages...)
}
}
// Dedup and sort the information to ensure consistent builds.
i.FlagFilesByCategory.sort()
i.PackagePrefixes = android.SortedUniqueStrings(i.PackagePrefixes)
i.SinglePackages = android.SortedUniqueStrings(i.SinglePackages)
i.SplitPackages = android.SortedUniqueStrings(i.SplitPackages)
}
// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
// needed for hidden API flag generation.
type HiddenAPIFlagInput struct {

View File

@@ -629,6 +629,9 @@ func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.provideHiddenAPIPropertyInfo(ctx)
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
j.maxSdkVersion = j.MaxSdkVersion(ctx)

View File

@@ -675,8 +675,8 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary"),
java.FixtureConfigureApexBootJars("myapex:mybootlib"),
java.FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"),
java.FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"),
prepareForSdkTestWithApex,
// Add a platform_bootclasspath that depends on the fragment.
@@ -691,6 +691,7 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
"my-removed.txt": nil,
"my-unsupported-packages.txt": nil,
"my-unsupported.txt": nil,
"my-new-max-target-q.txt": nil,
}.AddToFixture(),
android.FixtureWithRootAndroidBp(`
sdk {
@@ -708,7 +709,7 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
bootclasspath_fragment {
name: "mybootclasspathfragment",
apex_available: ["myapex"],
contents: ["mybootlib"],
contents: ["mybootlib", "mynewlibrary"],
api: {
stub_libs: ["mysdklibrary"],
},
@@ -737,7 +738,9 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
unsupported_packages: [
"my-unsupported-packages.txt",
],
split_packages: ["*"],
split_packages: ["sdklibrary"],
package_prefixes: ["sdklibrary.all.mine"],
single_packages: ["sdklibrary.mine"],
},
}
@@ -759,6 +762,24 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
}
java_sdk_library {
name: "mynewlibrary",
apex_available: ["myapex"],
srcs: ["Test.java"],
min_sdk_version: "10",
compile_dex: true,
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
hidden_api: {
max_target_q: [
"my-new-max-target-q.txt",
],
split_packages: ["sdklibrary", "newlibrary"],
package_prefixes: ["newlibrary.all.mine"],
single_packages: ["newlibrary.mine"],
},
}
`),
).RunTest(t)
@@ -774,7 +795,10 @@ prebuilt_bootclasspath_fragment {
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["myapex"],
contents: ["mybootlib"],
contents: [
"mybootlib",
"mynewlibrary",
],
api: {
stub_libs: ["mysdklibrary"],
},
@@ -782,7 +806,10 @@ prebuilt_bootclasspath_fragment {
unsupported: ["hiddenapi/my-unsupported.txt"],
removed: ["hiddenapi/my-removed.txt"],
max_target_r_low_priority: ["hiddenapi/my-max-target-r-low-priority.txt"],
max_target_q: ["hiddenapi/my-max-target-q.txt"],
max_target_q: [
"hiddenapi/my-max-target-q.txt",
"hiddenapi/my-new-max-target-q.txt",
],
max_target_p: ["hiddenapi/my-max-target-p.txt"],
max_target_o_low_priority: ["hiddenapi/my-max-target-o-low-priority.txt"],
blocked: ["hiddenapi/my-blocked.txt"],
@@ -805,6 +832,23 @@ java_import {
permitted_packages: ["mybootlib"],
}
java_sdk_library_import {
name: "mynewlibrary",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["myapex"],
shared_library: true,
compile_dex: true,
permitted_packages: ["mysdklibrary"],
public: {
jars: ["sdk_library/public/mynewlibrary-stubs.jar"],
stub_srcs: ["sdk_library/public/mynewlibrary_stub_sources"],
current_api: "sdk_library/public/mynewlibrary.txt",
removed_api: "sdk_library/public/mynewlibrary-removed.txt",
sdk_version: "current",
},
}
java_sdk_library_import {
name: "mysdklibrary",
prefer: false,
@@ -827,6 +871,7 @@ my-unsupported.txt -> hiddenapi/my-unsupported.txt
my-removed.txt -> hiddenapi/my-removed.txt
my-max-target-r-low-priority.txt -> hiddenapi/my-max-target-r-low-priority.txt
my-max-target-q.txt -> hiddenapi/my-max-target-q.txt
my-new-max-target-q.txt -> hiddenapi/my-new-max-target-q.txt
my-max-target-p.txt -> hiddenapi/my-max-target-p.txt
my-max-target-o-low-priority.txt -> hiddenapi/my-max-target-o-low-priority.txt
my-blocked.txt -> hiddenapi/my-blocked.txt
@@ -838,6 +883,9 @@ my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
.intermediates/mynewlibrary.stubs/android_common/javac/mynewlibrary.stubs.jar -> sdk_library/public/mynewlibrary-stubs.jar
.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_api.txt -> sdk_library/public/mynewlibrary.txt
.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_removed.txt -> sdk_library/public/mynewlibrary-removed.txt
.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt