From 49b1eb6b045156c6481df584fdd21348a9df3383 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Fri, 26 Nov 2021 18:09:27 +0000 Subject: [PATCH] Add ART boot image profile to the ART APEX. We will need the profile when we generate the primary boot image on device. Bug: 203492478 Test: Run `banchan com.android.art x86_64 && m` and see `$ANDROID_PRODUCT_OUT/apex/com.android.art/etc/boot-image.prof`. Test: Run `lunch aosp_cf_x86_64_phone-userdebug && m` and see both `$ANDROID_PRODUCT_OUT/apex/com.android.art/etc/boot-image.prof` and `$ANDROID_PRODUCT_OUT/system/etc/boot-image.prof`, in different sizes. Test: Start Cuttlefish with the built image and see both `/apex/com.android.art/etc/boot-image.prof` and `/system/etc/boot-image.prof` on device. Change-Id: Id879dc49b234133dfbb9563814328661a1f4a6c0 --- apex/apex.go | 34 ++++++++++++++++++++++++++ apex/apex_test.go | 1 + apex/bootclasspath_fragment_test.go | 16 ++++++++---- dexpreopt/testing.go | 29 +++++++++++++--------- java/bootclasspath_fragment.go | 17 +++++++++++++ java/dexpreopt_bootjars.go | 14 +++++++++-- java/dexpreopt_config.go | 16 ++++++------ sdk/bootclasspath_fragment_sdk_test.go | 1 + 8 files changed, 101 insertions(+), 27 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 9a299dee5..56bd2f76e 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2159,6 +2159,40 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. filesToAdd = append(filesToAdd, *af) } + if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" { + pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost() + tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex) + + if pathOnHost != nil { + // We need to copy the profile to a temporary path with the right filename because the apexer + // will take the filename as is. + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: pathOnHost, + Output: tempPath, + }) + } else { + // At this point, the boot image profile cannot be generated. It is probably because the boot + // image profile source file does not exist on the branch, or it is not available for the + // current build target. + // However, we cannot enforce the boot image profile to be generated because some build + // targets (such as module SDK) do not need it. It is only needed when the APEX is being + // built. Therefore, we create an error rule so that an error will occur at the ninja phase + // only if the APEX is being built. + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: tempPath, + Args: map[string]string{ + "error": "Boot image profile cannot be generated", + }, + }) + } + + androidMkModuleName := filepath.Base(pathInApex) + af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil) + filesToAdd = append(filesToAdd, af) + } + return filesToAdd } diff --git a/apex/apex_test.go b/apex/apex_test.go index 130581ca4..59b94cf33 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -7037,6 +7037,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F `, insert)) } }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), ). ExtendWithErrorHandler(errorHandler). RunTestWithBp(t, bp) diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index cb7d3d113..9e030f10c 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -21,6 +21,7 @@ import ( "testing" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" "github.com/google/blueprint/proptools" @@ -35,11 +36,14 @@ var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers( ) // Some additional files needed for the art apex. -var prepareForTestWithArtApex = android.FixtureMergeMockFs(android.MockFS{ - "com.android.art.avbpubkey": nil, - "com.android.art.pem": nil, - "system/sepolicy/apex/com.android.art-file_contexts": nil, -}) +var prepareForTestWithArtApex = android.GroupFixturePreparers( + android.FixtureMergeMockFs(android.MockFS{ + "com.android.art.avbpubkey": nil, + "com.android.art.pem": nil, + "system/sepolicy/apex/com.android.art-file_contexts": nil, + }), + dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"), +) func TestBootclasspathFragments(t *testing.T) { result := android.GroupFixturePreparers( @@ -408,6 +412,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", @@ -451,6 +456,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { ).RunTest(t) ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{ + "etc/boot-image.prof", "etc/classpaths/bootclasspath.pb", "javalib/arm/boot.art", "javalib/arm/boot.oat", diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go index 2fba01aa7..5131cd3f4 100644 --- a/dexpreopt/testing.go +++ b/dexpreopt/testing.go @@ -85,12 +85,12 @@ var PrepareForTestWithFakeDex2oatd = android.GroupFixturePreparers( // Prepares a test fixture by enabling dexpreopt, registering the fake_tool_binary module type and // using that to define the `dex2oatd` module. var PrepareForTestByEnablingDexpreopt = android.GroupFixturePreparers( - FixtureModifyGlobalConfig(func(*GlobalConfig) {}), + FixtureModifyGlobalConfig(func(android.PathContext, *GlobalConfig) {}), ) // FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the // configuration. -func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig)) android.FixturePreparer { +func FixtureModifyGlobalConfig(configModifier func(ctx android.PathContext, dexpreoptConfig *GlobalConfig)) android.FixturePreparer { return android.FixtureModifyConfig(func(config android.Config) { // Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has // already been set. @@ -100,48 +100,48 @@ func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig // Retrieve the existing configuration and modify it. dexpreoptConfig = GetGlobalConfig(pathCtx) - configModifier(dexpreoptConfig) + configModifier(pathCtx, dexpreoptConfig) }) } // FixtureSetArtBootJars enables dexpreopt and sets the ArtApexJars property. func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetBootJars enables dexpreopt and sets the BootJars property. func FixtureSetBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetApexBootJars sets the ApexBootJars property in the global config. func FixtureSetApexBootJars(bootJars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexBootJars = android.CreateTestConfiguredJarList(bootJars) }) } // FixtureSetStandaloneSystemServerJars sets the StandaloneSystemServerJars property. func FixtureSetStandaloneSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetSystemServerJars sets the SystemServerJars property. func FixtureSetSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.SystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config. func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } @@ -149,14 +149,21 @@ func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer { // FixtureSetApexStandaloneSystemServerJars sets the ApexStandaloneSystemServerJars property in the // global config. func FixtureSetApexStandaloneSystemServerJars(jars ...string) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars) }) } // FixtureSetPreoptWithUpdatableBcp sets the PreoptWithUpdatableBcp property in the global config. func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer { - return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) { + return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) { dexpreoptConfig.PreoptWithUpdatableBcp = value }) } + +// FixtureSetBootImageProfiles sets the BootImageProfiles property in the global config. +func FixtureSetBootImageProfiles(profiles ...string) android.FixturePreparer { + return FixtureModifyGlobalConfig(func(ctx android.PathContext, dexpreoptConfig *GlobalConfig) { + dexpreoptConfig.BootImageProfiles = android.PathsForSource(ctx, profiles) + }) +} diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index bfa683824..df1e121be 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -390,6 +390,13 @@ type BootclasspathFragmentApexContentInfo struct { // Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the // hidden API encoded dex jar path. contentModuleDexJarPaths bootDexJarByModule + + // Path to the image profile file on host (or empty, if profile is not generated). + profilePathOnHost android.Path + + // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not + // needed. + profileInstallPathInApex string } func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList { @@ -418,6 +425,14 @@ func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(mod } } +func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path { + return i.profilePathOnHost +} + +func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string { + return i.profileInstallPathInApex +} + func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { tag := ctx.OtherModuleDependencyTag(dep) if IsBootclasspathFragmentContentDepTag(tag) { @@ -579,6 +594,8 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC if imageConfig != nil { info.modules = imageConfig.modules + info.profilePathOnHost = imageConfig.profilePathOnHost + info.profileInstallPathInApex = imageConfig.profileInstallPathInApex } info.bootImageFilesByArch = bootImageFilesByArch diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index a72294626..75083e8c2 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -256,6 +256,10 @@ type bootImageConfig struct { // Subdirectory where the image files on device are installed. installDirOnDevice string + // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not + // needed. + profileInstallPathInApex string + // A list of (location, jar) pairs for the Java modules in this image. modules android.ConfiguredJarList @@ -272,6 +276,9 @@ type bootImageConfig struct { // Rules which should be used in make to install the outputs. profileInstalls android.RuleBuilderInstalls + // Path to the image profile file on host (or empty, if profile is not generated). + profilePathOnHost android.Path + // Target-dependent fields. variants []*bootImageVariant } @@ -769,11 +776,14 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps). FlagWithOutput("--reference-profile-file=", profile) - rule.Install(profile, "/system/etc/boot-image.prof") + if image == defaultBootImageConfig(ctx) { + rule.Install(profile, "/system/etc/boot-image.prof") + image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + } rule.Build("bootJarsProfile", "profile boot jars") - image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + image.profilePathOnHost = profile return profile } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 415a1d4e7..26c110544 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -56,22 +56,20 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { artModules := global.ArtApexJars frameworkModules := global.BootJars.RemoveList(artModules) - artDirOnHost := "apex/art_boot_images/javalib" - artDirOnDevice := "apex/com.android.art/javalib" - frameworkSubdir := "system/framework" - // ART config for the primary boot image in the ART apex. // It includes the Core Libraries. artCfg := bootImageConfig{ - name: artBootImageName, - stem: "boot", - installDirOnHost: artDirOnHost, - installDirOnDevice: artDirOnDevice, - modules: artModules, + name: artBootImageName, + stem: "boot", + installDirOnHost: "apex/art_boot_images/javalib", + installDirOnDevice: "apex/com.android.art/javalib", + profileInstallPathInApex: "etc/boot-image.prof", + modules: artModules, } // Framework config for the boot image extension. // It includes framework libraries and depends on the ART config. + frameworkSubdir := "system/framework" frameworkCfg := bootImageConfig{ extends: &artCfg, name: frameworkBootImageName, diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index ff2af439f..2dacdb55c 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -40,6 +40,7 @@ func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment stri } `, apex, fragment)), android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil), + android.FixtureAddFile("frameworks/base/config/boot-image-profile.txt", nil), android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil), ) }