Merge "Docs: Add link to related Soong docs on SAC"
diff --git a/Android.bp b/Android.bp
index b4a9d30..97f786e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -243,6 +243,7 @@
"java/droiddoc.go",
"java/gen.go",
"java/genrule.go",
+ "java/hiddenapi.go",
"java/jacoco.go",
"java/java.go",
"java/jdeps.go",
diff --git a/OWNERS b/OWNERS
index 892beb7..7983c19 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,4 @@
-per-file * = ccross@android.com,dwillemsen@google.com,jungjw@google.com
+per-file * = asmundak@google.com,ccross@android.com,dwillemsen@google.com,jungjw@google.com
per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
per-file tidy.go = srhines@google.com, chh@google.com
diff --git a/android/config.go b/android/config.go
index 09d9cbc..cf4d6e5 100644
--- a/android/config.go
+++ b/android/config.go
@@ -983,6 +983,18 @@
return c.productVariables.EnforceSystemCertificateWhitelist
}
+func (c *config) HiddenAPIPublicList() string {
+ return String(c.productVariables.HiddenAPIPublicList)
+}
+
+func (c *config) HiddenAPIFlags() string {
+ return String(c.productVariables.HiddenAPIFlags)
+}
+
+func (c *config) HiddenAPIExtraAppUsageJars() []string {
+ return c.productVariables.HiddenAPIExtraAppUsageJars
+}
+
func stringSlice(s *[]string) []string {
if s != nil {
return *s
diff --git a/android/module.go b/android/module.go
index aed16b3..551824d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path"
"path/filepath"
"sort"
"strings"
@@ -1268,6 +1269,10 @@
if !a.skipInstall(fullInstallPath) {
+ relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
+ if err != nil {
+ panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
+ }
a.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base(),
@@ -1275,7 +1280,7 @@
OrderOnly: Paths{srcPath},
Default: !a.Config().EmbeddedInMake(),
Args: map[string]string{
- "fromPath": srcPath.String(),
+ "fromPath": relPath,
},
})
diff --git a/android/variable.go b/android/variable.go
index e19d858..46b1155 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -271,6 +271,11 @@
EnforceSystemCertificate *bool `json:",omitempty"`
EnforceSystemCertificateWhitelist []string `json:",omitempty"`
+
+ // TODO(ccross): move these to a Singleton in Soong
+ HiddenAPIPublicList *string `json:",omitempty"`
+ HiddenAPIFlags *string `json:",omitempty"`
+ HiddenAPIExtraAppUsageJars []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/java/androidmk.go b/java/androidmk.go
index 7b81273..b9e4298 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -28,6 +28,11 @@
fmt.Fprintln(w, "LOCAL_MODULE := "+name+"-hostdex")
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := JAVA_LIBRARIES")
+ if library.dexJarFile != nil {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.dexJarFile.String())
+ } else {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.implementationAndResourcesJar.String())
+ }
if library.installFile == nil {
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
}
diff --git a/java/app.go b/java/app.go
index 4bae78a..e44737e 100644
--- a/java/app.go
+++ b/java/app.go
@@ -261,7 +261,7 @@
certificates = append([]Certificate{a.certificate}, certificateDeps...)
- packageFile := android.PathForModuleOut(ctx, "package.apk")
+ packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
if !a.Module.Platform() {
diff --git a/java/config/config.go b/java/config/config.go
index 92cfb84..5c838a5 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -154,4 +154,7 @@
pctx.SourcePathsVariable("ManifestMergerClasspath", ":", ManifestMergerClasspath...)
pctx.HostBinToolVariable("ZipAlign", "zipalign")
+
+ pctx.HostBinToolVariable("Class2Greylist", "class2greylist")
+ pctx.HostBinToolVariable("HiddenAPI", "hiddenapi")
}
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 01adaa7..156ee26 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -78,4 +78,7 @@
ctx.Strict("ANDROID_MANIFEST_MERGER_DEPS", "${ManifestMergerJars}")
ctx.Strict("ANDROID_MANIFEST_MERGER",
"${JavaCmd} -classpath ${ManifestMergerClasspath} com.android.manifmerger.Merger")
+
+ ctx.Strict("CLASS2GREYLIST", "${Class2Greylist}")
+ ctx.Strict("HIDDENAPI", "${HiddenAPI}")
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
new file mode 100644
index 0000000..de72e7c
--- /dev/null
+++ b/java/hiddenapi.go
@@ -0,0 +1,145 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "sort"
+ "strings"
+ "sync"
+
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+)
+
+var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", blueprint.RuleParams{
+ Command: "${config.Class2Greylist} --public-api-list ${publicAPIList} $in $outFlag $out",
+ CommandDeps: []string{"${config.Class2Greylist}"},
+}, "outFlag", "publicAPIList")
+
+func hiddenAPIGenerateCSV(ctx android.ModuleContext, classesJar android.Path) {
+ flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
+ metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
+ publicList := &bootImagePath{ctx.Config().HiddenAPIPublicList()}
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hiddenAPIGenerateCSVRule,
+ Description: "hiddenapi flags",
+ Input: classesJar,
+ Output: flagsCSV,
+ Implicit: publicList,
+ Args: map[string]string{
+ "outFlag": "--write-flags-csv",
+ "publicAPIList": publicList.String(),
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hiddenAPIGenerateCSVRule,
+ Description: "hiddenapi metadata",
+ Input: classesJar,
+ Output: metadataCSV,
+ Implicit: publicList,
+ Args: map[string]string{
+ "outFlag": "--write-metadata-csv",
+ "publicAPIList": publicList.String(),
+ },
+ })
+
+ hiddenAPISaveCSVOutputs(ctx, flagsCSV, metadataCSV)
+}
+
+var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
+ Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output && ` +
+ `unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input && ` +
+ `for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do ` +
+ ` echo "--input-dex=$${INPUT_DEX}"; ` +
+ ` echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})"; ` +
+ `done | xargs ${config.HiddenAPI} encode --api-flags=$flags && ` +
+ `${config.SoongZipCmd} -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" && ` +
+ `${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" $out $tmpDir/dex.jar $in`,
+ CommandDeps: []string{
+ "${config.HiddenAPI}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+}, "flags", "tmpDir")
+
+func hiddenAPIEncodeDex(ctx android.ModuleContext, output android.WritablePath, dexInput android.WritablePath) {
+ flags := &bootImagePath{ctx.Config().HiddenAPIFlags()}
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hiddenAPIEncodeDexRule,
+ Description: "hiddenapi encode dex",
+ Input: dexInput,
+ Output: output,
+ Implicit: flags,
+ Args: map[string]string{
+ "flags": flags.String(),
+ "tmpDir": android.PathForModuleOut(ctx, "hiddenapi", "dex").String(),
+ },
+ })
+
+ hiddenAPISaveDexInputs(ctx, dexInput)
+}
+
+const hiddenAPIOutputsKey = "hiddenAPIOutputsKey"
+
+var hiddenAPIOutputsLock sync.Mutex
+
+func hiddenAPIGetOutputs(config android.Config) (*android.Paths, *android.Paths, *android.Paths) {
+ type threePathsPtrs [3]*android.Paths
+ s := config.Once(hiddenAPIOutputsKey, func() interface{} {
+ return threePathsPtrs{new(android.Paths), new(android.Paths), new(android.Paths)}
+ }).(threePathsPtrs)
+ return s[0], s[1], s[2]
+}
+
+func hiddenAPISaveCSVOutputs(ctx android.ModuleContext, flagsCSV, metadataCSV android.Path) {
+ flagsCSVList, metadataCSVList, _ := hiddenAPIGetOutputs(ctx.Config())
+
+ hiddenAPIOutputsLock.Lock()
+ defer hiddenAPIOutputsLock.Unlock()
+
+ *flagsCSVList = append(*flagsCSVList, flagsCSV)
+ *metadataCSVList = append(*metadataCSVList, metadataCSV)
+}
+
+func hiddenAPISaveDexInputs(ctx android.ModuleContext, dexInput android.Path) {
+ _, _, dexInputList := hiddenAPIGetOutputs(ctx.Config())
+
+ hiddenAPIOutputsLock.Lock()
+ defer hiddenAPIOutputsLock.Unlock()
+
+ *dexInputList = append(*dexInputList, dexInput)
+}
+
+func init() {
+ android.RegisterMakeVarsProvider(pctx, hiddenAPIMakeVars)
+}
+
+func hiddenAPIMakeVars(ctx android.MakeVarsContext) {
+ flagsCSVList, metadataCSVList, dexInputList := hiddenAPIGetOutputs(ctx.Config())
+
+ export := func(name string, paths *android.Paths) {
+ s := paths.Strings()
+ sort.Strings(s)
+ ctx.Strict(name, strings.Join(s, " "))
+ }
+
+ export("SOONG_HIDDENAPI_FLAGS", flagsCSVList)
+ export("SOONG_HIDDENAPI_GREYLIST_METADATA", metadataCSVList)
+ export("SOONG_HIDDENAPI_DEX_INPUTS", dexInputList)
+}
diff --git a/java/java.go b/java/java.go
index 2ac5a5b..209d0a7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1172,12 +1172,27 @@
j.implementationAndResourcesJar = implementationAndResourcesJar
if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
+ // Dex compilation
var dexOutputFile android.ModuleOutPath
dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
if ctx.Failed() {
return
}
+ // Hidden API CSV generation and dex encoding
+ if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ isBootJar := inList(ctx.ModuleName(), ctx.Config().BootJars())
+ if isBootJar || inList(ctx.ModuleName(), ctx.Config().HiddenAPIExtraAppUsageJars()) {
+ // Derive the greylist from classes jar.
+ hiddenAPIGenerateCSV(ctx, j.implementationJarFile)
+ }
+ if isBootJar {
+ hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", jarName)
+ hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexOutputFile)
+ dexOutputFile = hiddenAPIJar
+ }
+ }
+
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
@@ -1189,6 +1204,7 @@
j.dexJarFile = dexOutputFile
+ // Dexpreopting
j.dexpreopter.isInstallable = Bool(j.properties.Installable)
j.dexpreopter.uncompressedDex = j.deviceProperties.UncompressDex
dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 1d8684b..1c0ee34 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -96,7 +96,6 @@
"javap": Allowed,
"lsof": Allowed,
"m4": Allowed,
- "md5sum": Allowed,
"openssl": Allowed,
"patch": Allowed,
"pgrep": Allowed,
@@ -110,14 +109,10 @@
"rsync": Allowed,
"sed": Allowed,
"sh": Allowed,
- "sha1sum": Allowed,
- "sha256sum": Allowed,
- "sha512sum": Allowed,
"tar": Allowed,
"timeout": Allowed,
"tr": Allowed,
"unzip": Allowed,
- "wc": Allowed,
"which": Allowed,
"xz": Allowed,
"zip": Allowed,
@@ -137,46 +132,51 @@
"ld.gold": Forbidden,
"pkg-config": Forbidden,
- // On linux we'll use the toybox version of these instead
- "basename": Toybox,
- "cat": Toybox,
- "chmod": Toybox,
- "cmp": Toybox,
- "comm": Toybox,
- "cut": Toybox,
- "dirname": Toybox,
- "du": Toybox,
- "echo": Toybox,
- "env": Toybox,
- "expr": Toybox,
- "head": Toybox,
- "getconf": Toybox,
- "id": Toybox,
- "ln": Toybox,
- "ls": Toybox,
- "mkdir": Toybox,
- "mktemp": Toybox,
- "mv": Toybox,
- "od": Toybox,
- "paste": Toybox,
- "pwd": Toybox,
- "readlink": Toybox,
- "rm": Toybox,
- "rmdir": Toybox,
- "setsid": Toybox,
- "sleep": Toybox,
- "sort": Toybox,
- "stat": Toybox,
- "tail": Toybox,
- "tee": Toybox,
- "touch": Toybox,
- "true": Toybox,
- "uname": Toybox,
- "uniq": Toybox,
- "unix2dos": Toybox,
- "whoami": Toybox,
- "xargs": Toybox,
- "xxd": Toybox,
+ // On Linux we'll use the toybox versions of these instead.
+ "basename": Toybox,
+ "cat": Toybox,
+ "chmod": Toybox,
+ "cmp": Toybox,
+ "comm": Toybox,
+ "cut": Toybox,
+ "dirname": Toybox,
+ "du": Toybox,
+ "echo": Toybox,
+ "env": Toybox,
+ "expr": Toybox,
+ "head": Toybox,
+ "getconf": Toybox,
+ "id": Toybox,
+ "ln": Toybox,
+ "ls": Toybox,
+ "md5sum": Toybox,
+ "mkdir": Toybox,
+ "mktemp": Toybox,
+ "mv": Toybox,
+ "od": Toybox,
+ "paste": Toybox,
+ "pwd": Toybox,
+ "readlink": Toybox,
+ "rm": Toybox,
+ "rmdir": Toybox,
+ "setsid": Toybox,
+ "sha1sum": Toybox,
+ "sha256sum": Toybox,
+ "sha512sum": Toybox,
+ "sleep": Toybox,
+ "sort": Toybox,
+ "stat": Toybox,
+ "tail": Toybox,
+ "tee": Toybox,
+ "touch": Toybox,
+ "true": Toybox,
+ "uname": Toybox,
+ "uniq": Toybox,
+ "unix2dos": Toybox,
+ "wc": Toybox,
+ "whoami": Toybox,
+ "xargs": Toybox,
+ "xxd": Toybox,
}
func init() {