Merge "Make test_options.timeout an int64"
diff --git a/android/config.go b/android/config.go
index 1507c25..b0d8b7f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1103,6 +1103,10 @@
return Bool(c.productVariables.ProductCompatibleProperty)
}
+func (c *config) MissingUsesLibraries() []string {
+ return c.productVariables.MissingUsesLibraries
+}
+
func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
}
diff --git a/android/variable.go b/android/variable.go
index ff3ebaf..d039a16 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -306,6 +306,8 @@
ProductCompatibleProperty *bool `json:",omitempty"`
TargetFSConfigGen []string `json:",omitempty"`
+
+ MissingUsesLibraries []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index cb71725..24057af 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -529,7 +529,7 @@
ctx.file.errorf(ctx.mkvalue, "unsupported sanitize expression")
case *bpparser.String:
switch v.Value {
- case "never", "address", "coverage", "thread", "undefined", "cfi":
+ case "never", "address", "fuzzer", "thread", "undefined", "cfi":
bpTrue := &bpparser.Bool{
Value: true,
}
diff --git a/cc/cc.go b/cc/cc.go
index 4600a15..09496fc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,9 @@
ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
+ ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(fuzzer))
+ ctx.BottomUp("fuzzer", sanitizerMutator(fuzzer)).Parallel()
+
ctx.TopDown("cfi_deps", sanitizerDepsMutator(cfi))
ctx.BottomUp("cfi", sanitizerMutator(cfi)).Parallel()
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 4486d2e..fdda7be 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -77,6 +77,7 @@
intOverflow
cfi
scs
+ fuzzer
)
// Name of the sanitizer variation for this sanitizer type
@@ -94,6 +95,8 @@
return "cfi"
case scs:
return "scs"
+ case fuzzer:
+ return "fuzzer"
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -114,6 +117,8 @@
return "cfi"
case scs:
return "shadow-call-stack"
+ case fuzzer:
+ return "fuzzer"
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -133,7 +138,7 @@
Undefined *bool `android:"arch_variant"`
All_undefined *bool `android:"arch_variant"`
Misc_undefined []string `android:"arch_variant"`
- Coverage *bool `android:"arch_variant"`
+ Fuzzer *bool `android:"arch_variant"`
Safestack *bool `android:"arch_variant"`
Cfi *bool `android:"arch_variant"`
Integer_overflow *bool `android:"arch_variant"`
@@ -223,22 +228,16 @@
s.Undefined = boolPtr(true)
}
- if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
- if s.Address == nil {
- s.Address = boolPtr(true)
- } else if *s.Address == false {
- // Coverage w/o address is an error. If globalSanitizers includes both, and the module
- // disables address, then disable coverage as well.
- _, globalSanitizers = removeFromList("coverage", globalSanitizers)
- }
+ if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
+ s.Address = boolPtr(true)
}
if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
s.Thread = boolPtr(true)
}
- if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil {
- s.Coverage = boolPtr(true)
+ if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
+ s.Fuzzer = boolPtr(true)
}
if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
@@ -346,7 +345,7 @@
if ctx.staticBinary() {
s.Address = nil
- s.Coverage = nil
+ s.Fuzzer = nil
s.Thread = nil
}
@@ -362,7 +361,7 @@
}
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
- Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
+ Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
sanitize.Properties.SanitizerEnabled = true
}
@@ -377,10 +376,10 @@
s.Thread = nil
}
- if Bool(s.Coverage) {
- if !Bool(s.Address) {
- ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
- }
+ // TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
+ // mutually incompatible.
+ if Bool(s.Fuzzer) {
+ s.Cfi = nil
}
}
@@ -461,8 +460,13 @@
flags.CFlags = append(flags.CFlags, hwasanCflags...)
}
- if Bool(sanitize.Properties.Sanitize.Coverage) {
- flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
+ if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ flags.CFlags = append(flags.CFlags, "-fsanitize=fuzzer-no-link")
+ flags.LdFlags = append(flags.LdFlags, "-fsanitize=fuzzer-no-link")
+
+ // TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
+ _, flags.LdFlags = removeFromList("-flto", flags.LdFlags)
+ flags.LdFlags = append(flags.LdFlags, "-fno-lto")
}
if Bool(sanitize.Properties.Sanitize.Cfi) {
@@ -497,20 +501,26 @@
flags.CFlags = append(flags.CFlags, sanitizeArg)
flags.AsFlags = append(flags.AsFlags, sanitizeArg)
if ctx.Host() {
- flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
- flags.LdFlags = append(flags.LdFlags, sanitizeArg)
// Host sanitizers only link symbols in the final executable, so
// there will always be undefined symbols in intermediate libraries.
_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
+ flags.LdFlags = append(flags.LdFlags, sanitizeArg)
} else {
- flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
-
if enableMinimalRuntime(sanitize) {
flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
}
}
+
+ if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ // When fuzzing, we wish to crash with diagnostics on any bug.
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
+ } else if ctx.Host() {
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
+ } else {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
+ }
// http://b/119329758, Android core does not boot up with this sanitizer yet.
if toDisableImplicitIntegerChange(flags.CFlags) {
flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
@@ -573,6 +583,8 @@
return sanitize.Properties.Sanitize.Cfi
case scs:
return sanitize.Properties.Sanitize.Scs
+ case fuzzer:
+ return sanitize.Properties.Sanitize.Fuzzer
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -583,22 +595,21 @@
!sanitize.isSanitizerEnabled(hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
!sanitize.isSanitizerEnabled(cfi) &&
- !sanitize.isSanitizerEnabled(scs)
+ !sanitize.isSanitizerEnabled(scs) &&
+ !sanitize.isSanitizerEnabled(fuzzer)
}
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
return !sanitize.isSanitizerEnabled(asan) &&
!sanitize.isSanitizerEnabled(hwasan) &&
- !sanitize.isSanitizerEnabled(tsan)
+ !sanitize.isSanitizerEnabled(tsan) &&
+ !sanitize.isSanitizerEnabled(fuzzer)
}
func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
switch t {
case asan:
sanitize.Properties.Sanitize.Address = boolPtr(b)
- if !b {
- sanitize.Properties.Sanitize.Coverage = nil
- }
case hwasan:
sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
case tsan:
@@ -609,6 +620,8 @@
sanitize.Properties.Sanitize.Cfi = boolPtr(b)
case scs:
sanitize.Properties.Sanitize.Scs = boolPtr(b)
+ case fuzzer:
+ sanitize.Properties.Sanitize.Fuzzer = boolPtr(b)
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -793,6 +806,10 @@
sanitizers = append(sanitizers, "shadow-call-stack")
}
+ if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
+ sanitizers = append(sanitizers, "fuzzer-no-link")
+ }
+
// Save the list of sanitizers. These will be used again when generating
// the build rules (for Cflags, etc.)
c.sanitize.Properties.Sanitizers = sanitizers
@@ -931,6 +948,19 @@
modules[1].(*Module).Properties.HideFromMake = true
}
}
+ } else if t == fuzzer {
+ // TODO(b/131771163): CFI and fuzzer support are mutually incompatible
+ // as CFI pulls in LTO.
+ if mctx.Device() {
+ modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+ }
+ if isSanitizerEnabled {
+ modules[0].(*Module).Properties.PreventInstall = true
+ modules[0].(*Module).Properties.HideFromMake = true
+ } else {
+ modules[1].(*Module).Properties.PreventInstall = true
+ modules[1].(*Module).Properties.HideFromMake = true
+ }
} else if t == hwasan {
if mctx.Device() {
// CFI and HWASAN are currently mutually exclusive so disable
@@ -996,6 +1026,7 @@
func enableMinimalRuntime(sanitize *sanitize) bool {
if !Bool(sanitize.Properties.Sanitize.Address) &&
!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
+ !Bool(sanitize.Properties.Sanitize.Fuzzer) &&
(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index e11e33a..5a1bd74 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -65,8 +65,6 @@
AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
NeverOtherDebugInfo bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
- MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product
-
IsEng bool // build is a eng variant
SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
@@ -118,10 +116,10 @@
ProfileClassListing android.OptionalPath
ProfileIsTextListing bool
- EnforceUsesLibraries bool
- OptionalUsesLibraries []string
- UsesLibraries []string
- LibraryPaths map[string]android.Path
+ EnforceUsesLibraries bool
+ PresentOptionalUsesLibraries []string
+ UsesLibraries []string
+ LibraryPaths map[string]android.Path
Archs []android.ArchType
DexPreoptImages []android.Path
@@ -310,7 +308,6 @@
NeverSystemServerDebugInfo: false,
AlwaysOtherDebugInfo: false,
NeverOtherDebugInfo: false,
- MissingUsesLibraries: nil,
IsEng: false,
SanitizeLite: false,
DefaultAppImages: false,
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 2d521da..0be37d0 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -226,11 +226,6 @@
bootImageLocation = PathToLocation(bootImage, arch)
}
- // Lists of used and optional libraries from the build config, with optional libraries that are known to not
- // be present in the current product removed.
- var filteredUsesLibs []string
- var filteredOptionalUsesLibs []string
-
// The class loader context using paths in the build
var classLoaderContextHost android.Paths
@@ -248,11 +243,10 @@
var classLoaderContextHostString string
if module.EnforceUsesLibraries {
- filteredOptionalUsesLibs = filterOut(global.MissingUsesLibraries, module.OptionalUsesLibraries)
- filteredUsesLibs = append(copyOf(module.UsesLibraries), filteredOptionalUsesLibs...)
+ usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
// Create class loader context for dex2oat from uses libraries and filtered optional libraries
- for _, l := range filteredUsesLibs {
+ for _, l := range usesLibs {
classLoaderContextHost = append(classLoaderContextHost,
pathForLibrary(module, l))
@@ -267,7 +261,9 @@
// targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly depend on
// org.apache.http.legacy, then implicitly add the classes to the classpath for dexpreopt. One the
// device the classes will be in a file called org.apache.http.legacy.impl.jar.
- if !contains(module.UsesLibraries, httpLegacy) && !contains(module.OptionalUsesLibraries, httpLegacy) {
+ module.LibraryPaths[httpLegacyImpl] = module.LibraryPaths[httpLegacy]
+
+ if !contains(module.UsesLibraries, httpLegacy) && !contains(module.PresentOptionalUsesLibraries, httpLegacy) {
conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
pathForLibrary(module, httpLegacyImpl))
conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 6dfa9d2..0402f87 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -33,7 +33,7 @@
ProfileClassListing: android.OptionalPath{},
ProfileIsTextListing: false,
EnforceUsesLibraries: false,
- OptionalUsesLibraries: nil,
+ PresentOptionalUsesLibraries: nil,
UsesLibraries: nil,
LibraryPaths: nil,
Archs: []android.ArchType{android.Arm},
diff --git a/java/app.go b/java/app.go
index f7f08a8..2d817fe 100644
--- a/java/app.go
+++ b/java/app.go
@@ -17,12 +17,13 @@
// This file contains the module types for compiling Android apps.
import (
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
"path/filepath"
"reflect"
"strings"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/cc"
"android/soong/tradefed"
@@ -119,6 +120,8 @@
aapt
android.OverridableModuleBase
+ usesLibrary usesLibrary
+
certificate Certificate
appProperties appProperties
@@ -176,6 +179,8 @@
}
}
}
+
+ a.usesLibrary.deps(ctx, Bool(a.properties.No_framework_libs))
}
func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -276,6 +281,7 @@
aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
a.aapt.splitNames = a.appProperties.Package_splits
+ a.aapt.sdkLibraries = a.exportedSdkLibs
a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
@@ -308,9 +314,17 @@
} else {
installDir = filepath.Join("app", a.installApkName)
}
+
a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
a.dexpreopter.isInstallable = Bool(a.properties.Installable)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
+
+ a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+ a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
+ a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
+ a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+ a.dexpreopter.manifestFile = a.mergedManifestFile
+
a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
if ctx.ModuleName() != "framework-res" {
@@ -368,12 +382,19 @@
}
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
+ var apkDeps android.Paths
+
// Check if the install APK name needs to be overridden.
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
+ if a.usesLibrary.enforceUsesLibraries() {
+ manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
+ apkDeps = append(apkDeps, manifestCheckFile)
+ }
+
a.proguardBuildActions(ctx)
dexJarFile := a.dexBuildActions(ctx)
@@ -391,13 +412,13 @@
// Build a final signed app package.
// TODO(jungjw): Consider changing this to installApkName.
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
+ CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
a.outputFile = packageFile
for _, split := range a.aapt.splits {
// Sign the split APKs
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
}
@@ -483,7 +504,8 @@
&module.Module.protoProperties,
&module.aaptProperties,
&module.appProperties,
- &module.overridableAppProperties)
+ &module.overridableAppProperties,
+ &module.usesLibrary.usesLibraryProperties)
module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
return class == android.Device && ctx.Config().DevicePrefer32BitApps()
@@ -559,6 +581,7 @@
&module.appProperties,
&module.appTestProperties,
&module.overridableAppProperties,
+ &module.usesLibrary.usesLibraryProperties,
&module.testProperties)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
@@ -599,7 +622,8 @@
&module.aaptProperties,
&module.appProperties,
&module.appTestHelperAppProperties,
- &module.overridableAppProperties)
+ &module.overridableAppProperties,
+ &module.usesLibrary.usesLibraryProperties)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
@@ -666,6 +690,8 @@
certificate *Certificate
dexpreopter
+
+ usesLibrary usesLibrary
}
type AndroidAppImportProperties struct {
@@ -753,6 +779,8 @@
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+
+ a.usesLibrary.deps(ctx, false)
}
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
@@ -808,7 +836,12 @@
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
- srcApk := android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
+ var srcApk android.Path
+ srcApk = android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
+
+ if a.usesLibrary.enforceUsesLibraries() {
+ srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+ }
// TODO: Install or embed JNI libraries
@@ -821,6 +854,12 @@
a.dexpreopter.isInstallable = true
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
+
+ a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+ a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
+ a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
+ a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
if a.dexpreopter.uncompressedDex {
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
@@ -866,9 +905,129 @@
module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface()
module.AddProperties(&module.properties)
module.AddProperties(&module.dexpreoptProperties)
+ module.AddProperties(&module.usesLibrary.usesLibraryProperties)
InitJavaModule(module, android.DeviceSupported)
android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk)
return module
}
+
+type UsesLibraryProperties struct {
+ // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
+ Uses_libs []string
+
+ // A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
+ // required=false.
+ Optional_uses_libs []string
+
+ // If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults
+ // to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future.
+ Enforce_uses_libs *bool
+}
+
+// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
+// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
+// uses_libs and optional_uses_libs properties. The build system's values are used by dexpreopt to preopt apps
+// with knowledge of their shared libraries.
+type usesLibrary struct {
+ usesLibraryProperties UsesLibraryProperties
+}
+
+func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, noFrameworkLibs bool) {
+ ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
+ ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
+ if !noFrameworkLibs {
+ // dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs
+ // to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each
+ // library to dexpreopt.
+ ctx.AddVariationDependencies(nil, usesLibTag,
+ "org.apache.http.legacy",
+ "android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.0-java")
+ }
+}
+
+// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
+// build.
+func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
+ optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
+ return optionalUsesLibs
+}
+
+// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
+func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
+ usesLibPaths := make(map[string]android.Path)
+
+ if !ctx.Config().UnbundledBuild() {
+ ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
+ if lib, ok := m.(Dependency); ok {
+ if dexJar := lib.DexJar(); dexJar != nil {
+ usesLibPaths[ctx.OtherModuleName(m)] = dexJar
+ } else {
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
+ ctx.OtherModuleName(m))
+ }
+ } else if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
+ } else {
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
+ ctx.OtherModuleName(m))
+ }
+ })
+ }
+
+ return usesLibPaths
+}
+
+// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
+// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
+// unconditionally in the future.
+func (u *usesLibrary) enforceUsesLibraries() bool {
+ defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
+ len(u.usesLibraryProperties.Optional_uses_libs) > 0
+ return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
+}
+
+// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
+// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the manifest.
+func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
+ outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
+
+ rule := android.NewRuleBuilder()
+ cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")).
+ Flag("--enforce-uses-libraries").
+ Input(manifest).
+ FlagWithOutput("-o ", outputFile)
+
+ for _, lib := range u.usesLibraryProperties.Uses_libs {
+ cmd.FlagWithArg("--uses-library ", lib)
+ }
+
+ for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
+ cmd.FlagWithArg("--optional-uses-library ", lib)
+ }
+
+ rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
+
+ return outputFile
+}
+
+// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the ones specified
+// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the APK.
+func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
+ outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
+
+ rule := android.NewRuleBuilder()
+ aapt := ctx.Config().HostToolPath(ctx, "aapt")
+ rule.Command().
+ Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
+ Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
+ Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
+ Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
+ rule.Command().Text("cp -f").Input(apk).Output(outputFile)
+
+ rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
+
+ return outputFile
+}
diff --git a/java/app_builder.go b/java/app_builder.go
index 82a390f..348c8b4 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -31,7 +31,7 @@
var (
Signapk = pctx.AndroidStaticRule("signapk",
blueprint.RuleParams{
- Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
+ Command: `${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
`-jar $signapkCmd $flags $certificates $in $out`,
CommandDeps: []string{"$signapkCmd", "$signapkJniLibrary"},
},
@@ -63,7 +63,7 @@
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -78,9 +78,10 @@
}
ctx.Build(pctx, android.BuildParams{
- Rule: combineApk,
- Inputs: inputs,
- Output: unsignedApk,
+ Rule: combineApk,
+ Inputs: inputs,
+ Output: unsignedApk,
+ Implicits: deps,
})
SignAppPackage(ctx, outputFile, unsignedApk, certificates)
diff --git a/java/app_test.go b/java/app_test.go
index 40a64af..559afcc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1239,3 +1239,83 @@
})
}
}
+
+func TestUsesLibraries(t *testing.T) {
+ bp := `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java"],
+ api_packages: ["bar"],
+ }
+
+ android_app {
+ name: "app",
+ srcs: ["a.java"],
+ uses_libs: ["foo"],
+ optional_uses_libs: [
+ "bar",
+ "baz",
+ ],
+ }
+
+ android_app_import {
+ name: "prebuilt",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ uses_libs: ["foo"],
+ optional_uses_libs: [
+ "bar",
+ "baz",
+ ],
+ }
+ `
+
+ config := testConfig(nil)
+ config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
+
+ ctx := testAppContext(config, bp, nil)
+
+ run(t, ctx, config)
+
+ app := ctx.ModuleForTests("app", "android_common")
+ prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
+
+ // Test that all libraries are verified
+ cmd := app.Rule("verify_uses_libraries").RuleParams.Command
+ if w := "--uses-library foo"; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
+
+ if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ // Test that only present libraries are preopted
+ cmd = app.Rule("dexpreopt").RuleParams.Command
+
+ if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+
+ cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
+
+ if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
+ t.Errorf("wanted %q in %q", w, cmd)
+ }
+}
diff --git a/java/builder.go b/java/builder.go
index d257d1d..e1a912b 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -43,7 +43,8 @@
Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
- `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
+ `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ` +
+ `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
@@ -64,7 +65,7 @@
turbine = pctx.AndroidStaticRule("turbine",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` +
+ `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
`--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` +
`--javacopts ${config.CommonJdkFlags} ` +
`$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` +
@@ -108,7 +109,7 @@
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
- Command: "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out",
+ Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JarjarCmd} process $rulesFile $in $out",
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
"rulesFile")
@@ -124,7 +125,7 @@
jetifier = pctx.AndroidStaticRule("jetifier",
blueprint.RuleParams{
- Command: "${config.JavaCmd} -jar ${config.JetifierJar} -l error -o $out -i $in",
+ Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JetifierJar} -l error -o $out -i $in",
CommandDeps: []string{"${config.JavaCmd}", "${config.JetifierJar}"},
},
)
diff --git a/java/config/config.go b/java/config/config.go
index f9552d5..529f1e6 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -69,6 +69,8 @@
// b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
`-XDstringConcat=inline`,
}, " "))
+ pctx.StaticVariable("JavaVmFlags", "-XX:OnError=\"cat hs_err_pid%p.log\"")
+ pctx.StaticVariable("JavacVmFlags", "-J-XX:OnError=\"cat hs_err_pid%p.log\"")
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 9c78511..ead298a 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -39,8 +39,8 @@
ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
- ctx.Strict("JAVA", "${JavaCmd}")
- ctx.Strict("JAVAC", "${JavacCmd}")
+ ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}")
+ ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}")
ctx.Strict("JAR", "${JarCmd}")
ctx.Strict("JAR_ARGS", "${JarArgsCmd}")
ctx.Strict("JAVADOC", "${JavadocCmd}")
@@ -58,8 +58,8 @@
ctx.Strict("ERROR_PRONE_CHECKS", "${ErrorProneChecks}")
}
- ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
- ctx.Strict("HOST_JAVAC", "${JavacCmd} ${CommonJdkFlags}")
+ ctx.Strict("TARGET_JAVAC", "${JavacCmd} ${JavacVmFlags} ${CommonJdkFlags}")
+ ctx.Strict("HOST_JAVAC", "${JavacCmd} ${JavacVmFlags} ${CommonJdkFlags}")
ctx.Strict("JLINK", "${JlinkCmd}")
ctx.Strict("JMOD", "${JmodCmd}")
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 08fd06e..23d2aa6 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -29,6 +29,12 @@
isInstallable bool
isPresignedPrebuilt bool
+ manifestFile android.Path
+ usesLibs []string
+ optionalUsesLibs []string
+ enforceUsesLibs bool
+ libraryPaths map[string]android.Path
+
builtInstalled string
}
@@ -154,6 +160,7 @@
DexLocation: dexLocation,
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
DexPath: dexJarFile,
+ ManifestPath: d.manifestFile,
UncompressedDex: d.uncompressedDex,
HasApkLibraries: false,
PreoptFlags: nil,
@@ -161,10 +168,10 @@
ProfileClassListing: profileClassListing,
ProfileIsTextListing: profileIsTextListing,
- EnforceUsesLibraries: false,
- OptionalUsesLibraries: nil,
- UsesLibraries: nil,
- LibraryPaths: nil,
+ EnforceUsesLibraries: d.enforceUsesLibs,
+ PresentOptionalUsesLibraries: d.optionalUsesLibs,
+ UsesLibraries: d.usesLibs,
+ LibraryPaths: d.libraryPaths,
Archs: archs,
DexPreoptImages: images,
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 57da6b6..b41825e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -73,7 +73,7 @@
Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` +
`mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
- `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
+ `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
`$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` +
`$opts && ` +
`${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` +
@@ -95,7 +95,7 @@
blueprint.RuleParams{
Command: `( rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
- `${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
+ `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
`$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` +
`$opts && touch $out && rm -rf "$srcJarDir") || ` +
`( echo -e "$msg" ; exit 38 )`,
@@ -120,7 +120,7 @@
Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` +
`mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
- `${config.JavaCmd} -jar ${config.DokkaJar} $srcJarDir ` +
+ `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.DokkaJar} $srcJarDir ` +
`$classpathArgs -format dac -dacRoot /reference/kotlin -output $outDir $opts && ` +
`${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
`${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` +
diff --git a/java/jacoco.go b/java/jacoco.go
index 8b6d4ac..bce9822 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -31,7 +31,7 @@
jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{
Command: `rm -rf $tmpDir && mkdir -p $tmpDir && ` +
`${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
- `${config.JavaCmd} -jar ${config.JacocoCLIJar} ` +
+ `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JacocoCLIJar} ` +
` instrument --quiet --dest $tmpDir $strippedJar && ` +
`${config.Ziptime} $tmpJar && ` +
`${config.MergeZipsCmd} --ignore-duplicates -j $out $tmpJar $in`,
diff --git a/java/java.go b/java/java.go
index 8dbdfb6..84518a1 100644
--- a/java/java.go
+++ b/java/java.go
@@ -420,6 +420,7 @@
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
+ usesLibTag = dependencyTag{name: "uses-library"}
)
type sdkDep struct {
diff --git a/java/java_test.go b/java/java_test.go
index 50b1c34..3a7ed4e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -174,6 +174,8 @@
"build/soong/scripts/jar-wrapper.sh": nil,
+ "build/make/core/verify_uses_libraries.sh": nil,
+
"build/make/core/proguard.flags": nil,
"build/make/core/proguard_basic_keeps.flags": nil,
diff --git a/java/testing.go b/java/testing.go
index 22831c9..fc7842d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -77,6 +77,33 @@
name: "framework-res",
no_framework_libs: true,
}
+
+ java_library {
+ name: "android.hidl.base-V1.0-java",
+ srcs: ["a.java"],
+ no_standard_libs: true,
+ sdk_version: "core_current",
+ system_modules: "core-platform-api-stubs-system-modules",
+ installable: true,
+ }
+
+ java_library {
+ name: "android.hidl.manager-V1.0-java",
+ srcs: ["a.java"],
+ no_standard_libs: true,
+ sdk_version: "core_current",
+ system_modules: "core-platform-api-stubs-system-modules",
+ installable: true,
+ }
+
+ java_library {
+ name: "org.apache.http.legacy",
+ srcs: ["a.java"],
+ no_standard_libs: true,
+ sdk_version: "core_current",
+ system_modules: "core-platform-api-stubs-system-modules",
+ installable: true,
+ }
`
systemModules := []string{