Merge "Simplify the construction of class loader contexts for system server jars."
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 6cb9873..7dd01e2 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -41,21 +41,12 @@
"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 @@
}
}
- // 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 @@
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 @@
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 @@
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 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")
}
- // 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)
- }
- })
- 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 @@
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 @@
}).([]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 {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index d77d3e1..ffce2a9 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -30,9 +30,9 @@
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 @@
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),
diff --git a/java/java.go b/java/java.go
index 59a1e05..22d14ec 100644
--- a/java/java.go
+++ b/java/java.go
@@ -23,14 +23,12 @@
"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 @@
PropertyName: "java_tests",
},
})
-
- android.PostDepsMutators(RegisterPostDepsMutators)
}
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
@@ -90,44 +86,6 @@
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 @@
} 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 {