Merge "Add neverallow rules for java_device_for_host"
diff --git a/android/mutator.go b/android/mutator.go
index e5f742f..509b67f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -132,11 +132,15 @@
VisitDepsDepthFirst(visit func(Module))
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
WalkDeps(visit func(Module, Module) bool)
+ // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
+ // and returns a top-down dependency path from a start module to current child module.
+ GetWalkPath() []Module
}
type androidTopDownMutatorContext struct {
blueprint.TopDownMutatorContext
androidBaseContextImpl
+ walkPath []Module
}
type AndroidBottomUpMutator func(BottomUpMutatorContext)
@@ -287,10 +291,16 @@
}
func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
+ a.walkPath = []Module{a.Module()}
a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
childAndroidModule, _ := child.(Module)
parentAndroidModule, _ := parent.(Module)
if childAndroidModule != nil && parentAndroidModule != nil {
+ // record walkPath before visit
+ for a.walkPath[len(a.walkPath)-1] != parentAndroidModule {
+ a.walkPath = a.walkPath[0 : len(a.walkPath)-1]
+ }
+ a.walkPath = append(a.walkPath, childAndroidModule)
return visit(childAndroidModule, parentAndroidModule)
} else {
return false
@@ -298,6 +308,10 @@
})
}
+func (a *androidTopDownMutatorContext) GetWalkPath() []Module {
+ return a.walkPath
+}
+
func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) {
for _, p := range props {
err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties,
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
index 0426b43..d2a84d1 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/cmd/androidmk/androidmk.go
@@ -208,7 +208,7 @@
file.errorf(x, "missing if before else")
continue
} else if conds[len(conds)-1] == nil {
- file.errorf(x, "else from unsupported contitional")
+ file.errorf(x, "else from unsupported conditional")
continue
}
conds[len(conds)-1].eq = !conds[len(conds)-1].eq
@@ -217,7 +217,7 @@
file.errorf(x, "missing if before endif")
continue
} else if conds[len(conds)-1] == nil {
- file.errorf(x, "endif from unsupported contitional")
+ file.errorf(x, "endif from unsupported conditional")
conds = conds[:len(conds)-1]
} else {
if assignmentCond == conds[len(conds)-1] {
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 8ba3181..98d4506 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -504,9 +504,9 @@
// # b==false
// echo end
//
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
+// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
// endif
-// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
+// ANDROIDMK TRANSLATION ERROR: endif from unsupported conditional
// endif
`,
},
@@ -1064,6 +1064,17 @@
}
`,
},
+ {
+ desc: "comment with ESC",
+ in: `
+# Comment line 1 \
+# Comment line 2
+`,
+ expected: `
+// Comment line 1 \
+// Comment line 2
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index 89c1af9..86dabf9 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -485,10 +485,12 @@
case '\\':
p.parseEscape()
if p.tok == '\n' {
- comment += "\n"
- } else {
- comment += "\\" + p.scanner.TokenText()
+ // Special case: '\' does not "escape" newline in comment (b/127521510)
+ comment += "\\"
+ p.accept(p.tok)
+ break loop
}
+ comment += "\\" + p.scanner.TokenText()
p.accept(p.tok)
case '\n':
p.accept('\n')
diff --git a/cc/cc.go b/cc/cc.go
index 117bbc2..284b58d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -68,6 +68,8 @@
ctx.TopDown("lto_deps", ltoDepsMutator)
ctx.BottomUp("lto", ltoMutator).Parallel()
+
+ ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
pctx.Import("android/soong/cc/config")
@@ -1469,30 +1471,44 @@
}
// Tests whether the dependent library is okay to be double loaded inside a single process.
-// If a library is a member of VNDK and at the same time dependencies of an LLNDK library,
-// it is subject to be double loaded. Such lib should be explicitly marked as double_loaded: true
+// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
+// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
// or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
-func checkDoubleLoadableLibries(ctx android.ModuleContext, from *Module, to *Module) {
- if _, ok := from.linker.(*libraryDecorator); !ok {
- return
- }
+func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
+ check := func(child, parent android.Module) bool {
+ to, ok := child.(*Module)
+ if !ok {
+ // follow thru cc.Defaults, etc.
+ return true
+ }
- if inList(ctx.ModuleName(), llndkLibraries) ||
- (from.useVndk() && Bool(from.VendorProperties.Double_loadable)) {
- _, depIsLlndk := to.linker.(*llndkStubDecorator)
- depIsVndkSp := false
- if to.vndkdep != nil && to.vndkdep.isVndkSp() {
- depIsVndkSp = true
+ if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
+ return false
}
- depIsVndk := false
- if to.vndkdep != nil && to.vndkdep.isVndk() {
- depIsVndk = true
+
+ // if target lib has no vendor variant, keep checking dependency graph
+ if !to.hasVendorVariant() {
+ return true
}
- depIsDoubleLoadable := Bool(to.VendorProperties.Double_loadable)
- if !depIsLlndk && !depIsVndkSp && !depIsDoubleLoadable && depIsVndk {
- ctx.ModuleErrorf("links VNDK library %q that isn't double loadable (not also LL-NDK, "+
- "VNDK-SP, or explicitly marked as 'double_loadable').",
- ctx.OtherModuleName(to))
+
+ if to.isVndkSp() || inList(child.Name(), llndkLibraries) || Bool(to.VendorProperties.Double_loadable) {
+ return false
+ }
+
+ var stringPath []string
+ for _, m := range ctx.GetWalkPath() {
+ stringPath = append(stringPath, m.Name())
+ }
+ ctx.ModuleErrorf("links a library %q which is not LL-NDK, "+
+ "VNDK-SP, or explicitly marked as 'double_loadable:true'. "+
+ "(dependency: %s)", ctx.OtherModuleName(to), strings.Join(stringPath, " -> "))
+ return false
+ }
+ if module, ok := ctx.Module().(*Module); ok {
+ if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
+ if inList(ctx.ModuleName(), llndkLibraries) || Bool(module.VendorProperties.Double_loadable) {
+ ctx.WalkDeps(check)
+ }
}
}
}
@@ -1648,7 +1664,6 @@
}
checkLinkType(ctx, c, ccDep, t)
- checkDoubleLoadableLibries(ctx, c, ccDep)
}
var ptr *android.Paths
diff --git a/cc/cc_test.go b/cc/cc_test.go
index a0914c8..8c0bcfe 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -71,6 +71,9 @@
ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
})
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
+ })
ctx.Register()
// add some modules that are required by the compiler and/or linker
@@ -428,6 +431,309 @@
nocrt: true,
}
`)
+
+ // Check whether an error is emitted when a VNDK lib depends on a non-VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ shared_libs: ["libnonvndk"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libnonvndk",
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+
+ // Check whether an error is emitted when a VNDK-private lib depends on a non-VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+ cc_library {
+ name: "libvndkprivate",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ shared_libs: ["libnonvndk"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libnonvndk",
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+
+ // Check whether an error is emitted when a VNDK-sp lib depends on a non-VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+ cc_library {
+ name: "libvndksp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ shared_libs: ["libnonvndk"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libnonvndk",
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+
+ // Check whether an error is emitted when a VNDK-sp-private lib depends on a non-VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+ cc_library {
+ name: "libvndkspprivate",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ shared_libs: ["libnonvndk"],
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libnonvndk",
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+}
+
+func TestDoubleLoadbleDep(t *testing.T) {
+ // okay to link : LLNDK -> double_loadable VNDK
+ testCc(t, `
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libdoubleloadable"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libdoubleloadable",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ double_loadable: true,
+ }
+ `)
+ // okay to link : LLNDK -> VNDK-SP
+ testCc(t, `
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libvndksp"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libvndksp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ }
+ `)
+ // okay to link : double_loadable -> double_loadable
+ testCc(t, `
+ cc_library {
+ name: "libdoubleloadable1",
+ shared_libs: ["libdoubleloadable2"],
+ vendor_available: true,
+ double_loadable: true,
+ }
+
+ cc_library {
+ name: "libdoubleloadable2",
+ vendor_available: true,
+ double_loadable: true,
+ }
+ `)
+ // okay to link : double_loadable VNDK -> double_loadable VNDK private
+ testCc(t, `
+ cc_library {
+ name: "libdoubleloadable",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ double_loadable: true,
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ double_loadable: true,
+ }
+ `)
+ // okay to link : LLNDK -> core-only -> vendor_available & double_loadable
+ testCc(t, `
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libcoreonly"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libcoreonly",
+ shared_libs: ["libvendoravailable"],
+ }
+
+ // indirect dependency of LLNDK
+ cc_library {
+ name: "libvendoravailable",
+ vendor_available: true,
+ double_loadable: true,
+ }
+ `)
+}
+
+func TestDoubleLoadableDepError(t *testing.T) {
+ // Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ }
+ `)
+
+ // Check whether an error is emitted when a LLNDK depends on a non-double_loadable vendor_available lib.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libllndk",
+ no_libgcc: true,
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: true,
+ }
+ `)
+
+ // Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable vendor_available lib.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libdoubleloadable",
+ vendor_available: true,
+ double_loadable: true,
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: true,
+ }
+ `)
+
+ // Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable VNDK lib.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libdoubleloadable",
+ vendor_available: true,
+ double_loadable: true,
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ }
+ `)
+
+ // Check whether an error is emitted when a double_loadable VNDK depends on a non-double_loadable VNDK private lib.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libdoubleloadable",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ double_loadable: true,
+ shared_libs: ["libnondoubleloadable"],
+ }
+
+ cc_library {
+ name: "libnondoubleloadable",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ }
+ `)
+
+ // Check whether an error is emitted when a LLNDK depends on a non-double_loadable indirectly.
+ testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
+ cc_library {
+ name: "libllndk",
+ shared_libs: ["libcoreonly"],
+ }
+
+ llndk_library {
+ name: "libllndk",
+ symbol_file: "",
+ }
+
+ cc_library {
+ name: "libcoreonly",
+ shared_libs: ["libvendoravailable"],
+ }
+
+ // indirect dependency of LLNDK
+ cc_library {
+ name: "libvendoravailable",
+ vendor_available: true,
+ }
+ `)
}
func TestVndkMustNotBeProductSpecific(t *testing.T) {
diff --git a/cc/test.go b/cc/test.go
index 8e49fac..3ecc419 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -120,6 +120,10 @@
if m, ok := mctx.Module().(*Module); ok {
if test, ok := m.linker.(testPerSrc); ok {
if test.testPerSrc() && len(test.srcs()) > 0 {
+ if duplicate, found := checkDuplicate(test.srcs()); found {
+ mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
+ return
+ }
testNames := make([]string, len(test.srcs()))
for i, src := range test.srcs() {
testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
@@ -133,6 +137,17 @@
}
}
+func checkDuplicate(values []string) (duplicate string, found bool) {
+ seen := make(map[string]string)
+ for _, v := range values {
+ if duplicate, found = seen[v]; found {
+ return
+ }
+ seen[v] = v
+ }
+ return
+}
+
type testDecorator struct {
Properties TestProperties
linker *baseLinker
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 9e333c1..01ee15e 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -331,6 +331,14 @@
rule.Command().Text("source").Tool(global.Tools.ConstructContext)
}
+ // Devices that do not have a product partition use a symlink from /product to /system/product.
+ // Because on-device dexopt will see dex locations starting with /product, we change the paths
+ // to mimic this behavior.
+ dexLocationArg := module.DexLocation
+ if strings.HasPrefix(dexLocationArg, "/system/product/") {
+ dexLocationArg = strings.TrimPrefix(dexLocationArg, "/system")
+ }
+
cmd := rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
Tool(global.Tools.Dex2oat).
@@ -344,7 +352,7 @@
Flag("${stored_class_loader_context_arg}").
FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImage).
FlagWithInput("--dex-file=", module.DexPath).
- FlagWithArg("--dex-location=", module.DexLocation).
+ FlagWithArg("--dex-location=", dexLocationArg).
FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
// Pass an empty directory, dex2oat shouldn't be reading arbitrary files
FlagWithArg("--android-root=", global.EmptyDirectory).