diff --git a/apex/apex_test.go b/apex/apex_test.go index 484b807a5..4e2c1beab 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4646,6 +4646,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 { @@ -4658,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 { @@ -4673,10 +4684,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") @@ -4692,7 +4704,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 { @@ -4707,10 +4725,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") @@ -4733,7 +4752,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 { @@ -4754,6 +4779,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4769,7 +4795,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) { @@ -4784,7 +4810,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 { @@ -4807,6 +4839,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4817,7 +4850,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") @@ -4853,7 +4886,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 { @@ -4874,6 +4913,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4884,7 +4924,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") @@ -4920,7 +4960,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 { @@ -4943,6 +4989,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { jars: ["libbar.jar"], }, apex_available: ["myapex"], + shared_library: false, } java_sdk_library { @@ -4953,7 +5000,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") @@ -6528,7 +6575,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 := ` @@ -6547,6 +6594,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 { @@ -6578,7 +6634,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, } @@ -6593,7 +6649,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", } @@ -6626,10 +6682,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{ @@ -6657,11 +6713,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) @@ -6769,7 +6836,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) { @@ -6801,7 +6872,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) { @@ -6832,6 +6907,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" , @@ -6843,36 +6923,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 02343adba..3f5c94067 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. @@ -280,7 +276,15 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. return nil } - 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() @@ -297,9 +301,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) @@ -329,7 +330,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() @@ -339,7 +340,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)