diff --git a/apex/apex_test.go b/apex/apex_test.go index 956b8d9fd..08d82e90c 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -6519,6 +6519,15 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi min_sdk_version: "current", } + bootclasspath_fragment { + name: "art-bootclasspath-fragment", + image_name: "art", + contents: ["some-art-lib"], + apex_available: [ + "com.android.art.debug", + ], + } + apex_key { name: "com.android.art.debug.key", } @@ -6651,14 +6660,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { }) t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { - err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image` + err := `ArtApexJars expects this to be in apex "some-updatable-apex" but this is only in apexes.*"com.android.art.debug"` // Update the dexpreopt ArtApexJars directly. preparer := prepareSetArtJars("some-updatable-apex:some-updatable-apex-lib") testNoUpdatableJarsInBootImage(t, err, preparer) }) t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) { - err := `module "some-non-updatable-apex-lib" is not allowed in the ART boot image` + err := `ArtApexJars expects this to be in apex "some-non-updatable-apex" but this is only in apexes.*"com.android.art.debug"` // Update the dexpreopt ArtApexJars directly. preparer := prepareSetArtJars("some-non-updatable-apex:some-non-updatable-apex-lib") testNoUpdatableJarsInBootImage(t, err, preparer) @@ -6688,7 +6697,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { }) t.Run("platform jar in the ART boot image => error", func(t *testing.T) { - err := `module "some-platform-lib" is not allowed in the ART boot image` + err := `ArtApexJars is invalid as it requests a platform variant of "some-platform-lib"` // Update the dexpreopt ArtApexJars directly. preparer := prepareSetArtJars("platform:some-platform-lib") testNoUpdatableJarsInBootImage(t, err, preparer) diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index 3d39d341c..e2b320ca0 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -94,6 +94,8 @@ func TestBootclasspathFragments(t *testing.T) { bootclasspath_fragment { name: "art-bootclasspath-fragment", image_name: "art", + // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. + contents: ["baz", "quuz"], apex_available: [ "com.android.art", ], @@ -405,6 +407,8 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { prebuilt_bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", + // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. + contents: ["foo", "bar"], apex_available: [ "com.android.art", ], diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index d7525ecce..8fe362a56 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -145,11 +145,6 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`) } - if len(contents) != 0 { - // Nothing to do. - return - } - imageName := proptools.String(m.properties.Image_name) if imageName == "art" { // TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property. @@ -181,7 +176,7 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, continue } if !m.AvailableFor(apex) { - ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q", + ctx.ModuleErrorf("ArtApexJars configuration incompatible with this module, ArtApexJars expects this to be in apex %q but this is only in apexes %q", apex, m.ApexAvailable()) continue } @@ -193,6 +188,11 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, } } + if len(contents) != 0 { + // Nothing to do. + return + } + // Store the jars in the Contents property so that they can be used to add dependencies. m.properties.Contents = modules.CopyOfJars() } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 8c6c9e3bd..617bbc044 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -460,8 +460,7 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig // be needed there too. // // TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it. -func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList, - module android.Module, fromWhere string) (int, android.Path, *android.ApexInfo) { +func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList, module android.Module, fromWhere string) (int, android.Path) { name := ctx.ModuleName(module) @@ -471,7 +470,7 @@ func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList // Ignore any module that is not listed in the boot image configuration. index := bootjars.IndexOfJar(name) if index == -1 { - return -1, nil, nil + return -1, nil } // It is an error if a module configured in the boot image does not support accessing the dex jar. @@ -479,13 +478,13 @@ func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList jar, hasJar := module.(interface{ DexJarBuildPath() android.Path }) if !hasJar { ctx.Errorf("module %q %sdoes not support accessing dex jar", module, fromWhere) - return -1, nil, nil + return -1, nil } // It is also an error if the module is not an ApexModule. if _, ok := module.(android.ApexModule); !ok { ctx.Errorf("module %q %sdoes not support being added to an apex", module, fromWhere) - return -1, nil, nil + return -1, nil } apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) @@ -495,62 +494,24 @@ func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList if requiredApex == "platform" || requiredApex == "system_ext" { if len(apexInfo.InApexes) != 0 { // A platform variant is required but this is for an apex so ignore it. - return -1, nil, nil + return -1, nil } } else if !apexInfo.InApexByBaseName(requiredApex) { // An apex variant for a specific apex is required but this is the wrong apex. - return -1, nil, nil + return -1, nil } - return index, jar.DexJarBuildPath(), &apexInfo + return index, jar.DexJarBuildPath() } // Inspect this module to see if it contains a bootclasspath dex jar from a given boot image. func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) { fromImage := fmt.Sprintf("configured in boot image %q ", image.name) - index, jarPath, apexInfo := getBootJar(ctx, image.modules, module, fromImage) + index, jarPath := getBootJar(ctx, image.modules, module, fromImage) if index == -1 { return -1, nil } - name := ctx.ModuleName(module) - - // Check that this module satisfies any boot image specific constraints. - fromUpdatableApex := apexInfo.Updatable - - switch image.name { - case artBootImageName: - inArtApex := false - for _, n := range artApexNames { - if apexInfo.InApexByBaseName(n) { - inArtApex = true - break - } - } - if inArtApex { - // ok: found the jar in the ART apex - } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { - // exception (skip and continue): Jacoco platform variant for a coverage build - return -1, nil - } else if fromUpdatableApex { - // error: this jar is part of an updatable apex other than ART - ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apexInfo.InApexes) - } else { - // error: this jar is part of the platform or a non-updatable apex - ctx.Errorf("module %q is not allowed in the ART boot image", name) - } - - case frameworkBootImageName: - if !fromUpdatableApex { - // ok: this jar is part of the platform or a non-updatable apex - } else { - // error: this jar is part of an updatable apex - ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apexInfo.InApexes) - } - default: - panic("unknown boot image: " + image.name) - } - return index, jarPath } @@ -645,7 +606,7 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig, profil func copyUpdatableBootJars(ctx android.SingletonContext) { config := GetUpdatableBootConfig(ctx) getBootJarFunc := func(module android.Module) (int, android.Path) { - index, jar, _ := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ") + index, jar := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ") return index, jar } findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 9f1629428..f88823fd0 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -184,6 +184,11 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo // Gather all the fragments dependencies. b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) + // Check the configuration of the boot modules. + // ART modules are checked by the art-bootclasspath-fragment. + b.checkNonUpdatableModules(ctx, nonUpdatableModules) + b.checkUpdatableModules(ctx, updatableModules) + b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments) // Nothing to do if skipping the dexpreopt of boot image jars. @@ -194,6 +199,42 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo b.generateBootImageBuildActions(ctx, updatableModules) } +// checkNonUpdatableModules ensures that the non-updatable modules supplied are not part of an +// updatable module. +func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.ModuleContext, modules []android.Module) { + for _, m := range modules { + apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo) + fromUpdatableApex := apexInfo.Updatable + if fromUpdatableApex { + // error: this jar is part of an updatable apex + ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the framework boot image", ctx.OtherModuleName(m), apexInfo.InApexes) + } else { + // ok: this jar is part of the platform or a non-updatable apex + } + } +} + +// checkUpdatableModules ensures that the updatable modules supplied are not from the platform. +func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleContext, modules []android.Module) { + for _, m := range modules { + apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo) + fromUpdatableApex := apexInfo.Updatable + if fromUpdatableApex { + // ok: this jar is part of an updatable apex + } else { + name := ctx.OtherModuleName(m) + if apexInfo.IsForPlatform() { + // error: this jar is part of the platform + ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name) + } else { + // TODO(b/177892522): Treat this as an error. + // Cannot do that at the moment because framework-wifi and framework-tethering are in the + // PRODUCT_UPDATABLE_BOOT_JARS but not marked as updatable in AOSP. + } + } + } +} + func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig { return defaultBootImageConfig(ctx) } diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index 28275672b..0f2fd5436 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -68,6 +68,7 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", + contents: ["mybootlib"], apex_available: ["com.android.art"], }