From cd3203fd5dfc89ff908c3d9beb06ccf6d5d551eb Mon Sep 17 00:00:00 2001 From: Ulya Trafimovich Date: Fri, 27 Mar 2020 11:30:00 +0000 Subject: [PATCH] Error on suboptimal system server classpath order, unless explicitly allowed. The order is non-optimal if some jar X precedes its dependency Y. In that case dexpreopt will be unable to resolve any rerefences from X to Y. Raise an error unless the product sets variable PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS to true in the makefile. This is to prevent regressions in existing products that currently have correct order. Test: lunch cf_x86_phone-userdebug && m nothing Test: lunch aosp_car_arm && m nothing Bug: 140451054 Change-Id: Iafe8fe0e992deb628e38f2321d4601a4804a3c79 Merged-In: Iafe8fe0e992deb628e38f2321d4601a4804a3c79 (cherry picked from commit fb863c87c4240c09be45043d168c165760ecf90a) --- dexpreopt/config.go | 2 ++ dexpreopt/dexpreopt.go | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/dexpreopt/config.go b/dexpreopt/config.go index 98850e51a..01481615f 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -50,6 +50,8 @@ type GlobalConfig struct { UpdatableSystemServerJars []string // jars within apex that are loaded into system server SpeedApps []string // apps that should be speed optimized + BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error + PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index de696da10..b6e6b9a07 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -307,6 +307,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g 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) + + checkSystemServerOrder(ctx, jarIndex) } else { // Pass special class loader context to skip the classpath and collision check. // This will get removed once LOCAL_USES_LIBRARIES is enforced. @@ -606,6 +608,29 @@ func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.Out } } +// Check the order of jars on the system server classpath and give a warning/error if a jar precedes +// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't +// have the dependency jar in the class loader context, and it won't be able to resolve any +// references to its classes and methods. +func checkSystemServerOrder(ctx android.PathContext, jarIndex int) { + mctx, isModule := ctx.(android.ModuleContext) + if isModule { + config := GetGlobalConfig(ctx) + jars := NonUpdatableSystemServerJars(ctx, config) + mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { + depIndex := android.IndexList(dep.Name(), jars) + if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { + jar := jars[jarIndex] + dep := jars[depIndex] + mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+ + " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+ + " references from '%s' to '%s'.\n", jar, dep, jar, dep) + } + return true + }) + } +} + func contains(l []string, s string) bool { for _, e := range l { if e == s {