From 37ca4a1e0dfab898a8abc61c6f62b2d7fc1119e3 Mon Sep 17 00:00:00 2001 From: Jaewoong Jung Date: Thu, 26 Mar 2020 14:01:48 -0700 Subject: [PATCH] Add code coverage support to android_app JNI libs. This is a cherry-pick change. Test: Built mainline module coverage data Bug: 152117890 Change-Id: I47bf3e5d6e78c4518729bdb52616e248156d3cec Merged-In: I47bf3e5d6e78c4518729bdb52616e248156d3cec --- apex/androidmk.go | 4 ++++ java/androidmk.go | 6 +++++- java/app.go | 42 ++++++++++++++++++++++++++++++++++++++---- java/java.go | 7 ++++--- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/apex/androidmk.go b/apex/androidmk.go index 9a29687c2..2303efe58 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -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()) diff --git a/java/androidmk.go b/java/androidmk.go index a220cce70..ee2437aa0 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -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) } diff --git a/java/app.go b/java/app.go index 7a444ca77..f9992d885 100755 --- a/java/app.go +++ b/java/app.go @@ -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 } @@ -572,9 +587,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) @@ -628,6 +644,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{} diff --git a/java/java.go b/java/java.go index dc0b27244..55ad8b019 100644 --- a/java/java.go +++ b/java/java.go @@ -538,9 +538,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 {