Merge "Simplify the construction of class loader contexts for system server jars."
This commit is contained in:
@@ -41,21 +41,12 @@ import (
|
|||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
|
||||||
"github.com/google/blueprint/pathtools"
|
"github.com/google/blueprint/pathtools"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SystemPartition = "/system/"
|
const SystemPartition = "/system/"
|
||||||
const SystemOtherPartition = "/system_other/"
|
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
|
// 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().
|
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
|
||||||
func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig,
|
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
|
// 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
|
// 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
|
// /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")
|
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
|
||||||
|
|
||||||
|
systemServerJars := NonUpdatableSystemServerJars(ctx, global)
|
||||||
|
|
||||||
// The class loader context using paths in the build
|
// The class loader context using paths in the build
|
||||||
var classLoaderContextHost android.Paths
|
var classLoaderContextHost android.Paths
|
||||||
|
|
||||||
@@ -253,8 +239,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||||||
var conditionalClassLoaderContextHost29 android.Paths
|
var conditionalClassLoaderContextHost29 android.Paths
|
||||||
var conditionalClassLoaderContextTarget29 []string
|
var conditionalClassLoaderContextTarget29 []string
|
||||||
|
|
||||||
var classLoaderContextHostString, classLoaderContextDeviceString string
|
// A flag indicating if the '&' class loader context is used.
|
||||||
var classLoaderDeps android.Paths
|
unknownClassLoaderContext := false
|
||||||
|
|
||||||
if module.EnforceUsesLibraries {
|
if module.EnforceUsesLibraries {
|
||||||
usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
|
usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
|
||||||
@@ -298,49 +284,38 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||||||
pathForLibrary(module, hidlBase))
|
pathForLibrary(module, hidlBase))
|
||||||
conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
|
conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
|
||||||
filepath.Join("/system/framework", hidlBase+".jar"))
|
filepath.Join("/system/framework", hidlBase+".jar"))
|
||||||
|
} else if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
||||||
classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":")
|
// System server jars should be dexpreopted together: class loader context of each jar
|
||||||
} else if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) {
|
// should include all preceding jars on the system server classpath.
|
||||||
// We expect that all dexpreopted system server jars are Soong modules.
|
for _, otherJar := range systemServerJars[:jarIndex] {
|
||||||
mctx, isModule := ctx.(android.ModuleContext)
|
classLoaderContextHost = append(classLoaderContextHost, SystemServerDexJarHostPath(ctx, otherJar))
|
||||||
if !isModule {
|
classLoaderContextTarget = append(classLoaderContextTarget, "/system/framework/"+otherJar+".jar")
|
||||||
panic("Cannot dexpreopt system server jar that is not a soong module.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// System server jars should be dexpreopted together: class loader context of each jar
|
// Copy the system server jar to a predefined location where dex2oat will find it.
|
||||||
// should include preceding jars (which can be found as dependencies of the current jar
|
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
|
||||||
// with a special tag).
|
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
|
||||||
var jarsOnHost android.Paths
|
rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost)
|
||||||
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
|
|
||||||
} else {
|
} else {
|
||||||
// Pass special class loader context to skip the classpath and collision check.
|
// Pass special class loader context to skip the classpath and collision check.
|
||||||
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
|
// 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
|
// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
|
||||||
// to the &.
|
// to the &.
|
||||||
classLoaderContextHostString = `\&`
|
unknownClassLoaderContext = true
|
||||||
}
|
}
|
||||||
|
|
||||||
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
|
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
|
||||||
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
||||||
// Set values in the environment of the rule. These may be modified by construct_context.sh.
|
// Set values in the environment of the rule. These may be modified by construct_context.sh.
|
||||||
if classLoaderContextHostString == `\&` {
|
if unknownClassLoaderContext {
|
||||||
rule.Command().Text(`class_loader_context_arg=--class-loader-context=\&`)
|
rule.Command().
|
||||||
rule.Command().Text(`stored_class_loader_context_arg=""`)
|
Text(`class_loader_context_arg=--class-loader-context=\&`).
|
||||||
|
Text(`stored_class_loader_context_arg=""`)
|
||||||
} else {
|
} else {
|
||||||
rule.Command().Text("class_loader_context_arg=--class-loader-context=PCL[" + classLoaderContextHostString + "]")
|
rule.Command().
|
||||||
rule.Command().Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + classLoaderContextDeviceString + "]")
|
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 {
|
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").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":").
|
||||||
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
|
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
|
||||||
Flag("${class_loader_context_arg}").
|
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()).
|
FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()).
|
||||||
FlagWithInput("--dex-file=", module.DexPath).
|
FlagWithInput("--dex-file=", module.DexPath).
|
||||||
FlagWithArg("--dex-location=", dexLocationArg).
|
FlagWithArg("--dex-location=", dexLocationArg).
|
||||||
@@ -609,6 +584,14 @@ func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig)
|
|||||||
}).([]string)
|
}).([]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 {
|
func contains(l []string, s string) bool {
|
||||||
for _, e := range l {
|
for _, e := range l {
|
||||||
if e == s {
|
if e == s {
|
||||||
|
@@ -30,9 +30,9 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string {
|
|||||||
return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
|
return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string {
|
||||||
global := dexpreopt.GetGlobalConfig(ctx)
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
var systemServerClasspathLocations []string
|
var systemServerClasspathLocations []string
|
||||||
var dexpreoptJars = *DexpreoptedSystemServerJars(ctx.Config())
|
nonUpdatable := dexpreopt.NonUpdatableSystemServerJars(ctx, global)
|
||||||
// 1) The jars that are dexpreopted.
|
// 1) Non-updatable jars.
|
||||||
for _, m := range dexpreoptJars {
|
for _, m := range nonUpdatable {
|
||||||
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
||||||
filepath.Join("/system/framework", m+".jar"))
|
filepath.Join("/system/framework", m+".jar"))
|
||||||
}
|
}
|
||||||
@@ -41,13 +41,6 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string {
|
|||||||
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
systemServerClasspathLocations = append(systemServerClasspathLocations,
|
||||||
dexpreopt.GetJarLocationFromApexJarPair(m))
|
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) {
|
if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) {
|
||||||
panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d",
|
panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d",
|
||||||
len(systemServerClasspathLocations),
|
len(systemServerClasspathLocations),
|
||||||
|
47
java/java.go
47
java/java.go
@@ -23,14 +23,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
"github.com/google/blueprint/pathtools"
|
"github.com/google/blueprint/pathtools"
|
||||||
"github.com/google/blueprint/proptools"
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/dexpreopt"
|
|
||||||
"android/soong/java/config"
|
"android/soong/java/config"
|
||||||
"android/soong/tradefed"
|
"android/soong/tradefed"
|
||||||
)
|
)
|
||||||
@@ -60,8 +58,6 @@ func init() {
|
|||||||
PropertyName: "java_tests",
|
PropertyName: "java_tests",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
android.PostDepsMutators(RegisterPostDepsMutators)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
|
func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
|
||||||
@@ -90,44 +86,6 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
|
|||||||
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
|
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) {
|
func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
|
||||||
if j.SocSpecific() || j.DeviceSpecific() ||
|
if j.SocSpecific() || j.DeviceSpecific() ||
|
||||||
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
|
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
|
||||||
@@ -711,11 +669,6 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
|
|||||||
} else if j.shouldInstrumentStatic(ctx) {
|
} else if j.shouldInstrumentStatic(ctx) {
|
||||||
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
|
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 {
|
func hasSrcExt(srcs []string, ext string) bool {
|
||||||
|
Reference in New Issue
Block a user