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

Commit 54c481ed authored by Ulyana Trafimovich's avatar Ulyana Trafimovich Committed by Gerrit Code Review
Browse files

Merge "Simplify the construction of class loader contexts for system server jars."

parents 7b5f1a61 dacc6c56
Loading
Loading
Loading
Loading
+32 −49
Original line number Diff line number Diff line
@@ -41,21 +41,12 @@ import (

	"android/soong/android"

	"github.com/google/blueprint"
	"github.com/google/blueprint/pathtools"
)

const SystemPartition = "/system/"
const SystemOtherPartition = "/system_other/"

type dependencyTag struct {
	blueprint.BaseDependencyTag
	name string
}

var SystemServerDepTag = dependencyTag{name: "system-server-dep"}
var SystemServerForcedDepTag = dependencyTag{name: "system-server-forced-dep"}

// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig.  The produced files and their install locations will be available through rule.Installs().
func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig,
@@ -116,13 +107,6 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo
		}
	}

	// Don't preopt system server jars that are not Soong modules.
	if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) {
		if _, ok := ctx.(android.ModuleContext); !ok {
			return true
		}
	}

	// If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
	// Also preopt system server jars since selinux prevents system server from loading anything from
	// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
@@ -239,6 +223,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g

	invocationPath := odexPath.ReplaceExtension(ctx, "invocation")

	systemServerJars := NonUpdatableSystemServerJars(ctx, global)

	// The class loader context using paths in the build
	var classLoaderContextHost android.Paths

@@ -253,8 +239,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
	var conditionalClassLoaderContextHost29 android.Paths
	var conditionalClassLoaderContextTarget29 []string

	var classLoaderContextHostString, classLoaderContextDeviceString string
	var classLoaderDeps android.Paths
	// A flag indicating if the '&' class loader context is used.
	unknownClassLoaderContext := false

	if module.EnforceUsesLibraries {
		usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
@@ -298,49 +284,38 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
			pathForLibrary(module, hidlBase))
		conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
			filepath.Join("/system/framework", hidlBase+".jar"))

		classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":")
	} else if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) {
		// We expect that all dexpreopted system server jars are Soong modules.
		mctx, isModule := ctx.(android.ModuleContext)
		if !isModule {
			panic("Cannot dexpreopt system server jar that is not a soong module.")
		}

	} else if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
		// System server jars should be dexpreopted together: class loader context of each jar
		// should include preceding jars (which can be found as dependencies of the current jar
		// with a special tag).
		var jarsOnHost android.Paths
		var jarsOnDevice []string
		mctx.VisitDirectDepsWithTag(SystemServerDepTag, func(dep android.Module) {
			depName := mctx.OtherModuleName(dep)
			if jar, ok := dep.(interface{ DexJar() android.Path }); ok {
				jarsOnHost = append(jarsOnHost, jar.DexJar())
				jarsOnDevice = append(jarsOnDevice, "/system/framework/"+depName+".jar")
			} else {
				mctx.ModuleErrorf("module \"%s\" is not a jar", depName)
		// should include all preceding jars on the system server classpath.
		for _, otherJar := range systemServerJars[:jarIndex] {
			classLoaderContextHost = append(classLoaderContextHost, SystemServerDexJarHostPath(ctx, otherJar))
			classLoaderContextTarget = append(classLoaderContextTarget, "/system/framework/"+otherJar+".jar")
		}
		})
		classLoaderContextHostString = strings.Join(jarsOnHost.Strings(), ":")
		classLoaderContextDeviceString = strings.Join(jarsOnDevice, ":")
		classLoaderDeps = jarsOnHost

		// Copy the system server jar to a predefined location where dex2oat will find it.
		dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
		rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
		rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost)
	} else {
		// Pass special class loader context to skip the classpath and collision check.
		// This will get removed once LOCAL_USES_LIBRARIES is enforced.
		// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
		// to the &.
		classLoaderContextHostString = `\&`
		unknownClassLoaderContext = true
	}

	rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
	rule.Command().FlagWithOutput("rm -f ", odexPath)
	// Set values in the environment of the rule.  These may be modified by construct_context.sh.
	if classLoaderContextHostString == `\&` {
		rule.Command().Text(`class_loader_context_arg=--class-loader-context=\&`)
		rule.Command().Text(`stored_class_loader_context_arg=""`)
	if unknownClassLoaderContext {
		rule.Command().
			Text(`class_loader_context_arg=--class-loader-context=\&`).
			Text(`stored_class_loader_context_arg=""`)
	} else {
		rule.Command().Text("class_loader_context_arg=--class-loader-context=PCL[" + classLoaderContextHostString + "]")
		rule.Command().Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + classLoaderContextDeviceString + "]")
		rule.Command().
			Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(classLoaderContextHost.Strings(), ":") + "]").
			Implicits(classLoaderContextHost).
			Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(classLoaderContextTarget, ":") + "]")
	}

	if module.EnforceUsesLibraries {
@@ -395,7 +370,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
		Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":").
		Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
		Flag("${class_loader_context_arg}").
		Flag("${stored_class_loader_context_arg}").Implicits(classLoaderDeps).
		Flag("${stored_class_loader_context_arg}").
		FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
		FlagWithInput("--dex-file=", module.DexPath).
		FlagWithArg("--dex-location=", dexLocationArg).
