From 1a8010a24171c4ac1928b659f48dc680ee8b0353 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Sat, 15 May 2021 12:39:23 +0100 Subject: [PATCH] Store dex jar paths in bootclasspath_fragment's apex content info Previously, the DexBootJarPathForContentModule(module) simply called directly through to the module to retrieve the dex jar path. This change changes it so the bootclasspath_fragment retrieves the dex jars from the module and stores them in the info structure for this method to retrieve directly. This makes it easier for the bootclasspath_fragment to stop retrieving hidden API encoded dex jars from the module and perform the encoding itself. Bug: 179354495 Test: m com.android.art com.android.ipsec com.android.os.statsd com.android.conscrypt - verify that this does not change the contents of the apex files Change-Id: Ic79dea080f10f4017f1a75d6d1fb5a3bfe04c2ce --- apex/apex.go | 5 ++- apex/bootclasspath_fragment_test.go | 5 ++- java/bootclasspath_fragment.go | 55 ++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 7b2e19d03..8122e8b9d 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2149,7 +2149,10 @@ func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fr // Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the // hidden API encpding. - dexBootJar := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule) + dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule) + if err != nil { + ctx.ModuleErrorf("%s", err) + } // Create an apexFile as for a normal java module but with the dex boot jar provided by the // bootclasspath_fragment. diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index 7f5e15c04..9a8c7d0b6 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -512,7 +512,10 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) { checkFragmentExportedDexJar := func(name string, expectedDexJar string) { module := result.Module(name, "android_common_apex10000") - dexJar := info.DexBootJarPathForContentModule(module) + dexJar, err := info.DexBootJarPathForContentModule(module) + if err != nil { + t.Error(err) + } android.AssertPathRelativeToTopEquals(t, name+" dex", expectedDexJar, dexJar) expectedCopyCommand := fmt.Sprintf("&& cp -f %s out/soong/.intermediates/myapex/android_common_myapex_image/image.apex/javalib/%s.jar", expectedDexJar, name) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 5d8a8e525..6b395fbf0 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -273,6 +273,10 @@ type BootclasspathFragmentApexContentInfo struct { // Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur // when SkipDexpreoptBootJars(ctx) returns true. imageConfig *bootImageConfig + + // Map from the name of the context module (as returned by Name()) to the hidden API encoded dex + // jar path. + contentModuleDexJarPaths map[string]android.Path } func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList { @@ -299,10 +303,14 @@ func (i BootclasspathFragmentApexContentInfo) AndroidBootImageFilesByArchType() // DexBootJarPathForContentModule returns the path to the dex boot jar for specified module. // // The dex boot jar is one which has had hidden API encoding performed on it. -func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) android.Path { - j := module.(UsesLibraryDependency) - dexJar := j.DexJarBuildPath() - return dexJar +func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) { + name := module.Name() + if dexJar, ok := i.contentModuleDexJarPaths[name]; ok { + return dexJar, nil + } else { + return nil, fmt.Errorf("unknown bootclasspath_fragment content module %s, expected one of %s", + name, strings.Join(android.SortedStringKeys(i.contentModuleDexJarPaths), ", ")) + } } func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { @@ -380,6 +388,28 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Perform hidden API processing. b.generateHiddenAPIBuildActions(ctx, contents) + // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a + // prebuilt which will not use the image config. + imageConfig := b.getImageConfig(ctx) + + // A prebuilt fragment cannot contribute to the apex. + if !android.IsModulePrebuilt(ctx.Module()) { + // Provide the apex content info. + b.provideApexContentInfo(ctx, imageConfig, contents) + } +} + +// provideApexContentInfo creates, initializes and stores the apex content info for use by other +// modules. +func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) { + // Construct the apex content info from the config. + info := BootclasspathFragmentApexContentInfo{ + imageConfig: imageConfig, + } + + // Populate the apex content info with paths to the dex jars. + b.populateApexContentInfoDexJars(ctx, &info, contents) + if !SkipDexpreoptBootJars(ctx) { // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars // GenerateSingletonBuildActions method as it cannot create it for itself. @@ -387,11 +417,20 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Only generate the boot image if the configuration does not skip it. b.generateBootImageBuildActions(ctx, contents) + } - // Make the boot image info available for other modules - ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, BootclasspathFragmentApexContentInfo{ - imageConfig: b.getImageConfig(ctx), - }) + // Make the apex content info available for other modules. + ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) +} + +// populateApexContentInfoDexJars adds paths to the dex jars provided by this fragment to the +// apex content info. +func (b *BootclasspathFragmentModule) populateApexContentInfoDexJars(ctx android.ModuleContext, info *BootclasspathFragmentApexContentInfo, contents []android.Module) { + info.contentModuleDexJarPaths = map[string]android.Path{} + for _, m := range contents { + j := m.(UsesLibraryDependency) + dexJar := j.DexJarBuildPath() + info.contentModuleDexJarPaths[m.Name()] = dexJar } }