Merge "Ensure sscp jars get copied to $OUT/soong/system_server_dexjars" into main am: 9d4ad66a93

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2923733

Change-Id: Ie566d78cd8a5f4d64c749c341e1e1d1a64e1fa60
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Spandan Das
2024-01-25 02:18:25 +00:00
committed by Automerger Merge Worker
5 changed files with 105 additions and 47 deletions

View File

@@ -11537,6 +11537,17 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar) android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar)
} }
// Check that system server jars is copied to out/soong/system_server_dexjars. This hardcoded location is used by dexpreopt
checkSystemServerJarOnHost := func(t *testing.T, ctx *android.TestContext, m, libName, expectedSystemServerJarPath string) {
variation := "android_common_com.android.foo"
if m == "com.android.foo" {
m = libName // for source builds, the cp rule is still generated by the java_library module
variation = "android_common_apex10000"
}
output := ctx.ModuleForTests(m, variation).MaybeOutput("system_server_dexjars/" + libName + ".jar")
android.AssertStringListContains(t, libName+" is expected to be copied to out/soong/system_server_dexjars/ from ", output.Implicits.Strings(), expectedSystemServerJarPath)
}
bp := ` bp := `
// Source APEX. // Source APEX.
@@ -11560,6 +11571,24 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
}, },
} }
java_library {
name: "service-foo",
srcs: ["foo.java"],
installable: true,
apex_available: [
"com.android.foo",
],
}
systemserverclasspath_fragment {
name: "foo-systemserverclasspath-fragment",
contents: ["service-foo"],
apex_available: [
"com.android.foo",
],
}
apex_key { apex_key {
name: "com.android.foo.key", name: "com.android.foo.key",
public_key: "com.android.foo.avbpubkey", public_key: "com.android.foo.avbpubkey",
@@ -11570,18 +11599,16 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
name: "com.android.foo", name: "com.android.foo",
key: "com.android.foo.key", key: "com.android.foo.key",
bootclasspath_fragments: ["foo-bootclasspath-fragment"], bootclasspath_fragments: ["foo-bootclasspath-fragment"],
systemserverclasspath_fragments: ["foo-systemserverclasspath-fragment"],
updatable: false, updatable: false,
} }
// Prebuilt APEX. // Prebuilt APEX.
java_sdk_library_import { java_import {
name: "framework-foo", name: "framework-foo",
public: { jars: ["foo.jar"],
jars: ["foo.jar"],
},
apex_available: ["com.android.foo"], apex_available: ["com.android.foo"],
shared_library: false,
} }
prebuilt_bootclasspath_fragment { prebuilt_bootclasspath_fragment {
@@ -11599,11 +11626,27 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
], ],
} }
java_import {
name: "service-foo",
jars: ["foo.jar"],
apex_available: ["com.android.foo"],
}
prebuilt_systemserverclasspath_fragment {
name: "foo-systemserverclasspath-fragment",
contents: ["service-foo"],
apex_available: [
"com.android.foo",
],
}
prebuilt_apex { prebuilt_apex {
name: "com.android.foo", name: "com.android.foo",
apex_name: "com.android.foo", apex_name: "com.android.foo",
src: "com.android.foo-arm.apex", src: "com.android.foo-arm.apex",
exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"], exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
exported_systemserverclasspath_fragments: ["foo-systemserverclasspath-fragment"],
} }
// Another Prebuilt ART APEX // Another Prebuilt ART APEX
@@ -11612,48 +11655,41 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
apex_name: "com.android.foo", // Used to determine the API domain apex_name: "com.android.foo", // Used to determine the API domain
src: "com.android.foo-arm.apex", src: "com.android.foo-arm.apex",
exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"], exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
exported_systemserverclasspath_fragments: ["foo-systemserverclasspath-fragment"],
} }
// APEX contribution modules // APEX contribution modules
apex_contributions { apex_contributions {
name: "foo.source.contributions", name: "foo.contributions",
api_domain: "com.android.foo", api_domain: "com.android.foo",
contents: ["com.android.foo"], contents: ["%v"],
}
apex_contributions {
name: "foo.prebuilt.contributions",
api_domain: "com.android.foo",
contents: ["prebuilt_com.android.foo"],
}
apex_contributions {
name: "foo.prebuilt.v2.contributions",
api_domain: "com.android.foo",
contents: ["com.android.foo.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
} }
` `
testCases := []struct { testCases := []struct {
desc string desc string
selectedApexContributions string selectedApex string
expectedBootJar string expectedBootJar string
expectedSystemServerJar string
}{ }{
{ {
desc: "Source apex com.android.foo is selected, bootjar should come from source java library", desc: "Source apex com.android.foo is selected, bootjar should come from source java library",
selectedApexContributions: "foo.source.contributions", selectedApex: "com.android.foo",
expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar", expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar",
expectedSystemServerJar: "out/soong/.intermediates/service-foo/android_common_apex10000/aligned/service-foo.jar",
}, },
{ {
desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt", desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.contributions", selectedApex: "prebuilt_com.android.foo",
expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar", expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar",
expectedSystemServerJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/service-foo.jar",
}, },
{ {
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt", desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions", selectedApex: "com.android.foo.v2",
expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar", expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
expectedSystemServerJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/service-foo.jar",
}, },
} }
@@ -11665,19 +11701,21 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
preparer := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
java.FixtureConfigureApexBootJars("com.android.foo:framework-foo"), java.FixtureConfigureApexBootJars("com.android.foo:framework-foo"),
dexpreopt.FixtureSetApexSystemServerJars("com.android.foo:service-foo"),
android.FixtureMergeMockFs(map[string][]byte{ android.FixtureMergeMockFs(map[string][]byte{
"system/sepolicy/apex/com.android.foo-file_contexts": nil, "system/sepolicy/apex/com.android.foo-file_contexts": nil,
}), }),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{ variables.BuildFlags = map[string]string{
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions, "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "foo.contributions",
} }
}), }),
) )
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) ctx := testDexpreoptWithApexes(t, fmt.Sprintf(bp, tc.selectedApex), "", preparer, fragment)
checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar) checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar)
checkBootJarsPackageCheck(t, ctx, tc.expectedBootJar) checkBootJarsPackageCheck(t, ctx, tc.expectedBootJar)
checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar) checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar)
checkSystemServerJarOnHost(t, ctx, tc.selectedApex, "service-foo", tc.expectedSystemServerJar)
} }
} }

