aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorJaewoong Jung <jungjw@google.com>2019-06-17 17:40:56 -0700
committerJaewoong Jung <jungjw@google.com>2019-06-25 20:56:17 +0000
commit5c6572e53fa2810e45215850842b81b8fa9a22ec (patch)
tree0db20545dd2f0cda070b05d11069bb8f813cd09d /java
parent3ad00bf196544f686eaf8b9caf8ef44d3e991744 (diff)
downloadbuild_soong-5c6572e53fa2810e45215850842b81b8fa9a22ec.tar.gz
build_soong-5c6572e53fa2810e45215850842b81b8fa9a22ec.tar.bz2
build_soong-5c6572e53fa2810e45215850842b81b8fa9a22ec.zip
Optionally embed NOTICE files in apks.
If embed_notices or ALWAYS_EMBED_NOTICES is set, collect NOTICE files from all dependencies of the android_app, merge them with the app's own one (if exists), transform it to HTML, gzip it, and put it as an asset in the final APK output. Bug: 135460391 Test: app_test.go + Built Mainline modules Change-Id: I52d92e2fd19b3f5f396100424665c5cc344190d8 Merged-In: I52d92e2fd19b3f5f396100424665c5cc344190d8 (cherry picked from commit 5b425e2e20c55216c1ed13fcf047b0df33886736)
Diffstat (limited to 'java')
-rw-r--r--java/aar.go10
-rw-r--r--java/app.go79
-rw-r--r--java/app_test.go95
-rw-r--r--java/java_test.go4
4 files changed, 177 insertions, 11 deletions
diff --git a/java/aar.go b/java/aar.go
index c6212766..6273a9b5 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -17,6 +17,7 @@ package java
import (
"android/soong/android"
"fmt"
+ "path/filepath"
"strings"
"github.com/google/blueprint"
@@ -78,6 +79,7 @@ type aapt struct {
rroDirs []rroDir
rTxt android.Path
extraAaptPackagesFile android.Path
+ noticeFile android.OptionalPath
isLibrary bool
uncompressedJNI bool
useEmbeddedDex bool
@@ -150,10 +152,16 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, mani
assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
}
+ assetDirStrings := assetDirs.Strings()
+ if a.noticeFile.Valid() {
+ assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
+ assetFiles = append(assetFiles, a.noticeFile.Path())
+ }
+
linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
linkDeps = append(linkDeps, manifestPath)
- linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
+ linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A "))
linkDeps = append(linkDeps, assetFiles...)
// SDK version flags
diff --git a/java/app.go b/java/app.go
index da8024fd..8d41b570 100644
--- a/java/app.go
+++ b/java/app.go
@@ -18,6 +18,7 @@ package java
import (
"path/filepath"
+ "sort"
"strings"
"github.com/google/blueprint"
@@ -79,6 +80,10 @@ type appProperties struct {
// Use_embedded_native_libs still selects whether they are stored uncompressed and aligned or compressed.
// True for android_test* modules.
AlwaysPackageNativeLibs bool `blueprint:"mutated"`
+
+ // 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
}
// android_app properties that can be overridden by override_android_app
@@ -335,10 +340,74 @@ func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx
return append([]Certificate{a.certificate}, certificateDeps...)
}
+func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) android.OptionalPath {
+ if !Bool(a.appProperties.Embed_notices) && !ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
+ return android.OptionalPath{}
+ }
+
+ // Collect NOTICE files from all dependencies.
+ seenModules := make(map[android.Module]bool)
+ noticePathSet := make(map[android.Path]bool)
+
+ ctx.WalkDepsBlueprint(func(child blueprint.Module, parent blueprint.Module) bool {
+ if _, ok := child.(android.Module); !ok {
+ return false
+ }
+ module := child.(android.Module)
+ // Have we already seen this?
+ if _, ok := seenModules[module]; ok {
+ return false
+ }
+ seenModules[module] = true
+
+ // Skip host modules.
+ if module.Target().Os.Class == android.Host || module.Target().Os.Class == android.HostCross {
+ return false
+ }
+
+ path := module.NoticeFile()
+ if path.Valid() {
+ noticePathSet[path.Path()] = true
+ }
+ return true
+ })
+
+ // If the app has one, add it too.
+ if a.NoticeFile().Valid() {
+ noticePathSet[a.NoticeFile().Path()] = true
+ }
+
+ if len(noticePathSet) == 0 {
+ return android.OptionalPath{}
+ }
+ var noticePaths []android.Path
+ for path := range noticePathSet {
+ noticePaths = append(noticePaths, path)
+ }
+ sort.Slice(noticePaths, func(i, j int) bool {
+ return noticePaths[i].String() < noticePaths[j].String()
+ })
+ noticeFile := android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
+
+ return android.OptionalPathForPath(noticeFile)
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
// Check if the install APK name needs to be overridden.
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
+ var installDir android.OutputPath
+ if ctx.ModuleName() == "framework-res" {
+ // framework-res.apk is installed as system/framework/framework-res.apk
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ } else if Bool(a.appProperties.Privileged) {
+ installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
+ }
+
+ a.aapt.noticeFile = a.noticeBuildActions(ctx, installDir)
+
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
@@ -374,16 +443,6 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.bundleFile = bundleFile
// Install the app package.
- var installDir android.OutputPath
- if ctx.ModuleName() == "framework-res" {
- // framework-res.apk is installed as system/framework/framework-res.apk
- installDir = android.PathForModuleInstall(ctx, "framework")
- } else if Bool(a.appProperties.Privileged) {
- installDir = android.PathForModuleInstall(ctx, "priv-app", a.installApkName)
- } else {
- installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
- }
-
ctx.InstallFile(installDir, a.installApkName+".apk", a.outputFile)
for _, split := range a.aapt.splits {
ctx.InstallFile(installDir, a.installApkName+"_"+split.suffix+".apk", split.path)
diff --git a/java/app_test.go b/java/app_test.go
index 1f6297c2..d2685107 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -968,3 +968,98 @@ func TestOverrideAndroidApp(t *testing.T) {
}
}
}
+
+func TestEmbedNotice(t *testing.T) {
+ ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ static_libs: ["javalib"],
+ jni_libs: ["libjni"],
+ notice: "APP_NOTICE",
+ embed_notices: true,
+ }
+
+ // No embed_notice flag
+ android_app {
+ name: "bar",
+ srcs: ["a.java"],
+ jni_libs: ["libjni"],
+ notice: "APP_NOTICE",
+ }
+
+ // No NOTICE files
+ android_app {
+ name: "baz",
+ srcs: ["a.java"],
+ embed_notices: true,
+ }
+
+ cc_library {
+ name: "libjni",
+ system_shared_libs: [],
+ stl: "none",
+ notice: "LIB_NOTICE",
+ }
+
+ java_library {
+ name: "javalib",
+ srcs: [
+ ":gen",
+ ],
+ }
+
+ genrule {
+ name: "gen",
+ tools: ["gentool"],
+ out: ["gen.java"],
+ notice: "GENRULE_NOTICE",
+ }
+
+ java_binary_host {
+ name: "gentool",
+ srcs: ["b.java"],
+ notice: "TOOL_NOTICE",
+ }
+ `)
+
+ // foo has NOTICE files to process, and embed_notices is true.
+ foo := ctx.ModuleForTests("foo", "android_common")
+ // verify merge notices rule.
+ mergeNotices := foo.Rule("mergeNoticesRule")
+ noticeInputs := mergeNotices.Inputs.Strings()
+ // TOOL_NOTICE should be excluded as it's a host module.
+ if len(mergeNotices.Inputs) != 3 {
+ t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
+ }
+ if !inList("APP_NOTICE", noticeInputs) {
+ t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
+ }
+ if !inList("LIB_NOTICE", noticeInputs) {
+ t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
+ }
+ if !inList("GENRULE_NOTICE", noticeInputs) {
+ t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
+ }
+ // aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
+ res := foo.Output("package-res.apk")
+ aapt2Flags := res.Args["flags"]
+ e := "-A " + buildDir + "/.intermediates/foo/android_common/NOTICE"
+ if !strings.Contains(aapt2Flags, e) {
+ t.Errorf("asset dir flag for NOTICE, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
+ }
+
+ // bar has NOTICE files to process, but embed_notices is not set.
+ bar := ctx.ModuleForTests("bar", "android_common")
+ mergeNotices = bar.MaybeRule("mergeNoticesRule")
+ if mergeNotices.Rule != nil {
+ t.Errorf("mergeNotices shouldn't have run for bar")
+ }
+
+ // baz's embed_notice is true, but it doesn't have any NOTICE files.
+ baz := ctx.ModuleForTests("baz", "android_common")
+ mergeNotices = baz.MaybeRule("mergeNoticesRule")
+ if mergeNotices.Rule != nil {
+ t.Errorf("mergeNotices shouldn't have run for baz")
+ }
+}
diff --git a/java/java_test.go b/java/java_test.go
index a5c0aa93..31b23e76 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -119,6 +119,10 @@ func testContext(config android.Config, bp string,
"b.kt": nil,
"a.jar": nil,
"b.jar": nil,
+ "APP_NOTICE": nil,
+ "GENRULE_NOTICE": nil,
+ "LIB_NOTICE": nil,
+ "TOOL_NOTICE": nil,
"java-res/a/a": nil,
"java-res/b/b": nil,
"java-res2/a": nil,