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).