From 3db3547d1fc19a18aa180d3b929270a6736fb501 Mon Sep 17 00:00:00 2001 From: satayev Date: Thu, 6 May 2021 23:59:58 +0100 Subject: [PATCH] Generate empty classpaths.proto for bootclasspath_fragment.go. - Adds all required details for bootclasspath_fragment to implement classpath_fragment. - Keeps the actual boot jars in platform-bootclasspath to begin with. - Makes sure to put the file in apex/etc/classpath on device. Note that for platform versions of classpath fragment AndroidMkEntries perform the installation, while for APEXes it must be plumbed via apex.go. Bug: 180105615 Test: m && launch_cvd; atest CtsClasspathsTestCases Change-Id: I6101ebdf5b8bcbe95c0b7ce21f3f67a2685aef50 --- android/config.go | 9 ++++ apex/apex.go | 5 +++ apex/bootclasspath_fragment_test.go | 2 + java/bootclasspath_fragment.go | 66 ++++++++++++++++++++++------- java/classpath_fragment.go | 2 + java/platform_bootclasspath.go | 1 + 6 files changed, 70 insertions(+), 15 deletions(-) diff --git a/android/config.go b/android/config.go index 3db798081..79917adf4 100644 --- a/android/config.go +++ b/android/config.go @@ -1564,6 +1564,15 @@ func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool { return false } +// ApexOfJar returns the apex component of the first pair with the given jar name on the list, or +// an empty string if not found. +func (l *ConfiguredJarList) ApexOfJar(jar string) string { + if idx := IndexList(jar, l.jars); idx != -1 { + return l.Apex(IndexList(jar, l.jars)) + } + return "" +} + // IndexOfJar returns the first pair with the given jar name on the list, or -1 // if not found. func (l *ConfiguredJarList) IndexOfJar(jar string) int { diff --git a/apex/apex.go b/apex/apex.go index 949d80ed3..7ceb00b8a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2097,6 +2097,11 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. } } + // Add classpaths.proto config. + classpathProtoOutput := bootclasspathFragmentInfo.ClasspathFragmentProtoOutput + classpathProto := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), bootclasspathFragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) + filesToAdd = append(filesToAdd, classpathProto) + return filesToAdd } diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index e2b320ca0..7bb3ff611 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -279,6 +279,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/classpaths/mybootclasspathfragment.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", "javalib/arm/boot.vdex", @@ -481,6 +482,7 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) { ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ // This does not include art, oat or vdex files as they are only included for the art boot // image. + "etc/classpaths/mybootclasspathfragment.pb", "javalib/bar.jar", "javalib/foo.jar", }) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 6270b5b35..bed629da3 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -109,6 +109,8 @@ type BootclasspathFragmentModule struct { android.ModuleBase android.ApexModuleBase android.SdkBase + ClasspathFragmentBase + properties bootclasspathFragmentProperties } @@ -117,6 +119,7 @@ func bootclasspathFragmentFactory() android.Module { m.AddProperties(&m.properties) android.InitApexModule(m) android.InitSdkAwareModule(m) + initClasspathFragment(m, BOOTCLASSPATH) android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon) android.AddLoadHook(m, func(ctx android.LoadHookContext) { @@ -242,6 +245,22 @@ var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(Bootcla // BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the // apex contents. type BootclasspathFragmentApexContentInfo struct { + // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module. + // + // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir + // for more details. + ClasspathFragmentProtoOutput android.OutputPath + + // ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file. + // + // The path encodes expected sub-location within partitions, i.e. etc/classpaths/, + // for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path + // use android.InstallPath#Rel(). + // + // This is only relevant for APEX modules as they perform their own installation; while regular + // system files are installed via ClasspathFragmentBase#androidMkEntries(). + ClasspathFragmentProtoInstallDir android.InstallPath + // The image config, internal to this module (and the dex_bootjars singleton). // // Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur @@ -339,30 +358,47 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo b.bootclasspathImageNameContentsConsistencyCheck(ctx) } + // Generate classpaths.proto config + b.generateClasspathProtoBuildActions(ctx) + // Perform hidden API processing. b.generateHiddenAPIBuildActions(ctx) - // Nothing to do if skipping the dexpreopt of boot image jars. - if SkipDexpreoptBootJars(ctx) { - return - } - - // 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) - - imageConfig := b.getImageConfig(ctx) - if imageConfig == nil { - return - } - // Construct the boot image info from the config. - info := BootclasspathFragmentApexContentInfo{imageConfig: imageConfig} + info := BootclasspathFragmentApexContentInfo{ + ClasspathFragmentProtoInstallDir: b.classpathFragmentBase().installDirPath, + ClasspathFragmentProtoOutput: b.classpathFragmentBase().outputFilepath, + imageConfig: nil, + } + + 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. + dexpreopt.GetGlobalSoongConfig(ctx) + info.imageConfig = b.getImageConfig(ctx) + } // Make it available for other modules. ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) } +// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config +func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { + var classpathJars []classpathJar + if "art" == proptools.String(b.properties.Image_name) { + // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH + classpathJars = configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + } else { + classpathJars = configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), b.classpathType) + } + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) +} + +func (b *BootclasspathFragmentModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { + // TODO(satayev): populate with actual content + return android.EmptyConfiguredJarList() +} + func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { // Get a map of the image configs that are supported. imageConfigs := genBootImageConfigs(ctx) diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go index 2e0582390..7422fa2d5 100644 --- a/java/classpath_fragment.go +++ b/java/classpath_fragment.go @@ -143,6 +143,8 @@ func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, android.WriteFileRule(ctx, output, content.String()) } +// Returns AndroidMkEntries objects to install generated classpath.proto. +// Do not use this to install into APEXes as the injection of the generated files happen separately for APEXes. func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{{ Class: "ETC", diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 1caffe48c..c787e4797 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -203,6 +203,7 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH classpathJars := configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + // TODO(satayev): remove updatable boot jars once each apex has its own fragment global := dexpreopt.GetGlobalConfig(ctx) classpathJars = append(classpathJars, configuredJarListToClasspathJars(ctx, global.UpdatableBootJars, BOOTCLASSPATH)...)