@@ -609,6 +584,14 @@ func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig)
	}).([]string)
}

// A predefined location for the system server dex jars. This is needed in order to generate
// class loader context for dex2oat, as the path to the jar in the Soong module may be unknown
// at that time (Soong processes the jars in dependency order, which may be different from the
// the system server classpath order).
func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath {
	return android.PathForOutput(ctx, ctx.Config().DeviceName(), "system_server_dexjars", jar+".jar")
}

func contains(l []string, s string) bool {
	for _, e := range l {
		if e == s {
+3 −10
Original line number Diff line number Diff line
@@ -30,9 +30,9 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string {
	return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
		global := dexpreopt.GetGlobalConfig(ctx)
		var systemServerClasspathLocations []string
		var dexpreoptJars = *DexpreoptedSystemServerJars(ctx.Config())
		// 1) The jars that are dexpreopted.
		for _, m := range dexpreoptJars {
		nonUpdatable := dexpreopt.NonUpdatableSystemServerJars(ctx, global)
		// 1) Non-updatable jars.
		for _, m := range nonUpdatable {
			systemServerClasspathLocations = append(systemServerClasspathLocations,
				filepath.Join("/system/framework", m+".jar"))
		}
@@ -41,13 +41,6 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string {
			systemServerClasspathLocations = append(systemServerClasspathLocations,
				dexpreopt.GetJarLocationFromApexJarPair(m))
		}
		// 3) The jars from make (which are not updatable, not preopted).
		for _, m := range dexpreopt.NonUpdatableSystemServerJars(ctx, global) {
			if !android.InList(m, dexpreoptJars) {
				systemServerClasspathLocations = append(systemServerClasspathLocations,
					filepath.Join("/system/framework", m+".jar"))
			}
		}
		if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) {
			panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d",
				len(systemServerClasspathLocations),
+0 −47
Original line number Diff line number Diff line
@@ -23,14 +23,12 @@ import (
	"path/filepath"
	"strconv"
	"strings"
	"sync"

	"github.com/google/blueprint"
	"github.com/google/blueprint/pathtools"
	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/dexpreopt"
	"android/soong/java/config"
	"android/soong/tradefed"
)
@@ -60,8 +58,6 @@ func init() {
			PropertyName: "java_tests",
		},
	})

	android.PostDepsMutators(RegisterPostDepsMutators)
}

func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
@@ -90,44 +86,6 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}

func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.BottomUp("ordered_system_server_jars", systemServerJarsDepsMutator)
}

var (
	dexpreoptedSystemServerJarsKey  = android.NewOnceKey("dexpreoptedSystemServerJars")
	dexpreoptedSystemServerJarsLock sync.Mutex
)

func DexpreoptedSystemServerJars(config android.Config) *[]string {
	return config.Once(dexpreoptedSystemServerJarsKey, func() interface{} {
		return &[]string{}
	}).(*[]string)
}

// A PostDepsMutator pass that enforces total order on non-updatable system server jars. A total
// order is neededed because such jars must be dexpreopted together (each jar on the list must have
// all preceding jars in its class loader context). The total order must be compatible with the
// partial order imposed by genuine dependencies between system server jars (which is not always
// respected by the PRODUCT_SYSTEM_SERVER_JARS variable).
//
// An earlier mutator pass creates genuine dependencies, and this pass traverses the jars in that
// order (which is partial and non-deterministic). This pass adds additional dependencies between
// jars, making the order total and deterministic. It also constructs a global ordered list.
func systemServerJarsDepsMutator(ctx android.BottomUpMutatorContext) {
	jars := dexpreopt.NonUpdatableSystemServerJars(ctx, dexpreopt.GetGlobalConfig(ctx))
	name := ctx.ModuleName()
	if android.InList(name, jars) {
		dexpreoptedSystemServerJarsLock.Lock()
		defer dexpreoptedSystemServerJarsLock.Unlock()
		jars := DexpreoptedSystemServerJars(ctx.Config())
		for _, dep := range *jars {
			ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerDepTag, dep)
		}
		*jars = append(*jars, name)
	}
}

func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
	if j.SocSpecific() || j.DeviceSpecific() ||
		(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
@@ -711,11 +669,6 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
	} else if j.shouldInstrumentStatic(ctx) {
		ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
	}

	// services depend on com.android.location.provider, but dependency in not registered in a Blueprint file
	if ctx.ModuleName() == "services" {
		ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerForcedDepTag, "com.android.location.provider")
	}
}

func hasSrcExt(srcs []string, ext string) bool {