Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afb3e639 authored by Ulya Trafimovich's avatar Ulya Trafimovich Committed by Automerger Merge Worker
Browse files

Forbid generating boot image files for jars in updatable modules. am:...

Forbid generating boot image files for jars in updatable modules. am: cc21bba9 am: de2b535f am: a9e1fc42

Change-Id: I096ee643b60d1e67a2e124405afac2ba3569d07d
parents 0b264fe1 a9e1fc42
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ type Module interface {
	InstallInRoot() bool
	InstallBypassMake() bool
	SkipInstall()
	IsSkipInstall() bool
	ExportedToMake() bool
	InitRc() Paths
	VintfFragments() Paths
@@ -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,7 +1317,9 @@ 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) 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...)
@@ -1321,7 +1328,9 @@ func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) bluepri
	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) 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)
+170 −0
Original line number Diff line number Diff line
@@ -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()
+60 −8
Original line number Diff line number Diff line
@@ -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])
			}
		}
+1 −1
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ func TestDexpreoptBootJars(t *testing.T) {

	ctx := testContext()

	ctx.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
	RegisterDexpreoptBootJarsComponents(ctx)

	run(t, ctx, config)