From 3ae9e2cef5c1265d1a1f3c1b51bb68665e66906a Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 16 Jun 2021 01:42:33 +0100 Subject: [PATCH] Use classpath elements in platform_bootclasspath Use classpath elements in newMonolithicHiddenAPIInfo. That means the method can collate information from both fragments and libraries rather than just fragments. So, this change moves the collation of the classesJars into the method. Bug: 177892522 Test: m out/soong/hiddenapi/hiddenapi-flags.csv out/soong/hiddenapi/hiddenapi-index.csv - make sure that this change does not affect the contents. Merged-In: I7c2a229fab60d02bd211438735a8d7303ed83386 Change-Id: I7c2a229fab60d02bd211438735a8d7303ed83386 (cherry picked from commit 89f570ac44af4bcf5b78fa8dad3d57f24cd3ca0e) --- apex/apex_test.go | 167 +++++++++++++++++++--------- apex/platform_bootclasspath_test.go | 29 ++++- java/hiddenapi_monolithic.go | 29 +++-- java/platform_bootclasspath.go | 21 ++-- 4 files changed, 174 insertions(+), 72 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index 1bc25141a..11fed3626 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4423,6 +4423,11 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule) } + fragment := java.ApexVariantReference{ + Apex: proptools.StringPtr("myapex"), + Module: proptools.StringPtr("my-bootclasspath-fragment"), + } + t.Run("prebuilt only", func(t *testing.T) { bp := ` prebuilt_apex { @@ -4435,7 +4440,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4450,10 +4461,11 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } ` - ctx := testDexpreoptWithApexes(t, bp, "", preparer) + ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") @@ -4469,7 +4481,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { apex_set { name: "myapex", set: "myapex.apks", - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4484,10 +4502,11 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } ` - ctx := testDexpreoptWithApexes(t, bp, "", preparer) + ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") @@ -4510,7 +4529,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4531,6 +4556,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4546,7 +4572,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { // prebuilt_apex module always depends on the prebuilt, and so it doesn't // find the dex boot jar in it. We either need to disable the source libfoo // or make the prebuilt libfoo preferred. - testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer) + testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment) }) t.Run("prebuilt library preferred with source", func(t *testing.T) { @@ -4561,7 +4587,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4584,6 +4616,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4594,7 +4627,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { } ` - ctx := testDexpreoptWithApexes(t, bp, "", preparer) + ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") @@ -4630,7 +4663,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4651,6 +4690,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4661,7 +4701,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { } ` - ctx := testDexpreoptWithApexes(t, bp, "", preparer) + ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar") @@ -4697,7 +4737,13 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo", "libbar"], + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo", "libbar"], + apex_available: ["myapex"], } java_import { @@ -4720,6 +4766,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4730,7 +4777,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { } ` - ctx := testDexpreoptWithApexes(t, bp, "", preparer) + ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar") @@ -6305,7 +6352,7 @@ func TestAppSetBundlePrebuilt(t *testing.T) { android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String()) } -func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer) { +func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) { t.Helper() bp := ` @@ -6324,6 +6371,15 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi apex_available: [ "some-non-updatable-apex", ], + compile_dex: true, + } + + bootclasspath_fragment { + name: "some-non-updatable-fragment", + contents: ["some-non-updatable-apex-lib"], + apex_available: [ + "some-non-updatable-apex", + ], } java_library { @@ -6355,7 +6411,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi apex { name: "some-non-updatable-apex", key: "some-non-updatable-apex.key", - java_libs: ["some-non-updatable-apex-lib"], + bootclasspath_fragments: ["some-non-updatable-fragment"], updatable: false, } @@ -6370,7 +6426,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi apex { name: "com.android.art.debug", key: "com.android.art.debug.key", - java_libs: ["some-art-lib"], + bootclasspath_fragments: ["art-bootclasspath-fragment"], updatable: true, min_sdk_version: "current", } @@ -6403,10 +6459,10 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi } ` - testDexpreoptWithApexes(t, bp, errmsg, preparer) + testDexpreoptWithApexes(t, bp, errmsg, preparer, fragments...) } -func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer) *android.TestContext { +func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext { t.Helper() fs := android.MockFS{ @@ -6434,11 +6490,22 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F PrepareForTestWithApexBuildComponents, preparer, fs.AddToFixture(), - android.FixtureAddTextFile("frameworks/base/boot/Android.bp", ` - platform_bootclasspath { - name: "platform-bootclasspath", + android.FixtureModifyMockFS(func(fs android.MockFS) { + if _, ok := fs["frameworks/base/boot/Android.bp"]; !ok { + insert := "" + for _, fragment := range fragments { + insert += fmt.Sprintf("{apex: %q, module: %q},\n", *fragment.Apex, *fragment.Module) + } + fs["frameworks/base/boot/Android.bp"] = []byte(fmt.Sprintf(` + platform_bootclasspath { + name: "platform-bootclasspath", + fragments: [ + %s + ], + } + `, insert)) } - `), + }), ). ExtendWithErrorHandler(errorHandler). RunTestWithBp(t, bp) @@ -6505,7 +6572,11 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) { preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib") - testNoUpdatableJarsInBootImage(t, "", preparer) + fragment := java.ApexVariantReference{ + Apex: proptools.StringPtr("com.android.art.debug"), + Module: proptools.StringPtr("art-bootclasspath-fragment"), + } + testNoUpdatableJarsInBootImage(t, "", preparer, fragment) }) t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) { @@ -6537,7 +6608,11 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) { preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib") - testNoUpdatableJarsInBootImage(t, "", preparer) + fragment := java.ApexVariantReference{ + Apex: proptools.StringPtr("some-non-updatable-apex"), + Module: proptools.StringPtr("some-non-updatable-fragment"), + } + testNoUpdatableJarsInBootImage(t, "", preparer, fragment) }) t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) { @@ -6568,6 +6643,11 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) { preparer := java.FixtureConfigureBootJars("myapex:libfoo") t.Run("prebuilt no source", func(t *testing.T) { + fragment := java.ApexVariantReference{ + Apex: proptools.StringPtr("myapex"), + Module: proptools.StringPtr("my-bootclasspath-fragment"), + } + testDexpreoptWithApexes(t, ` prebuilt_apex { name: "myapex" , @@ -6579,36 +6659,21 @@ func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) { src: "myapex-arm.apex", }, }, - exported_java_libs: ["libfoo"], - } + exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], + } - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - } -`, "", preparer) - }) + prebuilt_bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["libfoo"], + apex_available: ["myapex"], + } - t.Run("prebuilt no source", func(t *testing.T) { - testDexpreoptWithApexes(t, ` - prebuilt_apex { - name: "myapex" , - arch: { - arm64: { - src: "myapex-arm64.apex", - }, - arm: { - src: "myapex-arm.apex", - }, - }, - exported_java_libs: ["libfoo"], - } - - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - } -`, "", preparer) + java_import { + name: "libfoo", + jars: ["libfoo.jar"], + apex_available: ["myapex"], + } + `, "", preparer, fragment) }) } diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go index 729792663..bd4a9d599 100644 --- a/apex/platform_bootclasspath_test.go +++ b/apex/platform_bootclasspath_test.go @@ -234,12 +234,18 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { apex { name: "myapex", key: "myapex.key", - java_libs: [ - "bar", + bootclasspath_fragments: [ + "my-bootclasspath-fragment", ], updatable: false, } + bootclasspath_fragment { + name: "my-bootclasspath-fragment", + contents: ["bar"], + apex_available: ["myapex"], + } + apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", @@ -267,6 +273,10 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { apex: "com.android.art", module: "art-bootclasspath-fragment", }, + { + apex: "myapex", + module: "my-bootclasspath-fragment", + }, ], } `, @@ -283,7 +293,8 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { }) java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{ - `com.android.art:art-bootclasspath-fragment`, + "com.android.art:art-bootclasspath-fragment", + "myapex:my-bootclasspath-fragment", }) // Make sure that the myplatform-bootclasspath has the correct dependencies. @@ -307,6 +318,7 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { // The fragments. `com.android.art:art-bootclasspath-fragment`, + `myapex:my-bootclasspath-fragment`, }) } @@ -410,6 +422,12 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) { platform_bootclasspath { name: "myplatform-bootclasspath", + fragments: [ + { + apex: "myapex", + module:"mybootclasspath-fragment", + }, + ], } `, ) @@ -431,7 +449,7 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) { "platform:legacy.core.platform.api.stubs", // Needed for generating the boot image. - `platform:dex2oatd`, + "platform:dex2oatd", // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt // modules when available as it does not know which one will be preferred. @@ -442,6 +460,9 @@ func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) { // Only a source module exists. "myapex:bar", + + // The fragments. + "myapex:mybootclasspath-fragment", }) } diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go index edf42351f..8a83d1006 100644 --- a/java/hiddenapi_monolithic.go +++ b/java/hiddenapi_monolithic.go @@ -43,22 +43,37 @@ type MonolithicHiddenAPIInfo struct { // The paths to the generated all-flags.csv files. AllFlagsPaths android.Paths + + // The classes jars from the libraries on the platform bootclasspath. + ClassesJars android.Paths } // newMonolithicHiddenAPIInfo creates a new MonolithicHiddenAPIInfo from the flagFilesByCategory // plus information provided by each of the fragments. -func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, fragments []android.Module) MonolithicHiddenAPIInfo { +func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, classpathElements ClasspathElements) MonolithicHiddenAPIInfo { monolithicInfo := MonolithicHiddenAPIInfo{} monolithicInfo.FlagsFilesByCategory = flagFilesByCategory - // Merge all the information from the fragments. The fragments form a DAG so it is possible that - // this will introduce duplicates so they will be resolved after processing all the fragments. - for _, fragment := range fragments { - if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) { - info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo) - monolithicInfo.append(&info) + // Merge all the information from the classpathElements. The fragments form a DAG so it is possible that + // this will introduce duplicates so they will be resolved after processing all the classpathElements. + for _, element := range classpathElements { + var classesJars android.Paths + switch e := element.(type) { + case *ClasspathLibraryElement: + classesJars = retrieveClassesJarsFromModule(e.Module()) + + case *ClasspathFragmentElement: + fragment := e.Module() + if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) { + info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo) + monolithicInfo.append(&info) + } + + classesJars = extractClassesJarsFromModules(e.Contents) } + + monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...) } // Dedup paths. diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 48da29eb2..46fc7b5fd 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -44,13 +44,9 @@ type platformBootclasspathModule struct { properties platformBootclasspathProperties // The apex:module pairs obtained from the configured modules. - // - // Currently only for testing. configuredModules []android.Module // The apex:module pairs obtained from the fragments. - // - // Currently only for testing. fragments []android.Module // Path to the monolithic hiddenapi-flags.csv file. @@ -282,7 +278,15 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. return bootDexJarByModule } - monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments) + // Construct a list of ClasspathElement objects from the modules and fragments. + classpathElements := CreateClasspathElements(ctx, modules, fragments) + + monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements) + + // Extract the classes jars only from those libraries that do not have corresponding fragments as + // the fragments will have already provided the flags that are needed. + classesJars := monolithicInfo.ClassesJars + // Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile input := newHiddenAPIFlagInput() @@ -298,9 +302,6 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJarByModule.bootDexJars(), input) rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags") - // Extract the classes jars from the contents. - classesJars := extractClassesJarsFromModules(modules) - // Generate the annotation-flags.csv file from all the module annotations. annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv") buildRuleToGenerateAnnotationFlags(ctx, "monolithic hiddenapi flags", classesJars, stubFlags, annotationFlags) @@ -330,7 +331,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. // createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for // testing. -func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, fragments []android.Module) MonolithicHiddenAPIInfo { +func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, classpathElements ClasspathElements) MonolithicHiddenAPIInfo { // Create a temporary input structure in which to collate information provided directly by this // module, either through properties or direct dependencies. temporaryInput := newHiddenAPIFlagInput() @@ -340,7 +341,7 @@ func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ct // Create the monolithic info, by starting with the flag files specified on this and then merging // in information from all the fragment dependencies of this. - monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments) + monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, classpathElements) // Store the information for testing. ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)