Forbid generating boot image files for jars in updatable modules.
This is to guard against the potential situation when someone adds
updatable modules to the list of boot jars by mistake.
Test: aosp_walleye-userdebug builds.
Test: Manually break the checks and observe the errors:
- move updatable module 'conscrypt' from
PRODUCT_UPDATABLE_BOOT_JARS to ART_APEX_JARS:
internal error: module 'conscrypt' from updatable apex 'com.android.conscrypt' is not allowed in the ART boot image
- add updatable module 'conscrypt' to ART_APEX_JARS
(but do not remove it from PRODUCT_UPDATABLE_BOOT_JARS):
error: A jar in PRODUCT_UPDATABLE_BOOT_JARS must not be in PRODUCT_BOOT_JARS, but conscrypt is.
- move updatable module 'framework-tethering' from
PRODUCT_UPDATABLE_BOOT_JARS to PRODUCT_BOOT_JARS:
internal error: module 'framework-tethering' from updatable apex 'com.android.tethering' is not allowed in the framework boot image
- add non-updatable (in AOSP) module 'android.net.ipsec.ike'
to PRODUCT_BOOT_JARS:
internal error: failed to find a dex jar path for module 'com.android.ipsec.ike', note that some jars may be filtered out by module constraints
Bug: 147579140
Exempt-From-Owner-Approval: cherry-pick, approved in AOSP.
Change-Id: I25ca2f52530fcfa1f9823b2cfa3485db9c0d0db1
Merged-In: I25ca2f52530fcfa1f9823b2cfa3485db9c0d0db1
(cherry picked from commit b28cc3758c
)
This commit is contained in:
parent
aeb9e6ffe8
commit
cc21bba967
|
@ -215,6 +215,7 @@ type Module interface {
|
|||
InstallInRoot() bool
|
||||
InstallBypassMake() bool
|
||||
SkipInstall()
|
||||
IsSkipInstall() bool
|
||||
ExportedToMake() bool
|
||||
InitRc() Paths
|
||||
VintfFragments() Paths
|
||||
|
@ -844,7 +845,7 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
|
|||
// partition at "system/vendor/odm".
|
||||
if config.OdmPath() == "odm" {
|
||||
partition = "odm"
|
||||
} else if strings.HasPrefix(config.OdmPath (), "vendor/") {
|
||||
} else if strings.HasPrefix(config.OdmPath(), "vendor/") {
|
||||
partition = "vendor"
|
||||
}
|
||||
} else if m.ProductSpecific() {
|
||||
|
@ -879,6 +880,10 @@ func (m *ModuleBase) SkipInstall() {
|
|||
m.commonProperties.SkipInstall = true
|
||||
}
|
||||
|
||||
func (m *ModuleBase) IsSkipInstall() bool {
|
||||
return m.commonProperties.SkipInstall == true
|
||||
}
|
||||
|
||||
func (m *ModuleBase) ExportedToMake() bool {
|
||||
return m.commonProperties.NamespaceExportedToMake
|
||||
}
|
||||
|
@ -1312,16 +1317,20 @@ type baseModuleContext struct {
|
|||
strictVisitDeps bool // If true, enforce that all dependencies are enabled
|
||||
}
|
||||
|
||||
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string { return b.bp.OtherModuleName(m) }
|
||||
func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
|
||||
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
|
||||
return b.bp.OtherModuleName(m)
|
||||
}
|
||||
func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
|
||||
func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
|
||||
b.bp.OtherModuleErrorf(m, fmt, args...)
|
||||
}
|
||||
func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
|
||||
return b.bp.OtherModuleDependencyTag(m)
|
||||
}
|
||||
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
|
||||
func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) }
|
||||
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
|
||||
func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
|
||||
return b.bp.OtherModuleType(m)
|
||||
}
|
||||
|
||||
func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
|
||||
return b.bp.GetDirectDepWithTag(name, tag)
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/dexpreopt"
|
||||
"android/soong/java"
|
||||
)
|
||||
|
||||
|
@ -4089,6 +4090,175 @@ func TestAppBundle(t *testing.T) {
|
|||
ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
|
||||
}
|
||||
|
||||
func testNoUpdatableJarsInBootImage(t *testing.T, errmsg, bp string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
|
||||
t.Helper()
|
||||
|
||||
bp = bp + `
|
||||
filegroup {
|
||||
name: "some-updatable-apex-file_contexts",
|
||||
srcs: [
|
||||
"system/sepolicy/apex/some-updatable-apex-file_contexts",
|
||||
],
|
||||
}
|
||||
`
|
||||
bp += cc.GatherRequiredDepsForTest(android.Android)
|
||||
bp += java.GatherRequiredDepsForTest()
|
||||
bp += dexpreopt.BpToolModulesForTest()
|
||||
|
||||
fs := map[string][]byte{
|
||||
"a.java": nil,
|
||||
"a.jar": nil,
|
||||
"build/make/target/product/security": nil,
|
||||
"apex_manifest.json": nil,
|
||||
"AndroidManifest.xml": nil,
|
||||
"system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
|
||||
"system/sepolicy/apex/com.android.art.something-file_contexts": nil,
|
||||
"framework/aidl/a.aidl": nil,
|
||||
}
|
||||
cc.GatherRequiredFilesForTest(fs)
|
||||
|
||||
ctx := android.NewTestArchContext()
|
||||
ctx.RegisterModuleType("apex", BundleFactory)
|
||||
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
|
||||
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
|
||||
cc.RegisterRequiredBuildComponentsForTest(ctx)
|
||||
java.RegisterJavaBuildComponents(ctx)
|
||||
java.RegisterSystemModulesBuildComponents(ctx)
|
||||
java.RegisterAppBuildComponents(ctx)
|
||||
java.RegisterDexpreoptBootJarsComponents(ctx)
|
||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
|
||||
ctx.PreDepsMutators(RegisterPreDepsMutators)
|
||||
ctx.PostDepsMutators(RegisterPostDepsMutators)
|
||||
|
||||
config := android.TestArchConfig(buildDir, nil, bp, fs)
|
||||
ctx.Register(config)
|
||||
|
||||
_ = dexpreopt.GlobalSoongConfigForTests(config)
|
||||
dexpreopt.RegisterToolModulesForTest(ctx)
|
||||
pathCtx := android.PathContextForTesting(config)
|
||||
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
|
||||
transformDexpreoptConfig(dexpreoptConfig)
|
||||
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
|
||||
|
||||
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
|
||||
android.FailIfErrored(t, errs)
|
||||
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
if errmsg == "" {
|
||||
android.FailIfErrored(t, errs)
|
||||
} else if len(errs) > 0 {
|
||||
android.FailIfNoMatchingErrors(t, errmsg, errs)
|
||||
return
|
||||
} else {
|
||||
t.Fatalf("missing expected error %q (0 errors are returned)", errmsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoUpdatableJarsInBootImage(t *testing.T) {
|
||||
bp := `
|
||||
java_library {
|
||||
name: "some-updatable-apex-lib",
|
||||
srcs: ["a.java"],
|
||||
apex_available: [
|
||||
"some-updatable-apex",
|
||||
],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "some-platform-lib",
|
||||
srcs: ["a.java"],
|
||||
installable: true,
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "some-art-lib",
|
||||
srcs: ["a.java"],
|
||||
apex_available: [
|
||||
"com.android.art.something",
|
||||
],
|
||||
hostdex: true,
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "some-updatable-apex",
|
||||
key: "some-updatable-apex.key",
|
||||
java_libs: ["some-updatable-apex-lib"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "some-updatable-apex.key",
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "com.android.art.something",
|
||||
key: "com.android.art.something.key",
|
||||
java_libs: ["some-art-lib"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "com.android.art.something.key",
|
||||
}
|
||||
`
|
||||
|
||||
var error string
|
||||
var transform func(*dexpreopt.GlobalConfig)
|
||||
|
||||
// updatable jar from ART apex in the ART boot image => ok
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.ArtApexJars = []string{"some-art-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, "", bp, transform)
|
||||
|
||||
// updatable jar from ART apex in the framework boot image => error
|
||||
error = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.BootJars = []string{"some-art-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// updatable jar from some other apex in the ART boot image => error
|
||||
error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.ArtApexJars = []string{"some-updatable-apex-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// updatable jar from some other apex in the framework boot image => error
|
||||
error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.BootJars = []string{"some-updatable-apex-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// nonexistent jar in the ART boot image => error
|
||||
error = "failed to find a dex jar path for module 'nonexistent'"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.ArtApexJars = []string{"nonexistent"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// nonexistent jar in the framework boot image => error
|
||||
error = "failed to find a dex jar path for module 'nonexistent'"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.BootJars = []string{"nonexistent"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// platform jar in the ART boot image => error
|
||||
error = "module 'some-platform-lib' is part of the platform and not allowed in the ART boot image"
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.ArtApexJars = []string{"some-platform-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, error, bp, transform)
|
||||
|
||||
// platform jar in the framework boot image => ok
|
||||
transform = func(config *dexpreopt.GlobalConfig) {
|
||||
config.BootJars = []string{"some-platform-lib"}
|
||||
}
|
||||
testNoUpdatableJarsInBootImage(t, "", bp, transform)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
run := func() int {
|
||||
setUp()
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
||||
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
|
||||
}
|
||||
|
||||
// The image "location" is a symbolic path that with multiarchitecture
|
||||
|
@ -168,6 +168,10 @@ func dexpreoptBootJarsFactory() android.Singleton {
|
|||
return &dexpreoptBootJars{}
|
||||
}
|
||||
|
||||
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
|
||||
ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
||||
}
|
||||
|
||||
func skipDexpreoptBootJars(ctx android.PathContext) bool {
|
||||
if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
|
||||
return true
|
||||
|
@ -238,16 +242,63 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
dumpOatRules(ctx, d.defaultBootImage)
|
||||
}
|
||||
|
||||
// Inspect this module to see if it contains a bootclasspath dex jar.
|
||||
// Note that the same jar may occur in multiple modules.
|
||||
// This logic is tested in the apex package to avoid import cycle apex <-> java.
|
||||
func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
|
||||
// All apex Java libraries have non-installable platform variants, skip them.
|
||||
if module.IsSkipInstall() {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
jar, hasJar := module.(interface{ DexJar() android.Path })
|
||||
if !hasJar {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
name := ctx.ModuleName(module)
|
||||
index := android.IndexList(name, image.modules)
|
||||
if index == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// Check that this module satisfies constraints for a particular boot image.
|
||||
apex, isApexModule := module.(android.ApexModule)
|
||||
if image.name == artBootImageName {
|
||||
if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
|
||||
// ok, found the jar in the ART apex
|
||||
} else if isApexModule && !apex.IsForPlatform() {
|
||||
// this jar is part of an updatable apex other than ART, fail immediately
|
||||
ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
|
||||
} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
|
||||
// this is a special "hostdex" variant, skip it and resume search
|
||||
return -1, nil
|
||||
} else {
|
||||
// this (installable) jar is part of the platform, fail immediately
|
||||
ctx.Errorf("module '%s' is part of the platform and not allowed in the ART boot image", name)
|
||||
}
|
||||
} else if image.name == frameworkBootImageName {
|
||||
if !isApexModule || apex.IsForPlatform() {
|
||||
// ok, this jar is part of the platform
|
||||
} else {
|
||||
// this jar is part of an updatable apex, fail immediately
|
||||
ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
|
||||
}
|
||||
} else {
|
||||
panic("unknown boot image: " + image.name)
|
||||
}
|
||||
|
||||
return index, jar.DexJar()
|
||||
}
|
||||
|
||||
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
|
||||
func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
|
||||
// Collect dex jar paths for the boot image modules.
|
||||
// This logic is tested in the apex package to avoid import cycle apex <-> java.
|
||||
bootDexJars := make(android.Paths, len(image.modules))
|
||||
ctx.VisitAllModules(func(module android.Module) {
|
||||
// Collect dex jar paths for the modules listed above.
|
||||
if j, ok := module.(interface{ DexJar() android.Path }); ok {
|
||||
name := ctx.ModuleName(module)
|
||||
if i := android.IndexList(name, image.modules); i != -1 {
|
||||
bootDexJars[i] = j.DexJar()
|
||||
}
|
||||
if i, j := getBootImageJar(ctx, image, module); i != -1 {
|
||||
bootDexJars[i] = j
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -259,7 +310,8 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
|
|||
missingDeps = append(missingDeps, image.modules[i])
|
||||
bootDexJars[i] = android.PathForOutput(ctx, "missing")
|
||||
} else {
|
||||
ctx.Errorf("failed to find dex jar path for module %q",
|
||||
ctx.Errorf("failed to find a dex jar path for module '%s'"+
|
||||
", note that some jars may be filtered out by module constraints",
|
||||
image.modules[i])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ func TestDexpreoptBootJars(t *testing.T) {
|
|||
|
||||
ctx := testContext()
|
||||
|
||||
ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
||||
RegisterDexpreoptBootJarsComponents(ctx)
|
||||
|
||||
run(t, ctx, config)
|
||||
|
||||
|
|
Loading…
Reference in New Issue