aboutsummaryrefslogtreecommitdiff
path: root/dexpreopt
diff options
context:
space:
mode:
authorJiakai Zhang <jiakaiz@google.com>2021-12-14 18:54:06 +0000
committerJiakai Zhang <jiakaiz@google.com>2021-12-20 15:07:26 +0000
commit389a64732076afed0462790836e024badf7bf333 (patch)
treeb2841a1a6aacbe22a9bad4588e64cb3443dffd61 /dexpreopt
parentf25ab75d63805bd6db252d49fa8e47d56e797a0e (diff)
Dexpreopt standalone system server jars.
Standalone system server jars are dynamically loaded by system server using a `PathClassLoader` whose parent is `SYSTEMSERVERCLASSPATH`. They are listed in `PRODUCT_STANDALONE_SYSTEM_SERVER_JARS` and `PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS` in Makefile. We need to dexpreopt them to achieve better performance. Bug: 203198541 Test: m nothing Test: - 1. Add a standalone system server jar (e.g., by patching aosp/1906158) 2. Build a system image. 3. See the odex and vdex files generated in $ANDROID_PRODUCT_OUT/system/framework/oat/ 4. Flash the image to a device. 5. Run `atest art_standalone_dexpreopt_tests`. Change-Id: I358a62d34989c5c8eba12e18fe6167e0b72ff69d
Diffstat (limited to 'dexpreopt')
-rw-r--r--dexpreopt/config.go42
-rw-r--r--dexpreopt/dexpreopt.go49
-rw-r--r--dexpreopt/dexpreopt_test.go55
3 files changed, 124 insertions, 22 deletions
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 6d6b41d4b..1f99a96c1 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -100,6 +100,48 @@ type GlobalConfig struct {
RelaxUsesLibraryCheck bool
}
+var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
+
+// Returns all jars on the platform that system_server loads, including those on classpath and those
+// loaded dynamically.
+func (g *GlobalConfig) AllPlatformSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList {
+ return ctx.Config().Once(allPlatformSystemServerJarsKey, func() interface{} {
+ res := g.SystemServerJars.AppendList(&g.StandaloneSystemServerJars)
+ return &res
+ }).(*android.ConfiguredJarList)
+}
+
+var allApexSystemServerJarsKey = android.NewOnceKey("allApexSystemServerJars")
+
+// Returns all jars delivered via apex that system_server loads, including those on classpath and
+// those loaded dynamically.
+func (g *GlobalConfig) AllApexSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList {
+ return ctx.Config().Once(allApexSystemServerJarsKey, func() interface{} {
+ res := g.ApexSystemServerJars.AppendList(&g.ApexStandaloneSystemServerJars)
+ return &res
+ }).(*android.ConfiguredJarList)
+}
+
+var allSystemServerClasspathJarsKey = android.NewOnceKey("allSystemServerClasspathJars")
+
+// Returns all system_server classpath jars.
+func (g *GlobalConfig) AllSystemServerClasspathJars(ctx android.PathContext) *android.ConfiguredJarList {
+ return ctx.Config().Once(allSystemServerClasspathJarsKey, func() interface{} {
+ res := g.SystemServerJars.AppendList(&g.ApexSystemServerJars)
+ return &res
+ }).(*android.ConfiguredJarList)
+}
+
+var allSystemServerJarsKey = android.NewOnceKey("allSystemServerJars")
+
+// Returns all jars that system_server loads.
+func (g *GlobalConfig) AllSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList {
+ return ctx.Config().Once(allSystemServerJarsKey, func() interface{} {
+ res := g.AllPlatformSystemServerJars(ctx).AppendList(g.AllApexSystemServerJars(ctx))
+ return &res
+ }).(*android.ConfiguredJarList)
+}
+
// GlobalSoongConfig contains the global config that is generated from Soong,
// stored in dexpreopt_soong.config.
type GlobalSoongConfig struct {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 3145315e3..de139c439 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -115,7 +115,7 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo
// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
// or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options.
if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) &&
- !AllSystemServerJars(ctx, global).ContainsJar(module.Name) && !module.PreoptExtractedApk {
+ !global.AllSystemServerJars(ctx).ContainsJar(module.Name) && !module.PreoptExtractedApk {
return true
}
@@ -197,8 +197,8 @@ func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig,
}
// Returns the dex location of a system server java library.
-func GetSystemServerDexLocation(global *GlobalConfig, lib string) string {
- if apex := global.ApexSystemServerJars.ApexOfJar(lib); apex != "" {
+func GetSystemServerDexLocation(ctx android.PathContext, global *GlobalConfig, lib string) string {
+ if apex := global.AllApexSystemServerJars(ctx).ApexOfJar(lib); apex != "" {
return fmt.Sprintf("/apex/%s/javalib/%s.jar", apex, lib)
}
return fmt.Sprintf("/system/framework/%s.jar", lib)
@@ -240,7 +240,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
- systemServerJars := AllSystemServerJars(ctx, global)
+ systemServerJars := global.AllSystemServerJars(ctx)
+ systemServerClasspathJars := global.AllSystemServerClasspathJars(ctx)
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
rule.Command().FlagWithOutput("rm -f ", odexPath)
@@ -251,10 +252,15 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
var clcHost android.Paths
var clcTarget []string
- for i := 0; i < jarIndex; i++ {
- lib := systemServerJars.Jar(i)
+ endIndex := systemServerClasspathJars.IndexOfJar(module.Name)
+ if endIndex < 0 {
+ // The jar is a standalone one. Use the full classpath as the class loader context.
+ endIndex = systemServerClasspathJars.Len()
+ }
+ for i := 0; i < endIndex; i++ {
+ lib := systemServerClasspathJars.Jar(i)
clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
- clcTarget = append(clcTarget, GetSystemServerDexLocation(global, lib))
+ clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib))
}
if DexpreoptRunningInSoong {
@@ -270,12 +276,22 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
// cannot see the rule in the generated dexpreopt.sh script).
}
- checkSystemServerOrder(ctx, jarIndex)
+ clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]"
+ clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]"
+
+ if systemServerClasspathJars.ContainsJar(module.Name) {
+ checkSystemServerOrder(ctx, jarIndex)
+ } else {
+ // Standalone jars are loaded by separate class loaders with SYSTEMSERVERCLASSPATH as the
+ // parent.
+ clcHostString = "PCL[];" + clcHostString
+ clcTargetString = "PCL[];" + clcTargetString
+ }
rule.Command().
- Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clcHost.Strings(), ":") + "]").
+ Text(`class_loader_context_arg=--class-loader-context="` + clcHostString + `"`).
Implicits(clcHost).
- Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
+ Text(`stored_class_loader_context_arg=--stored-class-loader-context="` + clcTargetString + `"`)
} else {
// There are three categories of Java modules handled here:
@@ -533,17 +549,6 @@ func makefileMatch(pattern, s string) bool {
}
}
-var allSystemServerJarsKey = android.NewOnceKey("allSystemServerJars")
-
-// TODO: eliminate the superficial global config parameter by moving global config definition
-// from java subpackage to dexpreopt.
-func AllSystemServerJars(ctx android.PathContext, global *GlobalConfig) *android.ConfiguredJarList {
- return ctx.Config().Once(allSystemServerJarsKey, func() interface{} {
- allSystemServerJars := global.SystemServerJars.AppendList(global.ApexSystemServerJars)
- return &allSystemServerJars
- }).(*android.ConfiguredJarList)
-}
-
// 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
@@ -567,7 +572,7 @@ func checkSystemServerOrder(ctx android.PathContext, jarIndex int) {
mctx, isModule := ctx.(android.ModuleContext)
if isModule {
config := GetGlobalConfig(ctx)
- jars := AllSystemServerJars(ctx, config)
+ jars := config.AllSystemServerClasspathJars(ctx)
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
depIndex := jars.IndexOfJar(dep.Name())
if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 798d77604..07e4fad01 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -50,6 +50,15 @@ func testApexModuleConfig(ctx android.PathContext, name, apexName string) *Modul
android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
}
+func testPlatformSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
+ return createTestModuleConfig(
+ name,
+ fmt.Sprintf("/system/framework/%s.jar", name),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
+}
+
func createTestModuleConfig(name, dexLocation string, buildPath, dexPath, enforceUsesLibrariesStatusFile android.OutputPath) *ModuleConfig {
return &ModuleConfig{
Name: name,
@@ -181,6 +190,52 @@ func TestDexPreoptApexSystemServerJars(t *testing.T) {
android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
}
+func TestDexPreoptStandaloneSystemServerJars(t *testing.T) {
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.BuilderContextForTesting(config)
+ globalSoong := globalSoongConfigForTests()
+ global := GlobalConfigForTests(ctx)
+ module := testPlatformSystemServerModuleConfig(ctx, "service-A")
+
+ global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(
+ []string{"platform:service-A"})
+
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wantInstalls := android.RuleBuilderInstalls{
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/service-A.odex"},
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/service-A.vdex"},
+ }
+
+ android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
+}
+
+func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) {
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.BuilderContextForTesting(config)
+ globalSoong := globalSoongConfigForTests()
+ global := GlobalConfigForTests(ctx)
+ module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
+
+ global.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList(
+ []string{"com.android.apex1:service-A"})
+
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wantInstalls := android.RuleBuilderInstalls{
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"},
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"},
+ }
+
+ android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
+}
+
func TestDexPreoptProfile(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)