View File

@@ -201,6 +201,10 @@ func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
if !p.hasExportedDeps() { if !p.hasExportedDeps() {
return return
} }
// If this prebuilt apex has not been selected, return
if p.IsHideFromMake() {
return
}
// Use apex_name to determine the api domain of this prebuilt apex // Use apex_name to determine the api domain of this prebuilt apex
apexName := p.ApexVariationName() apexName := p.ApexVariationName()
di, err := android.FindDeapexerProviderForModule(ctx) di, err := android.FindDeapexerProviderForModule(ctx)

View File

@@ -229,6 +229,30 @@ func ToOdexPath(path string, arch android.ArchType) string {
pathtools.ReplaceExtension(filepath.Base(path), "odex")) pathtools.ReplaceExtension(filepath.Base(path), "odex"))
} }
// Copy the dex'd system server to a predefined location in out/soong/system_server_dexjars
// dex2oat will use this predefined location to generate the dexpreopt artifacts.
func CopySystemServerJarsToPredefinedLocations(ctx android.BuilderContext, libName string, libDexPath android.Path) {
allSystemServerJars := GetGlobalConfig(ctx).AllSystemServerJars(ctx)
if !allSystemServerJars.ContainsJar(libName) {
// This is not a system server jar
return
}
if DexpreoptRunningInSoong {
// Copy the system server jar to a predefined location where dex2oat will find it.
rule := android.NewRuleBuilder(pctx, ctx)
dexPathHost := SystemServerDexJarHostPath(ctx, libName)
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
rule.Command().Text("cp -f").Input(libDexPath).Output(dexPathHost)
rule.Build("copy "+libName+" to soong/system_server_dexjars/", "system_server_dexjars")
} else {
// For Make modules the copy rule is generated in the makefiles, not in dexpreopt.sh.
// This is necessary to expose the rule to Ninja, otherwise it has rules that depend on
// the jar (namely, dexpreopt commands for all subsequent system server jars that have
// this one in their class loader context), but no rule that creates it (because Ninja
// cannot see the rule in the generated dexpreopt.sh script).
}
}
func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig, func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig,
global *GlobalConfig, module *ModuleConfig, rule *android.RuleBuilder, archIdx int, global *GlobalConfig, module *ModuleConfig, rule *android.RuleBuilder, archIdx int,
profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path) { profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path) {
@@ -277,19 +301,6 @@ func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig
clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib)) clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib))
} }
if DexpreoptRunningInSoong {
// 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 {
// For Make modules the copy rule is generated in the makefiles, not in dexpreopt.sh.
// This is necessary to expose the rule to Ninja, otherwise it has rules that depend on
// the jar (namely, dexpreopt commands for all subsequent system server jars that have
// this one in their class loader context), but no rule that creates it (because Ninja
// cannot see the rule in the generated dexpreopt.sh script).
}
clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]" clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]"
clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]" clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]"

View File

@@ -1627,6 +1627,9 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath
// Dexpreopting // Dexpreopting
j.dexpreopt(ctx, dexOutputFile) j.dexpreopt(ctx, dexOutputFile)
if !j.IsHideFromMake() {
dexpreopt.CopySystemServerJarsToPredefinedLocations(ctx, j.Name(), dexOutputFile)
}
outputFile = dexOutputFile outputFile = dexOutputFile
} else { } else {

View File

@@ -274,6 +274,8 @@ func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleCo
// generate the rules for creating the .odex and .vdex files for this system server jar // generate the rules for creating the .odex and .vdex files for this system server jar
dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName)) dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
d.dexpreopt(ctx, dexJarFile) d.dexpreopt(ctx, dexJarFile)
dexpreopt.CopySystemServerJarsToPredefinedLocations(ctx, libraryName, dexJarFile)
} }
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) { func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
@@ -370,7 +372,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
// Full dexpreopt config, used to create dexpreopt build rules. // Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{ dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: moduleName(ctx), Name: dexJarStem, // use dexJarStem as the name of the library so that this function can be called from an apex.
DexLocation: dexLocation, DexLocation: dexLocation,
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, moduleName(ctx)+".jar").OutputPath, BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, moduleName(ctx)+".jar").OutputPath,
DexPath: dexJarFile, DexPath: dexJarFile,