Add code coverage support to android_app JNI libs.

Test: Built mainline module coverage data
Bug: 152117890
Change-Id: I47bf3e5d6e78c4518729bdb52616e248156d3cec
This commit is contained in:
Jaewoong Jung 2020-03-26 14:01:48 -07:00
parent 365d107dd3
commit 87a33e72bc
4 changed files with 51 additions and 8 deletions

View file

@ -22,6 +22,7 @@ import (
"android/soong/android"
"android/soong/cc"
"android/soong/java"
"github.com/google/blueprint/proptools"
)
@ -181,6 +182,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
// we will have foo.apk.apk
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".apk"))
if app, ok := fi.module.(*java.AndroidApp); ok && len(app.JniCoverageOutputs()) > 0 {
fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(app.JniCoverageOutputs().Strings(), " "))
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
} else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())

View file

@ -275,7 +275,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
}
func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if !app.IsForPlatform() {
if !app.IsForPlatform() || app.appProperties.HideFromMake {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Disabled: true,
}}
@ -288,6 +288,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
func(entries *android.AndroidMkEntries) {
// App module names can be overridden.
entries.SetString("LOCAL_MODULE", app.installApkName)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage)
if app.dexJarFile != nil {
entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile)
@ -347,6 +348,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
for _, jniLib := range app.installJniLibs {
entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
}
if len(app.jniCoverageOutputs) > 0 {
entries.AddStrings("LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.jniCoverageOutputs.Strings()...)
}
if len(app.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled)
}

View file

@ -105,6 +105,11 @@ type appProperties struct {
// If set, find and merge all NOTICE files that this module and its dependencies have and store
// it in the APK as an asset.
Embed_notices *bool
// cc.Coverage related properties
PreventInstall bool `blueprint:"mutated"`
HideFromMake bool `blueprint:"mutated"`
IsCoverageVariant bool `blueprint:"mutated"`
}
// android_app properties that can be overridden by override_android_app
@ -133,7 +138,8 @@ type AndroidApp struct {
overridableAppProperties overridableAppProperties
installJniLibs []jniLib
installJniLibs []jniLib
jniCoverageOutputs android.Paths
bundleFile android.Path
@ -171,6 +177,10 @@ func (a *AndroidApp) Certificate() Certificate {
return a.certificate
}
func (a *AndroidApp) JniCoverageOutputs() android.Paths {
return a.jniCoverageOutputs
}
var _ AndroidLibraryDependency = (*AndroidApp)(nil)
type Certificate struct {
@ -373,6 +383,11 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext
if a.shouldEmbedJnis(ctx) {
jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
for _, jni := range jniLibs {
if jni.coverageFile.Valid() {
a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path())
}
}
} else {
a.installJniLibs = jniLibs
}
@ -575,9 +590,10 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps
if lib.Valid() {
jniLibs = append(jniLibs, jniLib{
name: ctx.OtherModuleName(module),
path: path,
target: module.Target(),
name: ctx.OtherModuleName(module),
path: path,
target: module.Target(),
coverageFile: dep.CoverageOutputFile(),
})
} else {
ctx.ModuleErrorf("dependency %q missing output file", otherName)
@ -631,6 +647,24 @@ func (a *AndroidApp) Privileged() bool {
return Bool(a.appProperties.Privileged)
}
func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
return ctx.Device() && (ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled())
}
func (a *AndroidApp) PreventInstall() {
a.appProperties.PreventInstall = true
}
func (a *AndroidApp) HideFromMake() {
a.appProperties.HideFromMake = true
}
func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) {
a.appProperties.IsCoverageVariant = coverage
}
var _ cc.Coverage = (*AndroidApp)(nil)
// android_app compiles sources and Android resources into an Android application package `.apk` file.
func AndroidAppFactory() android.Module {
module := &AndroidApp{}

View file

@ -540,9 +540,10 @@ func (s sdkDep) hasFrameworkLibs() bool {
}
type jniLib struct {
name string
path android.Path
target android.Target
name string
path android.Path
target android.Target
coverageFile android.OptionalPath
}
func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {