Rework class loader context implementation.
The old representation consisted of a list of libraries (UsesLibraries),
a list of optional libraries (OptionalUsesLibraries) and a mapping from
library name to its build/install paths (LibraryPaths). The separation
into lists and map was necessary because of special handling of
compatibility libraries, which is now unified with normal libraries.
The new representation is a mapping from target SDK version to a tree
structure ClassLoaderContext. Each node of the tree represents a library
and contains library name, build/install paths and a slice of
subcontexts for dependencies. The same library may occur in the tree
multiple times in case it is a dependency of multiple libraries. The
order in which libraries are added matters (the resulting tree shape may
be different).
Test results have to be updated, as the resulting <uses-library> list is
reodered (previously it was a sorted list of map keys, and now it is
formed by a depth-first preorder traversal of the class loader tree).
Test: lunch aosp_cf_x86_phone-userdebug && m
Bug: 132357300
Bug: 168686456
Change-Id: I11be8cd2967f004fd58753d7c5fb99fed179cd63
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index a07f1fa..65380fe 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -81,16 +81,18 @@
}
if !dexpreoptDisabled(ctx, global, module) {
- if clc, err := genClassLoaderContext(ctx, global, module); err != nil {
+ if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil {
android.ReportPathErrorf(ctx, err.Error())
- } else if clc != nil {
+ } else if valid {
+ fixClassLoaderContext(module.ClassLoaderContexts)
+
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
!module.NoCreateAppImage
generateDM := shouldGenerateDM(module, global)
for archIdx, _ := range module.Archs {
- dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, *clc, profile, appImage, generateDM)
+ dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
}
}
}
@@ -197,8 +199,8 @@
}
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
- module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
- profile android.WritablePath, appImage bool, generateDM bool) {
+ module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
+ appImage bool, generateDM bool) {
arch := module.Archs[archIdx]
@@ -235,6 +237,16 @@
rule.Command().FlagWithOutput("rm -f ", odexPath)
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
+ // System server jars should be dexpreopted together: class loader context of each jar
+ // should include all preceding jars on the system server classpath.
+
+ var clcHost android.Paths
+ var clcTarget []string
+ for _, lib := range systemServerJars[:jarIndex] {
+ clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
+ clcTarget = append(clcTarget, filepath.Join("/system/framework", lib+".jar"))
+ }
+
// 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()))
@@ -242,11 +254,11 @@
checkSystemServerOrder(ctx, jarIndex)
- clc := classLoaderContexts[AnySdkVersion]
rule.Command().
- Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
- Implicits(clc.Host).
- Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
+ Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clcHost.Strings(), ":") + "]").
+ Implicits(clcHost).
+ Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
+
} else if module.EnforceUsesLibraries {
// Generate command that saves target SDK version in a shell variable.
if module.ManifestPath != nil {
@@ -266,13 +278,15 @@
}
// Generate command that saves host and target class loader context in shell variables.
- clc, paths := computeClassLoaderContext(ctx, classLoaderContexts)
+ clc, paths := ComputeClassLoaderContext(module.ClassLoaderContexts)
cmd := rule.Command().
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
Text(` --target-sdk-version ${target_sdk_version}`).
Text(clc).Implicits(paths)
cmd.Text(`)"`)
+
} else {
+ // Other libraries or APKs for which the exact <uses-library> list is unknown.
// 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