Merge "Forbid generating boot image files for jars in updatable modules."
This commit is contained in:
commit
0d8f61640e
4 changed files with 236 additions and 9 deletions
|
@ -227,6 +227,7 @@ type Module interface {
|
||||||
InstallBypassMake() bool
|
InstallBypassMake() bool
|
||||||
InstallForceOS() *OsType
|
InstallForceOS() *OsType
|
||||||
SkipInstall()
|
SkipInstall()
|
||||||
|
IsSkipInstall() bool
|
||||||
ExportedToMake() bool
|
ExportedToMake() bool
|
||||||
InitRc() Paths
|
InitRc() Paths
|
||||||
VintfFragments() Paths
|
VintfFragments() Paths
|
||||||
|
@ -950,6 +951,10 @@ func (m *ModuleBase) SkipInstall() {
|
||||||
m.commonProperties.SkipInstall = true
|
m.commonProperties.SkipInstall = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ModuleBase) IsSkipInstall() bool {
|
||||||
|
return m.commonProperties.SkipInstall == true
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ModuleBase) ExportedToMake() bool {
|
func (m *ModuleBase) ExportedToMake() bool {
|
||||||
return m.commonProperties.NamespaceExportedToMake
|
return m.commonProperties.NamespaceExportedToMake
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
|
"android/soong/dexpreopt"
|
||||||
"android/soong/java"
|
"android/soong/java"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4198,6 +4199,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"}]}`)
|
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) {
|
func TestMain(m *testing.M) {
|
||||||
run := func() int {
|
run := func() int {
|
||||||
setUp()
|
setUp()
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target-independent description of pre-compiled boot image.
|
// Target-independent description of pre-compiled boot image.
|
||||||
|
@ -174,6 +174,10 @@ func dexpreoptBootJarsFactory() android.Singleton {
|
||||||
return &dexpreoptBootJars{}
|
return &dexpreoptBootJars{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
|
||||||
|
ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
||||||
|
}
|
||||||
|
|
||||||
func skipDexpreoptBootJars(ctx android.PathContext) bool {
|
func skipDexpreoptBootJars(ctx android.PathContext) bool {
|
||||||
if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
|
if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
|
||||||
return true
|
return true
|
||||||
|
@ -242,16 +246,63 @@ func (d *dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
|
||||||
dumpOatRules(ctx, d.defaultBootImage)
|
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.
|
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
|
||||||
func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
|
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))
|
bootDexJars := make(android.Paths, len(image.modules))
|
||||||
ctx.VisitAllModules(func(module android.Module) {
|
ctx.VisitAllModules(func(module android.Module) {
|
||||||
// Collect dex jar paths for the modules listed above.
|
if i, j := getBootImageJar(ctx, image, module); i != -1 {
|
||||||
if j, ok := module.(interface{ DexJar() android.Path }); ok {
|
bootDexJars[i] = j
|
||||||
name := ctx.ModuleName(module)
|
|
||||||
if i := android.IndexList(name, image.modules); i != -1 {
|
|
||||||
bootDexJars[i] = j.DexJar()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -263,7 +314,8 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
|
||||||
missingDeps = append(missingDeps, image.modules[i])
|
missingDeps = append(missingDeps, image.modules[i])
|
||||||
bootDexJars[i] = android.PathForOutput(ctx, "missing")
|
bootDexJars[i] = android.PathForOutput(ctx, "missing")
|
||||||
} else {
|
} 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])
|
image.modules[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ func TestDexpreoptBootJars(t *testing.T) {
|
||||||
|
|
||||||
ctx := testContext()
|
ctx := testContext()
|
||||||
|
|
||||||
ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
|
RegisterDexpreoptBootJarsComponents(ctx)
|
||||||
|
|
||||||
run(t, ctx, config)
|
run(t, ctx, config)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue