Propagate java resources in apps with no code

Use the java resources jar as the dex jar when building apps that
have no code.

Also remove maybeStrippedDexJar, the dex jar is never stripped now.

Fixes: 176305357
Test: TestAppJavaResources
Change-Id: Ic8b1165bd35d71237d307e7f5f895764e203a10d
This commit is contained in:
Colin Cross 2021-02-26 14:54:36 -08:00
parent 5aa1debe6d
commit b014f0787e
4 changed files with 90 additions and 47 deletions

View file

@ -220,7 +220,7 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
} }
return []android.AndroidMkEntries{android.AndroidMkEntries{ return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES", Class: "JAVA_LIBRARIES",
OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile), OutputFile: android.OptionalPathForPath(prebuilt.dexJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {

View file

@ -469,7 +469,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.Module.compile(ctx, a.aaptSrcJar) a.Module.compile(ctx, a.aaptSrcJar)
} }
return a.maybeStrippedDexJarFile return a.dexJarFile
} }
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath { func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {

View file

@ -685,6 +685,51 @@ func TestLibraryAssets(t *testing.T) {
} }
} }
func TestAppJavaResources(t *testing.T) {
bp := `
android_app {
name: "foo",
sdk_version: "current",
java_resources: ["resources/a"],
srcs: ["a.java"],
}
android_app {
name: "bar",
sdk_version: "current",
java_resources: ["resources/a"],
}
`
ctx := testApp(t, bp)
foo := ctx.ModuleForTests("foo", "android_common")
fooResources := foo.Output("res/foo.jar")
fooDexJar := foo.Output("dex-withres/foo.jar")
fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
fooApk := foo.Rule("combineApk")
if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
}
if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
}
if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
}
bar := ctx.ModuleForTests("bar", "android_common")
barResources := bar.Output("res/bar.jar")
barApk := bar.Rule("combineApk")
if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
}
}
func TestAndroidResources(t *testing.T) { func TestAndroidResources(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string

View file

@ -434,9 +434,6 @@ type Module struct {
// output file containing classes.dex and resources // output file containing classes.dex and resources
dexJarFile android.Path dexJarFile android.Path
// output file that contains classes.dex if it should be in the output file
maybeStrippedDexJarFile android.Path
// output file containing uninstrumented classes that will be instrumented by jacoco // output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path jacocoReportClassesFile android.Path
@ -1818,47 +1815,51 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
} }
} }
if ctx.Device() && j.hasCode(ctx) && if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
(Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) { if j.hasCode(ctx) {
if j.shouldInstrumentStatic(ctx) { if j.shouldInstrumentStatic(ctx) {
j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles, j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags")) android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
var dexOutputFile android.OutputPath
dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
// Hidden API CSV generation and dex encoding
dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
proptools.Bool(j.dexProperties.Uncompress_dex))
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
dexOutputFile = combinedAlignedJar
} else {
dexOutputFile = combinedJar
} }
// Dex compilation
var dexOutputFile android.OutputPath
dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
// Hidden API CSV generation and dex encoding
dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
proptools.Bool(j.dexProperties.Uncompress_dex))
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
dexOutputFile = combinedAlignedJar
} else {
dexOutputFile = combinedJar
}
}
j.dexJarFile = dexOutputFile
// Dexpreopting
j.dexpreopt(ctx, dexOutputFile)
outputFile = dexOutputFile
} else {
// There is no code to compile into a dex jar, make sure the resources are propagated
// to the APK if this is an app.
outputFile = implementationAndResourcesJar
j.dexJarFile = j.resourceJar
} }
j.dexJarFile = dexOutputFile
// Dexpreopting
j.dexpreopt(ctx, dexOutputFile)
j.maybeStrippedDexJarFile = dexOutputFile
outputFile = dexOutputFile
if ctx.Failed() { if ctx.Failed() {
return return
} }
@ -3183,8 +3184,7 @@ type DexImport struct {
properties DexImportProperties properties DexImportProperties
dexJarFile android.Path dexJarFile android.Path
maybeStrippedDexJarFile android.Path
dexpreopter dexpreopter
@ -3271,8 +3271,6 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexpreopt(ctx, dexOutputFile) j.dexpreopt(ctx, dexOutputFile)
j.maybeStrippedDexJarFile = dexOutputFile
if apexInfo.IsForPlatform() { if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile) j.Stem()+".jar", dexOutputFile)