diff --git a/apex/Android.bp b/apex/Android.bp index 77dde72ac..b6fdcf415 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -25,6 +25,7 @@ bootstrap_go_package { ], testSrcs: [ "apex_test.go", + "boot_image_test.go", "vndk_test.go", ], pluginFor: ["soong_build"], diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go new file mode 100644 index 000000000..07feb0358 --- /dev/null +++ b/apex/boot_image_test.go @@ -0,0 +1,128 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apex + +import ( + "testing" + + "android/soong/android" + "android/soong/dexpreopt" + "android/soong/java" +) + +// Contains tests for boot_image logic from java/boot_image.go as the ART boot image requires +// modules from the ART apex. + +func TestBootImages(t *testing.T) { + ctx, _ := testApex(t, ` + java_sdk_library { + name: "foo", + srcs: ["b.java"], + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "bar", + srcs: ["b.java"], + installable: true, + } + + apex { + name: "com.android.art", + key: "com.android.art.key", + java_libs: [ + "baz", + "quuz", + ], + } + + apex_key { + name: "com.android.art.key", + public_key: "com.android.art.avbpubkey", + private_key: "com.android.art.pem", + } + + java_library { + name: "baz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + } + + java_library { + name: "quuz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + } +`, + // Configure some libraries in the art and framework boot images. + withArtBootImageJars("com.android.art:baz", "com.android.art:quuz"), + withFrameworkBootImageJars("platform:foo", "platform:bar"), + withFiles(filesForSdkLibrary), + // Some additional files needed for the art apex. + withFiles(map[string][]byte{ + "com.android.art.avbpubkey": nil, + "com.android.art.pem": nil, + "system/sepolicy/apex/com.android.art-file_contexts": nil, + }), + ) + + // Make sure that the framework-boot-image is using the correct configuration. + checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar") + + // Make sure that the art-boot-image is using the correct configuration. + checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz") +} + +func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string) { + t.Helper() + + bootImage := ctx.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule) + + bootImageInfo := ctx.ModuleProvider(bootImage, java.BootImageInfoProvider).(java.BootImageInfo) + modules := bootImageInfo.Modules() + if actual := modules.String(); actual != expectedConfiguredModules { + t.Errorf("invalid modules for %s: expected %q, actual %q", moduleName, expectedConfiguredModules, actual) + } +} + +func modifyDexpreoptConfig(configModifier func(dexpreoptConfig *dexpreopt.GlobalConfig)) func(fs map[string][]byte, config android.Config) { + return func(fs map[string][]byte, config android.Config) { + // Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has + // already been set. + pathCtx := android.PathContextForTesting(config) + dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx) + dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig) + + // Retrieve the existing configuration and modify it. + dexpreoptConfig = dexpreopt.GetGlobalConfig(pathCtx) + configModifier(dexpreoptConfig) + } +} + +func withArtBootImageJars(bootJars ...string) func(fs map[string][]byte, config android.Config) { + return modifyDexpreoptConfig(func(dexpreoptConfig *dexpreopt.GlobalConfig) { + dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars) + }) +} + +func withFrameworkBootImageJars(bootJars ...string) func(fs map[string][]byte, config android.Config) { + return modifyDexpreoptConfig(func(dexpreoptConfig *dexpreopt.GlobalConfig) { + dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars) + }) +} diff --git a/java/Android.bp b/java/Android.bp index 9c28968f6..364566a8b 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -24,6 +24,7 @@ bootstrap_go_package { "app.go", "app_import.go", "app_set.go", + "boot_image.go", "boot_jars.go", "builder.go", "device_host_converter.go", @@ -63,6 +64,7 @@ bootstrap_go_package { "app_import_test.go", "app_set_test.go", "app_test.go", + "boot_image_test.go", "device_host_converter_test.go", "dexpreopt_test.go", "dexpreopt_bootjars_test.go", diff --git a/java/boot_image.go b/java/boot_image.go new file mode 100644 index 000000000..07ef0d841 --- /dev/null +++ b/java/boot_image.go @@ -0,0 +1,85 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "strings" + + "android/soong/android" + "github.com/google/blueprint" +) + +func init() { + RegisterBootImageBuildComponents(android.InitRegistrationContext) +} + +func RegisterBootImageBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("boot_image", bootImageFactory) +} + +type bootImageProperties struct { + // The name of the image this represents. + // + // Must be one of "art" or "boot". + Image_name string +} + +type BootImageModule struct { + android.ModuleBase + + properties bootImageProperties +} + +func bootImageFactory() android.Module { + m := &BootImageModule{} + m.AddProperties(&m.properties) + android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibCommon) + return m +} + +var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{}) + +type BootImageInfo struct { + // The image config, internal to this module (and the dex_bootjars singleton). + imageConfig *bootImageConfig +} + +func (i BootImageInfo) Modules() android.ConfiguredJarList { + return i.imageConfig.modules +} + +func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Nothing to do if skipping the dexpreopt of boot image jars. + if SkipDexpreoptBootJars(ctx) { + return + } + + // Get a map of the image configs that are supported. + imageConfigs := genBootImageConfigs(ctx) + + // Retrieve the config for this image. + imageName := b.properties.Image_name + imageConfig := imageConfigs[imageName] + if imageConfig == nil { + ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", ")) + return + } + + // Construct the boot image info from the config. + info := BootImageInfo{imageConfig: imageConfig} + + // Make it available for other modules. + ctx.SetProvider(BootImageInfoProvider, info) +} diff --git a/java/boot_image_test.go b/java/boot_image_test.go new file mode 100644 index 000000000..a29578292 --- /dev/null +++ b/java/boot_image_test.go @@ -0,0 +1,31 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "testing" +) + +// Contains some simple tests for boot_image logic, additional tests can be found in +// apex/boot_image_test.go as the ART boot image requires modules from the ART apex. + +func TestUnknownBootImage(t *testing.T) { + testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", ` + boot_image { + name: "unknown-boot-image", + image_name: "unknown", + } +`) +} diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 004cbbb5a..78d9d02de 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -35,6 +35,13 @@ import ( // // Changes: // 1) dex_bootjars is now a singleton module and not a plain singleton. +// 2) Boot images are now represented by the boot_image module type. +// 3) The art boot image is called "art-boot-image", the framework boot image is called +// "framework-boot-image". +// 4) They are defined in art/build/boot/Android.bp and frameworks/base/boot/Android.bp +// respectively. +// 5) Each boot_image retrieves the appropriate boot image configuration from the map returned by +// genBootImageConfigs() using the image_name specified in the boot_image module. // ================================================================================================= // This comment describes: diff --git a/java/testing.go b/java/testing.go index 0b1f2d137..31ff47ff4 100644 --- a/java/testing.go +++ b/java/testing.go @@ -107,6 +107,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterAppBuildComponents(ctx) RegisterAppImportBuildComponents(ctx) RegisterAppSetBuildComponents(ctx) + RegisterBootImageBuildComponents(ctx) RegisterDexpreoptBootJarsComponents(ctx) RegisterDocsBuildComponents(ctx) RegisterGenRuleBuildComponents(ctx) @@ -218,6 +219,16 @@ func GatherRequiredDepsForTest() string { dex_bootjars { name: "dex_bootjars", } + + boot_image { + name: "art-boot-image", + image_name: "art", + } + + boot_image { + name: "framework-boot-image", + image_name: "boot", + } ` return bp