Allow installing boot images outside of APEX for prebuilt.
This change is similar to aosp/1947127, but for prebuilts.
After this change, if `bootImageConfig.installDirOnDevice` is set to a
path outside of the APEX, the build system will build a boot image from
the dex files and the profile extracted from the prebuilt APEX.
Otherwise, it keeps the current behavior: extracting the boot image from
the prebuilt APEX.
This is a no-op change. Current behavior is not affected.
Bug: 211973309
Test: m nothing
Test: -
On internal master:
1. Patch aosp/1947128.
2. Patch ag/16743847 and ag/16746804.
3. m SOONG_CONFIG_art_module_source_build=false com.google.android.art
4. See the boot image being installed in `/system/framework/<arch>`.
Change-Id: I24ca525309fecaf3ab7a67960fbf118cd00ecd1d
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 8f44fc5..ce6b7f7 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -553,12 +553,66 @@
`prebuilt_com.android.art`,
})
+ // The boot images are installed in the APEX by Soong, so there shouldn't be any dexpreopt-related Make modules.
+ ensureDoesNotContainRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+
// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
+ t.Run("boot image files from preferred prebuilt no boot image in apex", func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ commonPreparer,
+
+ // Configure some libraries in the art bootclasspath_fragment that match the source
+ // bootclasspath_fragment's contents property.
+ java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ addSource("foo", "bar"),
+
+ // Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
+ addPrebuilt(true, "foo", "bar"),
+
+ java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
+ ).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/bar.jar",
+ "javalib/foo.jar",
+ })
+
+ ensureContainsRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+ })
+
t.Run("source with inconsistency between config and contents", func(t *testing.T) {
android.GroupFixturePreparers(
commonPreparer,
@@ -631,6 +685,7 @@
// Configure some libraries in the art bootclasspath_fragment.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
)
bp := `
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 02d8075..158c804 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -65,7 +65,8 @@
// Installed locations of symlinks for backward compatibility.
compatSymlinks android.InstallPaths
- hostRequired []string
+ hostRequired []string
+ requiredModuleNames []string
}
type sanitizedPrebuilt interface {
@@ -195,9 +196,19 @@
}
p.apexFilesForAndroidMk = append(p.apexFilesForAndroidMk, af)
}
- } else if tag == exportedBootclasspathFragmentTag ||
- tag == exportedSystemserverclasspathFragmentTag {
- // Visit the children of the bootclasspath_fragment and systemserver_fragment.
+ } else if tag == exportedBootclasspathFragmentTag {
+ bcpfModule, ok := child.(*java.PrebuiltBootclasspathFragmentModule)
+ if !ok {
+ ctx.PropertyErrorf("exported_bootclasspath_fragments", "%q is not a prebuilt_bootclasspath_fragment module", name)
+ return false
+ }
+ for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
+ p.requiredModuleNames = append(p.requiredModuleNames, makeModuleName)
+ }
+ // Visit the children of the bootclasspath_fragment.
+ return true
+ } else if tag == exportedSystemserverclasspathFragmentTag {
+ // Visit the children of the systemserver_fragment.
return true
}
@@ -211,6 +222,7 @@
entries.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", fi.targetRequiredModuleNames...)
entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", fi.hostRequiredModuleNames...)
}
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...)
}
func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fee51d7..96b76f5 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -1071,7 +1071,7 @@
// At the moment this is basically just a bootclasspath_fragment module that can be used as a
// prebuilt. Eventually as more functionality is migrated into the bootclasspath_fragment module
// type from the various singletons then this will diverge.
-type prebuiltBootclasspathFragmentModule struct {
+type PrebuiltBootclasspathFragmentModule struct {
BootclasspathFragmentModule
prebuilt android.Prebuilt
@@ -1079,16 +1079,16 @@
prebuiltProperties prebuiltBootclasspathFragmentProperties
}
-func (module *prebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
+func (module *PrebuiltBootclasspathFragmentModule) Prebuilt() *android.Prebuilt {
return &module.prebuilt
}
-func (module *prebuiltBootclasspathFragmentModule) Name() string {
+func (module *PrebuiltBootclasspathFragmentModule) Name() string {
return module.prebuilt.Name(module.ModuleBase.Name())
}
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
if src == nil {
return defaultPath
@@ -1129,7 +1129,7 @@
}
// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
return nil
}
@@ -1139,37 +1139,53 @@
return nil // An error has been reported by FindDeapexerProviderForModule.
}
- files := bootImageFilesByArch{}
- for _, variant := range imageConfig.apexVariants() {
- arch := variant.target.Arch.ArchType
- for _, toPath := range variant.imagesDeps {
- apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
- // Get the path to the file that the deapexer extracted from the prebuilt apex file.
- fromPath := di.PrebuiltExportPath(apexRelativePath)
-
- // Return the toPath as the calling code expects the paths in the returned map to be the
- // paths predefined in the bootImageConfig.
- files[arch] = append(files[arch], toPath)
-
- // Copy the file to the predefined location.
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: fromPath,
- Output: toPath,
- })
- }
+ profile := (android.WritablePath)(nil)
+ if imageConfig.profileInstallPathInApex != "" {
+ profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex)
}
- // Build the boot image files for the host variants. These are built from the dex files provided
- // by the contents of this module as prebuilt versions of the host boot image files are not
- // available, i.e. there is no host specific prebuilt apex containing them. This has to be built
- // without a profile as the prebuilt modules do not provide a profile.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, nil)
+ // Build the boot image files for the host variants. These are always built from the dex files
+ // provided by the contents of this module as prebuilt versions of the host boot image files are
+ // not available, i.e. there is no host specific prebuilt apex containing them. This has to be
+ // built without a profile as the prebuilt modules do not provide a profile.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
- return files
+ if imageConfig.shouldInstallInApex() {
+ // If the boot image files for the android variants are in the prebuilt apex, we must use those
+ // rather than building new ones because those boot image files are going to be used on device.
+ files := bootImageFilesByArch{}
+ for _, variant := range imageConfig.apexVariants() {
+ arch := variant.target.Arch.ArchType
+ for _, toPath := range variant.imagesDeps {
+ apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
+ // Get the path to the file that the deapexer extracted from the prebuilt apex file.
+ fromPath := di.PrebuiltExportPath(apexRelativePath)
+
+ // Return the toPath as the calling code expects the paths in the returned map to be the
+ // paths predefined in the bootImageConfig.
+ files[arch] = append(files[arch], toPath)
+
+ // Copy the file to the predefined location.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: fromPath,
+ Output: toPath,
+ })
+ }
+ }
+ return files
+ } else {
+ if profile == nil {
+ ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex")
+ return nil
+ }
+ // Build boot image files for the android variants from the dex files provided by the contents
+ // of this module.
+ return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+ }
}
-var _ commonBootclasspathFragment = (*prebuiltBootclasspathFragmentModule)(nil)
+var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
// createBootImageTag creates the tag to uniquely identify the boot image file among all of the
// files that a module requires from the prebuilt .apex file.
@@ -1183,16 +1199,22 @@
//
// If there is no image config associated with this fragment then it returns nil. Otherwise, it
// returns the files that are listed in the image config.
-func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
+func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
imageConfig := module.getImageConfig(ctx)
if imageConfig != nil {
- // Add the boot image files, e.g. .art, .oat and .vdex files.
files := []string{}
- for _, variant := range imageConfig.apexVariants() {
- arch := variant.target.Arch.ArchType
- for _, path := range variant.imagesDeps.Paths() {
- base := path.Base()
- files = append(files, apexRootRelativePathToBootImageFile(arch, base))
+ if imageConfig.profileInstallPathInApex != "" {
+ // Add the boot image profile.
+ files = append(files, imageConfig.profileInstallPathInApex)
+ }
+ if imageConfig.shouldInstallInApex() {
+ // Add the boot image files, e.g. .art, .oat and .vdex files.
+ for _, variant := range imageConfig.apexVariants() {
+ arch := variant.target.Arch.ArchType
+ for _, path := range variant.imagesDeps.Paths() {
+ base := path.Base()
+ files = append(files, apexRootRelativePathToBootImageFile(arch, base))
+ }
}
}
return files
@@ -1204,10 +1226,10 @@
return filepath.Join("javalib", arch.String(), base)
}
-var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltBootclasspathFragmentModule)(nil)
+var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module {
- m := &prebuiltBootclasspathFragmentModule{}
+ m := &PrebuiltBootclasspathFragmentModule{}
m.AddProperties(&m.properties, &m.prebuiltProperties)
// This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs
// array.