Merge "Fix override for native_bridge modules"
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 6809914..ea5316c 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1,10 +1,11 @@
package android
import (
- "github.com/google/blueprint"
"io/ioutil"
"os"
"testing"
+
+ "github.com/google/blueprint"
)
var visibilityTests = []struct {
@@ -198,10 +199,17 @@
name: "libnested",
deps: ["libexample"],
}`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
},
expectedErrors: []string{
`module "libnested" variant "android_common": depends on //top:libexample which is not` +
` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+ `module "libother" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
},
},
{
@@ -223,10 +231,17 @@
name: "libnested",
deps: ["libexample"],
}`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
},
expectedErrors: []string{
`module "libnested" variant "android_common": depends on //top:libexample which is not` +
` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+ `module "libother" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
},
},
{
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index b54ad5e..a23879f 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -936,6 +936,7 @@
"STATIC_LIBRARIES": "cc_prebuilt_library_static",
"EXECUTABLES": "cc_prebuilt_binary",
"JAVA_LIBRARIES": "java_import",
+ "APPS": "android_app_import",
"ETC": "prebuilt_etc",
}
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 3ec5f2e..b3b1ce0 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -1235,6 +1235,32 @@
}
`,
},
+ {
+ desc: "android_app_import",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_SRC_FILES := foo.apk
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MODULE_CLASS := APPS
+LOCAL_MODULE_TAGS := optional
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PREBUILT)
+`,
+ expected: `
+android_app_import {
+ name: "foo",
+
+ privileged: true,
+
+ dex_preopt: {
+ enabled: false,
+ },
+ apk: "foo.apk",
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index c898196..17cff18 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -102,6 +102,10 @@
name: "rewriteAndroidTest",
fix: rewriteAndroidTest,
},
+ {
+ name: "rewriteAndroidAppImport",
+ fix: rewriteAndroidAppImport,
+ },
}
func NewFixRequest() FixRequest {
@@ -525,27 +529,8 @@
continue
}
- // The rewriter converts LOCAL_SRC_FILES to `srcs` attribute. Convert
- // it to 'src' attribute (which is where the file is installed). If the
- // value 'srcs' is a list, we can convert it only if it contains a single
- // element.
- if srcs, ok := mod.GetProperty("srcs"); ok {
- if srcList, ok := srcs.Value.(*parser.List); ok {
- removeProperty(mod, "srcs")
- if len(srcList.Values) == 1 {
- mod.Properties = append(mod.Properties,
- &parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcList.Values[0])})
- } else if len(srcList.Values) > 1 {
- indicateAttributeError(mod, "src", "LOCAL_SRC_FILES should contain at most one item")
- }
- } else if _, ok = srcs.Value.(*parser.Variable); ok {
- removeProperty(mod, "srcs")
- mod.Properties = append(mod.Properties,
- &parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcs.Value)})
- } else {
- renameProperty(mod, "srcs", "src")
- }
- }
+ // 'srcs' --> 'src' conversion
+ convertToSingleSource(mod, "src")
// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
// 'local_module_path'. Analyze its contents and create the correct sub_dir:,
@@ -603,6 +588,62 @@
return nil
}
+func rewriteAndroidAppImport(f *Fixer) error {
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !(ok && mod.Type == "android_app_import") {
+ continue
+ }
+ // 'srcs' --> 'apk' conversion
+ convertToSingleSource(mod, "apk")
+ // Handle special certificate value, "PRESIGNED".
+ if cert, ok := mod.GetProperty("certificate"); ok {
+ if certStr, ok := cert.Value.(*parser.String); ok {
+ if certStr.Value == "PRESIGNED" {
+ removeProperty(mod, "certificate")
+ prop := &parser.Property{
+ Name: "presigned",
+ Value: &parser.Bool{
+ Value: true,
+ },
+ }
+ mod.Properties = append(mod.Properties, prop)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Converts the default source list property, 'srcs', to a single source property with a given name.
+// "LOCAL_MODULE" reference is also resolved during the conversion process.
+func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
+ if srcs, ok := mod.GetProperty("srcs"); ok {
+ if srcList, ok := srcs.Value.(*parser.List); ok {
+ removeProperty(mod, "srcs")
+ if len(srcList.Values) == 1 {
+ mod.Properties = append(mod.Properties,
+ &parser.Property{
+ Name: srcPropertyName,
+ NamePos: srcs.NamePos,
+ ColonPos: srcs.ColonPos,
+ Value: resolveLocalModule(mod, srcList.Values[0])})
+ } else if len(srcList.Values) > 1 {
+ indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item")
+ }
+ } else if _, ok = srcs.Value.(*parser.Variable); ok {
+ removeProperty(mod, "srcs")
+ mod.Properties = append(mod.Properties,
+ &parser.Property{Name: srcPropertyName,
+ NamePos: srcs.NamePos,
+ ColonPos: srcs.ColonPos,
+ Value: resolveLocalModule(mod, srcs.Value)})
+ } else {
+ renameProperty(mod, "srcs", "apk")
+ }
+ }
+}
+
func runPatchListMod(modFunc func(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error) func(*Fixer) error {
return func(f *Fixer) error {
// Make sure all the offsets are accurate
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 459cd36..5e0b817 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -784,3 +784,52 @@
})
}
}
+
+func TestRewriteAndroidAppImport(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "android_app_import apk",
+ in: `
+ android_app_import {
+ name: "foo",
+ srcs: ["package.apk"],
+ }
+ `,
+ out: `
+ android_app_import {
+ name: "foo",
+ apk: "package.apk",
+ }
+ `,
+ },
+ {
+ name: "android_app_import presigned",
+ in: `
+ android_app_import {
+ name: "foo",
+ apk: "package.apk",
+ certificate: "PRESIGNED",
+ }
+ `,
+ out: `
+ android_app_import {
+ name: "foo",
+ apk: "package.apk",
+ presigned: true,
+
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPass(t, test.in, test.out, func(fixer *Fixer) error {
+ return rewriteAndroidAppImport(fixer)
+ })
+ })
+ }
+}
diff --git a/cc/builder.go b/cc/builder.go
index 5fa0fad..7cf5c29 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -124,11 +124,11 @@
_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
- // file descriptors on darwin. Limit concurrent calls to 10 on darwin.
+ // file descriptors on darwin. Limit concurrent calls to 5 on darwin.
darwinStripPool = func() blueprint.Pool {
if runtime.GOOS == "darwin" {
return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{
- Depth: 10,
+ Depth: 5,
})
} else {
return nil
diff --git a/cc/cc.go b/cc/cc.go
index 6c26b52..2e551e1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -919,7 +919,7 @@
}
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
- c.makeLinkType = c.getMakeLinkType(actx.Config())
+ c.makeLinkType = c.getMakeLinkType(actx)
ctx := &moduleContext{
ModuleContext: actx,
@@ -1940,19 +1940,22 @@
return false
}
-func (c *Module) getMakeLinkType(config android.Config) string {
+func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
+ name := actx.ModuleName()
if c.useVndk() {
- if inList(c.Name(), *vndkCoreLibraries(config)) ||
- inList(c.Name(), *vndkSpLibraries(config)) ||
- inList(c.Name(), *llndkLibraries(config)) {
- if inList(c.Name(), *vndkPrivateLibraries(config)) {
- return "native:vndk_private"
- } else {
+ if lib, ok := c.linker.(*llndkStubDecorator); ok {
+ if Bool(lib.Properties.Vendor_available) {
return "native:vndk"
}
- } else {
- return "native:vendor"
+ return "native:vndk_private"
}
+ if c.isVndk() && !c.isVndkExt() {
+ if Bool(c.VendorProperties.Vendor_available) {
+ return "native:vndk"
+ }
+ return "native:vndk_private"
+ }
+ return "native:vendor"
} else if c.inRecovery() {
return "native:recovery"
} else if c.Target().Os == android.Android && String(c.Properties.Sdk_version) != "" {
@@ -1960,7 +1963,7 @@
// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
//family, link := getNdkStlFamilyAndLinkType(c)
//return fmt.Sprintf("native:ndk:%s:%s", family, link)
- } else if inList(c.Name(), *vndkUsingCoreVariantLibraries(config)) {
+ } else if inList(name, *vndkUsingCoreVariantLibraries(actx.Config())) {
return "native:platform_vndk"
} else {
return "native:platform"
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f5bb12c..997e11e 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1263,6 +1263,110 @@
`)
}
+func TestMakeLinkType(t *testing.T) {
+ config := android.TestArchConfig(buildDir, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ // native:vndk
+ ctx := testCcWithConfig(t, `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ }
+ cc_library {
+ name: "libvndksp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ }
+ cc_library {
+ name: "libvndkprivate",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ }
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ }
+ cc_library {
+ name: "libvndkext",
+ vendor: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ }
+ vndk_prebuilt_shared {
+ name: "prevndk",
+ version: "27",
+ target_arch: "arm",
+ binder32bit: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["liba.so"],
+ },
+ },
+ }
+ cc_library {
+ name: "libllndk",
+ }
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libllndkprivate",
+ }
+ llndk_library {
+ name: "libllndkprivate",
+ vendor_available: false,
+ symbol_file: "",
+ }`, config)
+
+ assertArrayString(t, *vndkCoreLibraries(config),
+ []string{"libvndk", "libvndkprivate"})
+ assertArrayString(t, *vndkSpLibraries(config),
+ []string{"libc++", "libvndksp"})
+ assertArrayString(t, *llndkLibraries(config),
+ []string{"libc", "libdl", "libllndk", "libllndkprivate", "libm"})
+ assertArrayString(t, *vndkPrivateLibraries(config),
+ []string{"libllndkprivate", "libvndkprivate"})
+
+ tests := []struct {
+ variant string
+ name string
+ expected string
+ }{
+ {vendorVariant, "libvndk", "native:vndk"},
+ {vendorVariant, "libvndksp", "native:vndk"},
+ {vendorVariant, "libvndkprivate", "native:vndk_private"},
+ {vendorVariant, "libvendor", "native:vendor"},
+ {vendorVariant, "libvndkext", "native:vendor"},
+ {vendorVariant, "prevndk.vndk.27.arm.binder32", "native:vndk"},
+ {vendorVariant, "libllndk.llndk", "native:vndk"},
+ {coreVariant, "libvndk", "native:platform"},
+ {coreVariant, "libvndkprivate", "native:platform"},
+ {coreVariant, "libllndk", "native:platform"},
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ module := ctx.ModuleForTests(test.name, test.variant).Module().(*Module)
+ assertString(t, module.makeLinkType, test.expected)
+ })
+ }
+}
+
var (
str11 = "01234567891"
str10 = str11[:10]
@@ -2159,3 +2263,25 @@
)
}
}
+
+func assertString(t *testing.T, got, expected string) {
+ t.Helper()
+ if got != expected {
+ t.Errorf("expected %q got %q", expected, got)
+ }
+}
+
+func assertArrayString(t *testing.T, got, expected []string) {
+ t.Helper()
+ if len(got) != len(expected) {
+ t.Errorf("expected %d (%q) got (%d) %q", len(expected), expected, len(got), got)
+ return
+ }
+ for i := range got {
+ if got[i] != expected[i] {
+ t.Errorf("expected %d-th %q (%q) got %q (%q)",
+ i, expected[i], expected, got[i], got)
+ return
+ }
+ }
+}
diff --git a/cc/testing.go b/cc/testing.go
index 259fb19..d9be900 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -207,6 +207,7 @@
ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
+ ctx.RegisterModuleType("vndk_prebuilt_shared", android.ModuleFactoryAdaptor(vndkPrebuiltSharedFactory))
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("image", ImageMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
diff --git a/java/app.go b/java/app.go
index 9f37836..f7f08a8 100644
--- a/java/app.go
+++ b/java/app.go
@@ -85,6 +85,9 @@
// list of native libraries that will be provided in or alongside the resulting jar
Jni_libs []string `android:"arch_variant"`
+ // STL library to use for JNI libraries.
+ Stl *string `android:"arch_variant"`
+
// Store native libraries uncompressed in the APK and set the android:extractNativeLibs="false" manifest
// flag so that they are used from inside the APK at runtime. Defaults to true for android_test modules unless
// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
@@ -149,10 +152,15 @@
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
+ if String(a.appProperties.Stl) == "c++_shared" && a.sdkVersion() == "" {
+ ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
+ }
+
if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
a.aapt.deps(ctx, sdkContext(a))
}
+ embedJni := a.shouldEmbedJnis(ctx)
for _, jniTarget := range ctx.MultiTargets() {
variation := []blueprint.Variation{
{Mutator: "arch", Variation: jniTarget.String()},
@@ -162,6 +170,11 @@
target: jniTarget,
}
ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+ if String(a.appProperties.Stl) == "c++_shared" {
+ if embedJni {
+ ctx.AddFarVariationDependencies(variation, tag, "libc++")
+ }
+ }
}
}
@@ -217,6 +230,11 @@
return shouldUncompressDex(ctx, &a.dexpreopter)
}
+func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
+ return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
+ a.appProperties.AlwaysPackageNativeLibs
+}
+
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
@@ -305,9 +323,7 @@
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
var jniJarFile android.WritablePath
if len(jniLibs) > 0 {
- embedJni := ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
- a.appProperties.AlwaysPackageNativeLibs
- if embedJni {
+ if a.shouldEmbedJnis(ctx) {
jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
} else {
diff --git a/java/app_test.go b/java/app_test.go
index 347139e..40a64af 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1178,3 +1178,64 @@
}
}
}
+
+func TestStl(t *testing.T) {
+ ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+ cc_library {
+ name: "libjni",
+ }
+
+ android_test {
+ name: "stl",
+ jni_libs: ["libjni"],
+ compile_multilib: "both",
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+
+ android_test {
+ name: "system",
+ jni_libs: ["libjni"],
+ compile_multilib: "both",
+ sdk_version: "current",
+ }
+ `)
+
+ testCases := []struct {
+ name string
+ jnis []string
+ }{
+ {"stl",
+ []string{
+ "libjni.so",
+ "libc++.so",
+ },
+ },
+ {"system",
+ []string{
+ "libjni.so",
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ app := ctx.ModuleForTests(test.name, "android_common")
+ jniLibZip := app.Output("jnilibs.zip")
+ var jnis []string
+ args := strings.Fields(jniLibZip.Args["jarArgs"])
+ for i := 0; i < len(args); i++ {
+ if args[i] == "-f" {
+ jnis = append(jnis, args[i+1])
+ i += 1
+ }
+ }
+ jnisJoined := strings.Join(jnis, " ")
+ for _, jni := range test.jnis {
+ if !strings.Contains(jnisJoined, jni) {
+ t.Errorf("missing jni %q in %q", jni, jnis)
+ }
+ }
+ })
+ }
+}