Merge "Add support for nullability validation to droidstubs."
diff --git a/android/config.go b/android/config.go
index 3b7b477..695a298 100644
--- a/android/config.go
+++ b/android/config.go
@@ -708,6 +708,22 @@
return Bool(c.productVariables.HostStaticBinaries)
}
+func (c *config) UncompressPrivAppDex() bool {
+ return Bool(c.productVariables.UncompressPrivAppDex)
+}
+
+func (c *config) ModulesLoadedByPrivilegedModules() []string {
+ return c.productVariables.ModulesLoadedByPrivilegedModules
+}
+
+func (c *config) DefaultStripDex() bool {
+ return Bool(c.productVariables.DefaultStripDex)
+}
+
+func (c *config) DisableDexPreopt(name string) bool {
+ return Bool(c.productVariables.DisableDexPreopt) || InList(name, c.productVariables.DisableDexPreoptModules)
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
diff --git a/android/neverallow.go b/android/neverallow.go
index d3a2801..f6caebc 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -45,35 +45,85 @@
ctx.BottomUp("neverallow", neverallowMutator).Parallel()
}
-var neverallows = []*rule{
- neverallow().
- in("vendor", "device").
- with("vndk.enabled", "true").
- without("vendor", "true").
- because("the VNDK can never contain a library that is device dependent."),
- neverallow().
- with("vndk.enabled", "true").
- without("vendor", "true").
- without("owner", "").
- because("a VNDK module can never have an owner."),
- neverallow().
- notIn("libcore", "development", "external/apache-harmony", "external/apache-xml", "external/bouncycastle", "external/conscrypt", "external/icu", "external/okhttp", "external/wycheproof").
- with("no_standard_libs", "true"),
+var neverallows = createNeverAllows()
- // TODO(b/67974785): always enforce the manifest
- neverallow().
- without("name", "libhidltransport").
- with("product_variables.enforce_vintf_manifest.cflags", "*").
- because("manifest enforcement should be independent of ."),
+func createNeverAllows() []*rule {
+ rules := []*rule{}
+ rules = append(rules, createTrebleRules()...)
+ rules = append(rules, createLibcoreRules()...)
+ return rules
+}
- // TODO(b/67975799): vendor code should always use /vendor/bin/sh
- neverallow().
- without("name", "libc_bionic_ndk").
- with("product_variables.treble_linker_namespaces.cflags", "*").
- because("nothing should care if linker namespaces are enabled or not"),
+func createTrebleRules() []*rule {
+ return []*rule{
+ neverallow().
+ in("vendor", "device").
+ with("vndk.enabled", "true").
+ without("vendor", "true").
+ because("the VNDK can never contain a library that is device dependent."),
+ neverallow().
+ with("vndk.enabled", "true").
+ without("vendor", "true").
+ without("owner", "").
+ because("a VNDK module can never have an owner."),
- // Example:
- // *neverallow().with("Srcs", "main.cpp"),
+ // TODO(b/67974785): always enforce the manifest
+ neverallow().
+ without("name", "libhidltransport").
+ with("product_variables.enforce_vintf_manifest.cflags", "*").
+ because("manifest enforcement should be independent of ."),
+
+ // TODO(b/67975799): vendor code should always use /vendor/bin/sh
+ neverallow().
+ without("name", "libc_bionic_ndk").
+ with("product_variables.treble_linker_namespaces.cflags", "*").
+ because("nothing should care if linker namespaces are enabled or not"),
+
+ // Example:
+ // *neverallow().with("Srcs", "main.cpp"))
+ }
+}
+
+func createLibcoreRules() []*rule {
+ var coreLibraryProjects = []string{
+ "libcore",
+ "external/apache-harmony",
+ "external/apache-xml",
+ "external/bouncycastle",
+ "external/conscrypt",
+ "external/icu",
+ "external/okhttp",
+ "external/wycheproof",
+ }
+
+ var coreModules = []string{
+ "core-all",
+ "core-oj",
+ "core-libart",
+ "core-simple",
+ "okhttp",
+ "bouncycastle",
+ "conscrypt",
+ "apache-xml",
+ }
+
+ // Core library constraints. Prevent targets adding dependencies on core
+ // library internals, which could lead to compatibility issues with the ART
+ // mainline module. They should use core.platform.api.stubs instead.
+ rules := []*rule{
+ neverallow().
+ notIn(append(coreLibraryProjects, "development")...).
+ with("no_standard_libs", "true"),
+ }
+
+ for _, m := range coreModules {
+ r := neverallow().
+ notIn(coreLibraryProjects...).
+ with("libs", m).
+ because("Only core libraries projects can depend on " + m)
+ rules = append(rules, r)
+ }
+ return rules
}
func neverallowMutator(ctx BottomUpMutatorContext) {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index a278365..9e4886c 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -137,6 +137,17 @@
},
expectedError: "",
},
+ {
+ name: "dependency on core-libart",
+ fs: map[string][]byte{
+ "Blueprints": []byte(`
+ java_library {
+ name: "needs_core_libart",
+ libs: ["core-libart"],
+ }`),
+ },
+ expectedError: "Only core libraries projects can depend on core-libart",
+ },
}
func TestNeverallow(t *testing.T) {
@@ -164,6 +175,7 @@
func testNeverallow(t *testing.T, config Config, fs map[string][]byte) (*TestContext, []error) {
ctx := NewTestContext()
ctx.RegisterModuleType("cc_library", ModuleFactoryAdaptor(newMockCcLibraryModule))
+ ctx.RegisterModuleType("java_library", ModuleFactoryAdaptor(newMockJavaLibraryModule))
ctx.PostDepsMutators(registerNeverallowMutator)
ctx.Register()
@@ -178,7 +190,7 @@
return ctx, errs
}
-type mockProperties struct {
+type mockCcLibraryProperties struct {
Vendor_available *bool
Vndk struct {
@@ -200,7 +212,7 @@
type mockCcLibraryModule struct {
ModuleBase
- properties mockProperties
+ properties mockCcLibraryProperties
}
func newMockCcLibraryModule() Module {
@@ -215,3 +227,25 @@
func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}
+
+type mockJavaLibraryProperties struct {
+ Libs []string
+}
+
+type mockJavaLibraryModule struct {
+ ModuleBase
+ properties mockJavaLibraryProperties
+}
+
+func newMockJavaLibraryModule() Module {
+ m := &mockJavaLibraryModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidModule(m)
+ return m
+}
+
+func (p *mockJavaLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
+}
+
+func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/variable.go b/android/variable.go
index 2eb9900..f2ba89b 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -190,6 +190,12 @@
Arc *bool `json:",omitempty"`
MinimizeJavaDebugInfo *bool `json:",omitempty"`
+ UncompressPrivAppDex *bool `json:",omitempty"`
+ ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
+ DefaultStripDex *bool `json:",omitempty"`
+ DisableDexPreopt *bool `json:",omitempty"`
+ DisableDexPreoptModules []string `json:",omitempty"`
+
IntegerOverflowExcludePaths *[]string `json:",omitempty"`
EnableCFI *bool `json:",omitempty"`
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 5c82604..bbc78fa 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -86,7 +86,6 @@
// Ldflags that should be filtered out when linking with clang lld
var ClangUnknownLldflags = sorted([]string{
"-fuse-ld=gold",
- "-Wl,--icf=safe",
"-Wl,--fix-cortex-a8",
"-Wl,--no-fix-cortex-a8",
"-Wl,-m,aarch64_elf64_le_vec",
diff --git a/cc/config/global.go b/cc/config/global.go
index 330cb10..3e76373 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -91,7 +91,8 @@
// TODO(b/109657296): needs --no-rosegment until Android
// stack unwinder can handle the read-only segment.
"-Wl,--no-rosegment",
- "-Wl,--pack-dyn-relocs=android",
+ "-Wl,--pack-dyn-relocs=android+relr",
+ "-Wl,--use-android-relr-tags",
"-fuse-ld=lld",
}...)
diff --git a/cc/object.go b/cc/object.go
index 0010621..552f639 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -39,6 +39,10 @@
baseLinker: NewBaseLinker(nil),
}
module.compiler = NewBaseCompiler()
+
+ // Clang's address-significance tables are incompatible with ld -r.
+ module.compiler.appendCflags([]string{"-fno-addrsig"})
+
module.stl = &stl{}
return module.Init()
}
diff --git a/java/app.go b/java/app.go
index 5d25dcf..d1b04c3 100644
--- a/java/app.go
+++ b/java/app.go
@@ -67,7 +67,9 @@
// list of native libraries that will be provided in or alongside the resulting jar
Jni_libs []string `android:"arch_variant"`
- EmbedJNI bool `blueprint:"mutated"`
+ AllowDexPreopt bool `blueprint:"mutated"`
+ EmbedJNI bool `blueprint:"mutated"`
+ StripDex bool `blueprint:"mutated"`
}
type AndroidApp struct {
@@ -139,6 +141,42 @@
a.generateAndroidBuildActions(ctx)
}
+// Returns whether this module should have the dex file stored uncompressed in the APK, or stripped completely. If
+// stripped, the code will still be present on the device in the dexpreopted files.
+// This is only necessary for APKs, and not jars, because APKs are signed and the dex file should not be uncompressed
+// or removed after the signature has been generated. For jars, which are not signed, the dex file is uncompressed
+// or removed at installation time in Make.
+func (a *AndroidApp) uncompressOrStripDex(ctx android.ModuleContext) (uncompress, strip bool) {
+ if ctx.Config().UnbundledBuild() {
+ return false, false
+ }
+
+ strip = ctx.Config().DefaultStripDex()
+ // TODO(ccross): don't strip dex installed on partitions that may be updated separately (like vendor)
+ // TODO(ccross): don't strip dex on modules with LOCAL_APK_LIBRARIES equivalent
+ // TODO(ccross): don't strip dex on modules that are preopted to system_other
+
+ // Uncompress dex in APKs of privileged apps, and modules used by privileged apps.
+ if ctx.Config().UncompressPrivAppDex() &&
+ (Bool(a.appProperties.Privileged) ||
+ inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules())) {
+
+ uncompress = true
+ // If the dex files is store uncompressed, don't strip it, we will reuse the uncompressed dex from the APK
+ // instead of copying it into the odex file.
+ strip = false
+ }
+
+ // If dexpreopt is disabled, don't strip the dex file
+ if !a.appProperties.AllowDexPreopt ||
+ !BoolDefault(a.deviceProperties.Dex_preopt.Enabled, true) ||
+ ctx.Config().DisableDexPreopt(ctx.ModuleName()) {
+ strip = false
+ }
+
+ return uncompress, strip
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
linkFlags := append([]string(nil), a.extraLinkFlags...)
@@ -184,11 +222,16 @@
a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
+ a.deviceProperties.UncompressDex, a.appProperties.StripDex = a.uncompressOrStripDex(ctx)
+
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
}
+ dexJarFile := a.dexJarFile
- packageFile := android.PathForModuleOut(ctx, "package.apk")
+ if a.appProperties.StripDex {
+ dexJarFile = nil
+ }
var certificates []certificate
@@ -226,8 +269,8 @@
certificates = append([]certificate{a.certificate}, certificateDeps...)
- CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, a.outputFile, certificates)
-
+ packageFile := android.PathForModuleOut(ctx, "package.apk")
+ CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
a.outputFile = packageFile
if ctx.ModuleName() == "framework-res" {
@@ -284,6 +327,7 @@
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.appProperties.AllowDexPreopt = true
module.AddProperties(
&module.Module.properties,
@@ -345,6 +389,7 @@
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
module.appProperties.EmbedJNI = true
+ module.appProperties.AllowDexPreopt = false
module.AddProperties(
&module.Module.properties,
@@ -379,6 +424,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
module.appProperties.EmbedJNI = true
+ module.appProperties.AllowDexPreopt = false
module.AddProperties(
&module.Module.properties,
diff --git a/java/app_builder.go b/java/app_builder.go
index b9b5f43..7577444 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -87,9 +87,6 @@
certificateArgs = append(certificateArgs, c.pem.String(), c.key.String())
}
- // TODO(ccross): sometimes uncompress dex
- // TODO(ccross): sometimes strip dex
-
ctx.Build(pctx, android.BuildParams{
Rule: signapk,
Description: "signapk",
diff --git a/java/dex.go b/java/dex.go
index 625fb83..5cec325 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -26,7 +26,7 @@
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`${config.D8Cmd} --output $outDir $d8Flags $in && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.D8Cmd}",
@@ -34,7 +34,7 @@
"${config.MergeZipsCmd}",
},
},
- "outDir", "d8Flags")
+ "outDir", "d8Flags", "zipFlags")
var r8 = pctx.AndroidStaticRule("r8",
blueprint.RuleParams{
@@ -46,7 +46,7 @@
`-printmapping $outDict ` +
`$r8Flags && ` +
`touch "$outDict" && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.R8Cmd}",
@@ -54,7 +54,7 @@
"${config.MergeZipsCmd}",
},
},
- "outDir", "outDict", "r8Flags")
+ "outDir", "outDict", "r8Flags", "zipFlags")
func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
flags := j.deviceProperties.Dxflags
@@ -172,6 +172,11 @@
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
outDir := android.PathForModuleOut(ctx, "dex")
+ zipFlags := ""
+ if j.deviceProperties.UncompressDex {
+ zipFlags = "-L 0"
+ }
+
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
j.proguardDictionary = proguardDictionary
@@ -184,9 +189,10 @@
Input: classesJar,
Implicits: r8Deps,
Args: map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
- "outDict": j.proguardDictionary.String(),
- "outDir": outDir.String(),
+ "r8Flags": strings.Join(r8Flags, " "),
+ "zipFlags": zipFlags,
+ "outDict": j.proguardDictionary.String(),
+ "outDir": outDir.String(),
},
})
} else {
@@ -198,8 +204,9 @@
Input: classesJar,
Implicits: d8Deps,
Args: map[string]string{
- "d8Flags": strings.Join(d8Flags, " "),
- "outDir": outDir.String(),
+ "d8Flags": strings.Join(d8Flags, " "),
+ "zipFlags": zipFlags,
+ "outDir": outDir.String(),
},
})
}
diff --git a/java/java.go b/java/java.go
index f651884..0f95479 100644
--- a/java/java.go
+++ b/java/java.go
@@ -257,6 +257,8 @@
// When targeting 1.9, override the modules to use with --system
System_modules *string
+
+ UncompressDex bool `blueprint:"mutated"`
}
// Module contains the properties and members used by all java module types
@@ -432,7 +434,7 @@
func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
switch v {
- case "", "current", "system_current", "test_current", "core_current", "core_platform_current":
+ case "", "current", "system_current", "test_current", "core_current":
return ctx.Config().DefaultAppTargetSdk()
default:
return v
@@ -443,7 +445,7 @@
// it returns android.FutureApiLevel (10000).
func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
switch v {
- case "", "current", "test_current", "system_current", "core_current", "core_platform_current":
+ case "", "current", "test_current", "system_current", "core_current":
return ctx.Config().DefaultAppTargetSdkInt(), nil
default:
n := android.GetNumericSdkVersion(v)
@@ -564,8 +566,6 @@
return toModule("android_test_stubs_current", "framework-res")
case "core_current":
return toModule("core.current.stubs", "")
- case "core_platform_current":
- return toModule("core.platform.api.stubs", "")
default:
return toPrebuilt(v)
}
@@ -732,7 +732,7 @@
name == "stub-annotations" || name == "private-stub-annotations-jar" ||
name == "core-lambda-stubs":
return javaCore, true
- case ver == "core_current" || ver == "core_platform_current":
+ case ver == "core_current":
return javaCore, false
case name == "android_system_stubs_current":
return javaSystem, true