Merge "Revert "Pass jars with resources to R8""
diff --git a/android/bazel.go b/android/bazel.go
index 26e7deb..7123ed2 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -151,6 +151,7 @@
 
 		"prebuilts/sdk":/* recursive = */ false,
 		"prebuilts/sdk/tools":/* recursive = */ false,
+		"prebuilts/r8":/* recursive = */ false,
 		"packages/apps/Music":/* recursive = */ false,
 	}
 
diff --git a/android/paths.go b/android/paths.go
index 99db22f..9c9914e 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -20,6 +20,7 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"regexp"
 	"sort"
 	"strings"
 
@@ -2094,3 +2095,25 @@
 	}
 	return ret
 }
+
+var thirdPartyDirPrefixExceptions = []*regexp.Regexp{
+	regexp.MustCompile("^vendor/[^/]*google[^/]*/"),
+	regexp.MustCompile("^hardware/google/"),
+	regexp.MustCompile("^hardware/interfaces/"),
+	regexp.MustCompile("^hardware/libhardware[^/]*/"),
+	regexp.MustCompile("^hardware/ril/"),
+}
+
+func IsThirdPartyPath(path string) bool {
+	thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"}
+
+	if HasAnyPrefix(path, thirdPartyDirPrefixes) {
+		for _, prefix := range thirdPartyDirPrefixExceptions {
+			if prefix.MatchString(path) {
+				return false
+			}
+		}
+		return true
+	}
+	return false
+}
diff --git a/apex/apex.go b/apex/apex.go
index 149f782..e525aff 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1696,6 +1696,7 @@
 	a.checkUpdatable(ctx)
 	a.checkMinSdkVersion(ctx)
 	a.checkStaticLinkingToStubLibraries(ctx)
+	a.checkStaticExecutables(ctx)
 	if len(a.properties.Tests) > 0 && !a.testApex {
 		ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
 		return
@@ -2487,6 +2488,41 @@
 	})
 }
 
+// checkStaticExecutable ensures that executables in an APEX are not static.
+func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
+	// No need to run this for host APEXes
+	if ctx.Host() {
+		return
+	}
+
+	ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+		if ctx.OtherModuleDependencyTag(module) != executableTag {
+			return
+		}
+
+		if l, ok := module.(cc.LinkableInterface); ok && l.StaticExecutable() {
+			apex := a.ApexVariationName()
+			exec := ctx.OtherModuleName(module)
+			if isStaticExecutableAllowed(apex, exec) {
+				return
+			}
+			ctx.ModuleErrorf("executable %s is static", ctx.OtherModuleName(module))
+		}
+	})
+}
+
+// A small list of exceptions where static executables are allowed in APEXes.
+func isStaticExecutableAllowed(apex string, exec string) bool {
+	m := map[string][]string{
+		"com.android.runtime": []string{
+			"linker",
+			"linkerconfig",
+		},
+	}
+	execNames, ok := m[apex]
+	return ok && android.InList(exec, execNames)
+}
+
 // Collect information for opening IDE project files in java/jdeps.go.
 func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
 	dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 0ed94af..9178431 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -59,8 +59,15 @@
 				echo "******************************";
 				echo "Detected changes to allowed dependencies in updatable modules.";
 				echo "To fix and update packages/modules/common/build/allowed_deps.txt, please run:";
-				echo "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)";
-				echo "Members of mainline-modularization@google.com will review the changes.";
+				echo -e "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)\n";
+				echo "When submitting the generated CL, you must include the following information";
+				echo "in the commit message if you are adding a new dependency:";
+				echo "Apex-Size-Increase:";
+				echo "Previous-Platform-Support:";
+				echo "Aosp-First:";
+				echo "Test-Info:";
+				echo "You do not need OWNERS approval to submit the change, but mainline-modularization@";
+				echo "will periodically review additions and may require changes.";
 				echo -e "******************************\n";
 				exit 1;
 			fi;
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f58bf6c..41bfcea 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -374,7 +374,6 @@
 			symlinks: ["foo_link_"],
 			symlink_preferred_arch: true,
 			system_shared_libs: [],
-			static_executable: true,
 			stl: "none",
 			apex_available: [ "myapex", "com.android.gki.*" ],
 		}
@@ -2494,7 +2493,6 @@
 			srcs: ["mylib.cpp"],
 			relative_install_path: "foo/bar",
 			system_shared_libs: [],
-			static_executable: true,
 			stl: "none",
 			apex_available: [ "myapex" ],
 		}
@@ -2554,7 +2552,6 @@
 			name: "mybin",
 			relative_install_path: "foo/bar",
 			system_shared_libs: [],
-			static_executable: true,
 			stl: "none",
 			apex_available: [ "myapex" ],
 			native_bridge_supported: true,
@@ -8188,6 +8185,57 @@
 	}
 }
 
+func TestProhibitStaticExecutable(t *testing.T) {
+	testApexError(t, `executable mybin is static`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			binaries: ["mybin"],
+			min_sdk_version: "29",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_binary {
+			name: "mybin",
+			srcs: ["mylib.cpp"],
+			relative_install_path: "foo/bar",
+			static_executable: true,
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [ "myapex" ],
+			min_sdk_version: "29",
+		}
+	`)
+
+	testApexError(t, `executable mybin.rust is static`, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			binaries: ["mybin.rust"],
+			min_sdk_version: "29",
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		rust_binary {
+			name: "mybin.rust",
+			srcs: ["foo.rs"],
+			static_executable: true,
+			apex_available: ["myapex"],
+			min_sdk_version: "29",
+		}
+	`)
+}
+
 func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 }
diff --git a/cc/cc_test.go b/cc/cc_test.go
index dd51fe8..84c3a86 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3955,10 +3955,13 @@
 		`, lib, lib)
 	}
 
-	ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
+	ctx := android.GroupFixturePreparers(
+		PrepareForIntegrationTestWithCc,
+		android.FixtureAddTextFile("external/foo/Android.bp", bp),
+	).RunTest(t)
 	// Use the arm variant instead of the arm64 variant so that it gets headers from
 	// ndk_libandroid_support to test LateStaticLibs.
-	cflags := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_sdk_static").Output("obj/foo.o").Args["cFlags"]
+	cflags := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_sdk_static").Output("obj/external/foo/foo.o").Args["cFlags"]
 
 	var includes []string
 	flags := strings.Split(cflags, " ")
@@ -3981,32 +3984,32 @@
 		"${config.ArmToolchainCflags}",
 		"${config.ArmArmv7ANeonCflags}",
 		"${config.ArmGenericCflags}",
-		"android_arm_export_include_dirs",
-		"lib32_export_include_dirs",
-		"arm_export_include_dirs",
-		"android_export_include_dirs",
-		"linux_export_include_dirs",
-		"export_include_dirs",
-		"android_arm_local_include_dirs",
-		"lib32_local_include_dirs",
-		"arm_local_include_dirs",
-		"android_local_include_dirs",
-		"linux_local_include_dirs",
-		"local_include_dirs",
-		".",
-		"libheader1",
-		"libheader2",
-		"libwhole1",
-		"libwhole2",
-		"libstatic1",
-		"libstatic2",
-		"libshared1",
-		"libshared2",
-		"liblinux",
-		"libandroid",
-		"libarm",
-		"lib32",
-		"libandroid_arm",
+		"external/foo/android_arm_export_include_dirs",
+		"external/foo/lib32_export_include_dirs",
+		"external/foo/arm_export_include_dirs",
+		"external/foo/android_export_include_dirs",
+		"external/foo/linux_export_include_dirs",
+		"external/foo/export_include_dirs",
+		"external/foo/android_arm_local_include_dirs",
+		"external/foo/lib32_local_include_dirs",
+		"external/foo/arm_local_include_dirs",
+		"external/foo/android_local_include_dirs",
+		"external/foo/linux_local_include_dirs",
+		"external/foo/local_include_dirs",
+		"external/foo",
+		"external/foo/libheader1",
+		"external/foo/libheader2",
+		"external/foo/libwhole1",
+		"external/foo/libwhole2",
+		"external/foo/libstatic1",
+		"external/foo/libstatic2",
+		"external/foo/libshared1",
+		"external/foo/libshared2",
+		"external/foo/liblinux",
+		"external/foo/libandroid",
+		"external/foo/libarm",
+		"external/foo/lib32",
+		"external/foo/libandroid_arm",
 		"defaults/cc/common/ndk_libc++_shared",
 		"defaults/cc/common/ndk_libandroid_support",
 		"out/soong/ndk/sysroot/usr/include",
diff --git a/cc/compiler.go b/cc/compiler.go
index 34ac47a..03214c8 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -450,7 +450,7 @@
 		"${config.CommonGlobalCflags}",
 		fmt.Sprintf("${config.%sGlobalCflags}", hod))
 
-	if isThirdParty(modulePath) {
+	if android.IsThirdPartyPath(modulePath) {
 		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "${config.ExternalCflags}")
 	}
 
@@ -675,27 +675,6 @@
 	return transformSourceToObj(ctx, subdir, srcFiles, flags, pathDeps, cFlagsDeps)
 }
 
-var thirdPartyDirPrefixExceptions = []*regexp.Regexp{
-	regexp.MustCompile("^vendor/[^/]*google[^/]*/"),
-	regexp.MustCompile("^hardware/google/"),
-	regexp.MustCompile("^hardware/interfaces/"),
-	regexp.MustCompile("^hardware/libhardware[^/]*/"),
-	regexp.MustCompile("^hardware/ril/"),
-}
-
-func isThirdParty(path string) bool {
-	thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"}
-
-	if android.HasAnyPrefix(path, thirdPartyDirPrefixes) {
-		for _, prefix := range thirdPartyDirPrefixExceptions {
-			if prefix.MatchString(path) {
-				return false
-			}
-		}
-	}
-	return true
-}
-
 // Properties for rust_bindgen related to generating rust bindings.
 // This exists here so these properties can be included in a cc_default
 // which can be used in both cc and rust modules.
diff --git a/cc/compiler_test.go b/cc/compiler_test.go
index c301388..9ae4d18 100644
--- a/cc/compiler_test.go
+++ b/cc/compiler_test.go
@@ -16,27 +16,30 @@
 
 import (
 	"testing"
+
+	"android/soong/android"
 )
 
 func TestIsThirdParty(t *testing.T) {
-	shouldFail := []string{
+	thirdPartyPaths := []string{
 		"external/foo/",
 		"vendor/bar/",
 		"hardware/underwater_jaguar/",
 	}
-	shouldPass := []string{
+	nonThirdPartyPaths := []string{
 		"vendor/google/cts/",
 		"hardware/google/pixel",
 		"hardware/interfaces/camera",
 		"hardware/ril/supa_ril",
+		"bionic/libc",
 	}
-	for _, path := range shouldFail {
-		if !isThirdParty(path) {
+	for _, path := range thirdPartyPaths {
+		if !android.IsThirdPartyPath(path) {
 			t.Errorf("Expected %s to be considered third party", path)
 		}
 	}
-	for _, path := range shouldPass {
-		if isThirdParty(path) {
+	for _, path := range nonThirdPartyPaths {
+		if android.IsThirdPartyPath(path) {
 			t.Errorf("Expected %s to *not* be considered third party", path)
 		}
 	}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index c26b20c..71a8780 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -112,16 +112,17 @@
 	label string
 }
 type generatorProperties struct {
-	// The command to run on one or more input files. Cmd supports substitution of a few variables
+	// The command to run on one or more input files. Cmd supports substitution of a few variables.
 	//
 	// Available variables for substitution:
 	//
-	//  $(location): the path to the first entry in tools or tool_files
-	//  $(location <label>): the path to the tool, tool_file, input or output with name <label>
-	//  $(in): one or more input files
-	//  $(out): a single output file
-	//  $(depfile): a file to which dependencies will be written, if the depfile property is set to true
-	//  $(genDir): the sandbox directory for this tool; contains $(out)
+	//  $(location): the path to the first entry in tools or tool_files.
+	//  $(location <label>): the path to the tool, tool_file, input or output with name <label>. Use $(location) if <label> refers to a rule that outputs exactly one file.
+	//  $(locations <label>): the paths to the tools, tool_files, inputs or outputs with name <label>. Use $(locations) if <label> refers to a rule that outputs two or more files.
+	//  $(in): one or more input files.
+	//  $(out): a single output file.
+	//  $(depfile): a file to which dependencies will be written, if the depfile property is set to true.
+	//  $(genDir): the sandbox directory for this tool; contains $(out).
 	//  $$: a literal $
 	Cmd *string
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 268e797..c50e077 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -419,7 +419,7 @@
 	// local files that are used within user customized droiddoc options.
 	Droiddoc_option_files []string
 
-	// additional droiddoc options
+	// additional droiddoc options.
 	// Available variables for substitution:
 	//
 	//  $(location <label>): the path to the droiddoc_option_files with name <label>
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index 915f69e..0bb8b95 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -516,6 +516,7 @@
 }
 
 func (cx *callExpr) emit(gctx *generationContext) {
+	sep := ""
 	if cx.object != nil {
 		gctx.write("(")
 		cx.object.emit(gctx)
@@ -530,8 +531,14 @@
 			panic(fmt.Errorf("callExpr for %q should not be there", cx.name))
 		}
 		gctx.write(kf.runtimeName, "(")
+		if kf.hiddenArg == hiddenArgGlobal {
+			gctx.write("g")
+			sep = ", "
+		} else if kf.hiddenArg == hiddenArgConfig {
+			gctx.write("cfg")
+			sep = ", "
+		}
 	}
-	sep := ""
 	for _, arg := range cx.args {
 		gctx.write(sep)
 		arg.emit(gctx)
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 2173e9b..7ceac41 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -60,8 +60,10 @@
 const (
 	// Phony makefile functions, they are eventually rewritten
 	// according to knownFunctions map
-	fileExistsPhony     = "$file_exists"
-	wildcardExistsPhony = "$wildcard_exists"
+	addSoongNamespace      = "add_soong_config_namespace"
+	addSoongConfigVarValue = "add_soong_config_var_value"
+	fileExistsPhony        = "$file_exists"
+	wildcardExistsPhony    = "$wildcard_exists"
 )
 
 const (
@@ -75,54 +77,58 @@
 	// something else.
 	runtimeName string
 	returnType  starlarkType
+	hiddenArg   hiddenArgType
 }{
-	"abspath":                             {baseName + ".abspath", starlarkTypeString},
-	fileExistsPhony:                       {baseName + ".file_exists", starlarkTypeBool},
-	wildcardExistsPhony:                   {baseName + ".file_wildcard_exists", starlarkTypeBool},
-	"add-to-product-copy-files-if-exists": {baseName + ".copy_if_exists", starlarkTypeList},
-	"addprefix":                           {baseName + ".addprefix", starlarkTypeList},
-	"addsuffix":                           {baseName + ".addsuffix", starlarkTypeList},
-	"dir":                                 {baseName + ".dir", starlarkTypeList},
-	"enforce-product-packages-exist":      {baseName + ".enforce_product_packages_exist", starlarkTypeVoid},
-	"error":                               {baseName + ".mkerror", starlarkTypeVoid},
-	"findstring":                          {"!findstring", starlarkTypeInt},
-	"find-copy-subdir-files":              {baseName + ".find_and_copy", starlarkTypeList},
-	"find-word-in-list":                   {"!find-word-in-list", starlarkTypeUnknown}, // internal macro
-	"filter":                              {baseName + ".filter", starlarkTypeList},
-	"filter-out":                          {baseName + ".filter_out", starlarkTypeList},
-	"firstword":                           {"!firstword", starlarkTypeString},
-	"get-vendor-board-platforms":          {"!get-vendor-board-platforms", starlarkTypeList}, // internal macro, used by is-board-platform, etc.
-	"info":                                {baseName + ".mkinfo", starlarkTypeVoid},
-	"is-android-codename":                 {"!is-android-codename", starlarkTypeBool},         // unused by product config
-	"is-android-codename-in-list":         {"!is-android-codename-in-list", starlarkTypeBool}, // unused by product config
-	"is-board-platform":                   {"!is-board-platform", starlarkTypeBool},
-	"is-board-platform-in-list":           {"!is-board-platform-in-list", starlarkTypeBool},
-	"is-chipset-in-board-platform":        {"!is-chipset-in-board-platform", starlarkTypeUnknown},     // unused by product config
-	"is-chipset-prefix-in-board-platform": {"!is-chipset-prefix-in-board-platform", starlarkTypeBool}, // unused by product config
-	"is-not-board-platform":               {"!is-not-board-platform", starlarkTypeBool},               // defined but never used
-	"is-platform-sdk-version-at-least":    {"!is-platform-sdk-version-at-least", starlarkTypeBool},    // unused by product config
-	"is-product-in-list":                  {"!is-product-in-list", starlarkTypeBool},
-	"is-vendor-board-platform":            {"!is-vendor-board-platform", starlarkTypeBool},
-	callLoadAlways:                        {"!inherit-product", starlarkTypeVoid},
-	callLoadIf:                            {"!inherit-product-if-exists", starlarkTypeVoid},
-	"lastword":                            {"!lastword", starlarkTypeString},
-	"match-prefix":                        {"!match-prefix", starlarkTypeUnknown},       // internal macro
-	"match-word":                          {"!match-word", starlarkTypeUnknown},         // internal macro
-	"match-word-in-list":                  {"!match-word-in-list", starlarkTypeUnknown}, // internal macro
-	"notdir":                              {baseName + ".notdir", starlarkTypeString},
-	"my-dir":                              {"!my-dir", starlarkTypeString},
-	"patsubst":                            {baseName + ".mkpatsubst", starlarkTypeString},
-	"produce_copy_files":                  {baseName + ".produce_copy_files", starlarkTypeList},
-	"require-artifacts-in-path":           {baseName + ".require_artifacts_in_path", starlarkTypeVoid},
-	"require-artifacts-in-path-relaxed":   {baseName + ".require_artifacts_in_path_relaxed", starlarkTypeVoid},
+	"abspath":                             {baseName + ".abspath", starlarkTypeString, hiddenArgNone},
+	fileExistsPhony:                       {baseName + ".file_exists", starlarkTypeBool, hiddenArgNone},
+	wildcardExistsPhony:                   {baseName + ".file_wildcard_exists", starlarkTypeBool, hiddenArgNone},
+	addSoongNamespace:                     {baseName + ".add_soong_config_namespace", starlarkTypeVoid, hiddenArgGlobal},
+	addSoongConfigVarValue:                {baseName + ".add_soong_config_var_value", starlarkTypeVoid, hiddenArgGlobal},
+	"add-to-product-copy-files-if-exists": {baseName + ".copy_if_exists", starlarkTypeList, hiddenArgNone},
+	"addprefix":                           {baseName + ".addprefix", starlarkTypeList, hiddenArgNone},
+	"addsuffix":                           {baseName + ".addsuffix", starlarkTypeList, hiddenArgNone},
+	"copy-files":                          {baseName + ".copy_files", starlarkTypeList, hiddenArgNone},
+	"dir":                                 {baseName + ".dir", starlarkTypeList, hiddenArgNone},
+	"enforce-product-packages-exist":      {baseName + ".enforce_product_packages_exist", starlarkTypeVoid, hiddenArgNone},
+	"error":                               {baseName + ".mkerror", starlarkTypeVoid, hiddenArgNone},
+	"findstring":                          {"!findstring", starlarkTypeInt, hiddenArgNone},
+	"find-copy-subdir-files":              {baseName + ".find_and_copy", starlarkTypeList, hiddenArgNone},
+	"find-word-in-list":                   {"!find-word-in-list", starlarkTypeUnknown, hiddenArgNone}, // internal macro
+	"filter":                              {baseName + ".filter", starlarkTypeList, hiddenArgNone},
+	"filter-out":                          {baseName + ".filter_out", starlarkTypeList, hiddenArgNone},
+	"firstword":                           {"!firstword", starlarkTypeString, hiddenArgNone},
+	"get-vendor-board-platforms":          {"!get-vendor-board-platforms", starlarkTypeList, hiddenArgNone}, // internal macro, used by is-board-platform, etc.
+	"info":                                {baseName + ".mkinfo", starlarkTypeVoid, hiddenArgNone},
+	"is-android-codename":                 {"!is-android-codename", starlarkTypeBool, hiddenArgNone},         // unused by product config
+	"is-android-codename-in-list":         {"!is-android-codename-in-list", starlarkTypeBool, hiddenArgNone}, // unused by product config
+	"is-board-platform":                   {"!is-board-platform", starlarkTypeBool, hiddenArgNone},
+	"is-board-platform-in-list":           {"!is-board-platform-in-list", starlarkTypeBool, hiddenArgNone},
+	"is-chipset-in-board-platform":        {"!is-chipset-in-board-platform", starlarkTypeUnknown, hiddenArgNone},     // unused by product config
+	"is-chipset-prefix-in-board-platform": {"!is-chipset-prefix-in-board-platform", starlarkTypeBool, hiddenArgNone}, // unused by product config
+	"is-not-board-platform":               {"!is-not-board-platform", starlarkTypeBool, hiddenArgNone},               // defined but never used
+	"is-platform-sdk-version-at-least":    {"!is-platform-sdk-version-at-least", starlarkTypeBool, hiddenArgNone},    // unused by product config
+	"is-product-in-list":                  {"!is-product-in-list", starlarkTypeBool, hiddenArgNone},
+	"is-vendor-board-platform":            {"!is-vendor-board-platform", starlarkTypeBool, hiddenArgNone},
+	callLoadAlways:                        {"!inherit-product", starlarkTypeVoid, hiddenArgNone},
+	callLoadIf:                            {"!inherit-product-if-exists", starlarkTypeVoid, hiddenArgNone},
+	"lastword":                            {"!lastword", starlarkTypeString, hiddenArgNone},
+	"match-prefix":                        {"!match-prefix", starlarkTypeUnknown, hiddenArgNone},       // internal macro
+	"match-word":                          {"!match-word", starlarkTypeUnknown, hiddenArgNone},         // internal macro
+	"match-word-in-list":                  {"!match-word-in-list", starlarkTypeUnknown, hiddenArgNone}, // internal macro
+	"notdir":                              {baseName + ".notdir", starlarkTypeString, hiddenArgNone},
+	"my-dir":                              {"!my-dir", starlarkTypeString, hiddenArgNone},
+	"patsubst":                            {baseName + ".mkpatsubst", starlarkTypeString, hiddenArgNone},
+	"produce_copy_files":                  {baseName + ".produce_copy_files", starlarkTypeList, hiddenArgNone},
+	"require-artifacts-in-path":           {baseName + ".require_artifacts_in_path", starlarkTypeVoid, hiddenArgNone},
+	"require-artifacts-in-path-relaxed":   {baseName + ".require_artifacts_in_path_relaxed", starlarkTypeVoid, hiddenArgNone},
 	// TODO(asmundak): remove it once all calls are removed from configuration makefiles. see b/183161002
-	"shell":      {baseName + ".shell", starlarkTypeString},
-	"strip":      {baseName + ".mkstrip", starlarkTypeString},
-	"tb-modules": {"!tb-modules", starlarkTypeUnknown}, // defined in hardware/amlogic/tb_modules/tb_detect.mk, unused
-	"subst":      {baseName + ".mksubst", starlarkTypeString},
-	"warning":    {baseName + ".mkwarning", starlarkTypeVoid},
-	"word":       {baseName + "!word", starlarkTypeString},
-	"wildcard":   {baseName + ".expand_wildcard", starlarkTypeList},
+	"shell":      {baseName + ".shell", starlarkTypeString, hiddenArgNone},
+	"strip":      {baseName + ".mkstrip", starlarkTypeString, hiddenArgNone},
+	"tb-modules": {"!tb-modules", starlarkTypeUnknown, hiddenArgNone}, // defined in hardware/amlogic/tb_modules/tb_detect.mk, unused
+	"subst":      {baseName + ".mksubst", starlarkTypeString, hiddenArgNone},
+	"warning":    {baseName + ".mkwarning", starlarkTypeVoid, hiddenArgNone},
+	"word":       {baseName + "!word", starlarkTypeString, hiddenArgNone},
+	"wildcard":   {baseName + ".expand_wildcard", starlarkTypeList, hiddenArgNone},
 }
 
 var builtinFuncRex = regexp.MustCompile(
@@ -392,6 +398,7 @@
 	receiverStack    []nodeReceiver
 	outputDir        string
 	dependentModules map[string]*moduleInfo
+	soongNamespaces  map[string]map[string]bool
 }
 
 func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
@@ -443,6 +450,7 @@
 		builtinMakeVars:  map[string]starlarkExpr{},
 		variables:        make(map[string]variable),
 		dependentModules: make(map[string]*moduleInfo),
+		soongNamespaces:  make(map[string]map[string]bool),
 	}
 	ctx.pushVarAssignments()
 	for _, item := range predefined {
@@ -521,6 +529,12 @@
 		return
 	}
 	name := a.Name.Strings[0]
+	const soongNsPrefix = "SOONG_CONFIG_"
+	// Soong confuguration
+	if strings.HasPrefix(name, soongNsPrefix) {
+		ctx.handleSoongNsAssignment(strings.TrimPrefix(name, soongNsPrefix), a)
+		return
+	}
 	lhs := ctx.addVariable(name)
 	if lhs == nil {
 		ctx.errorf(a, "unknown variable %s", name)
@@ -584,6 +598,88 @@
 	ctx.receiver.newNode(asgn)
 }
 
+func (ctx *parseContext) handleSoongNsAssignment(name string, asgn *mkparser.Assignment) {
+	val := ctx.parseMakeString(asgn, asgn.Value)
+	if xBad, ok := val.(*badExpr); ok {
+		ctx.wrapBadExpr(xBad)
+		return
+	}
+	val, _ = val.eval(ctx.builtinMakeVars)
+
+	// Unfortunately, Soong namespaces can be set up by directly setting corresponding Make
+	// variables instead of via add_soong_config_namespace + add_soong_config_var_value.
+	// Try to divine the call from the assignment as follows:
+	if name == "NAMESPACES" {
+		// Upon seeng
+		//      SOONG_CONFIG_NAMESPACES += foo
+		//    remember that there is a namespace `foo` and act as we saw
+		//      $(call add_soong_config_namespace,foo)
+		s, ok := maybeString(val)
+		if !ok {
+			ctx.errorf(asgn, "cannot handle variables in SOONG_CONFIG_NAMESPACES assignment, please use add_soong_config_namespace instead")
+			return
+		}
+		for _, ns := range strings.Fields(s) {
+			ctx.addSoongNamespace(ns)
+			ctx.receiver.newNode(&exprNode{&callExpr{
+				name:       addSoongNamespace,
+				args:       []starlarkExpr{&stringLiteralExpr{ns}},
+				returnType: starlarkTypeVoid,
+			}})
+		}
+	} else {
+		// Upon seeing
+		//      SOONG_CONFIG_x_y = v
+		// find a namespace called `x` and act as if we encountered
+		//      $(call add_config_var_value(x,y,v)
+		// or check that `x_y` is a namespace, and then add the RHS of this assignment as variables in
+		// it.
+		// Emit an error in the ambiguous situation (namespaces `foo_bar` with a variable `baz`
+		// and `foo` with a variable `bar_baz`.
+		namespaceName := ""
+		if ctx.hasSoongNamespace(name) {
+			namespaceName = name
+		}
+		var varName string
+		for pos, ch := range name {
+			if !(ch == '_' && ctx.hasSoongNamespace(name[0:pos])) {
+				continue
+			}
+			if namespaceName != "" {
+				ctx.errorf(asgn, "ambiguous soong namespace (may be either `%s` or  `%s`)", namespaceName, name[0:pos])
+				return
+			}
+			namespaceName = name[0:pos]
+			varName = name[pos+1:]
+		}
+		if namespaceName == "" {
+			ctx.errorf(asgn, "cannot figure out Soong namespace, please use add_soong_config_var_value macro instead")
+			return
+		}
+		if varName == "" {
+			// Remember variables in this namespace
+			s, ok := maybeString(val)
+			if !ok {
+				ctx.errorf(asgn, "cannot handle variables in SOONG_CONFIG_ assignment, please use add_soong_config_var_value instead")
+				return
+			}
+			ctx.updateSoongNamespace(asgn.Type != "+=", namespaceName, strings.Fields(s))
+			return
+		}
+
+		// Finally, handle assignment to a namespace variable
+		if !ctx.hasNamespaceVar(namespaceName, varName) {
+			ctx.errorf(asgn, "no %s variable in %s namespace, please use add_soong_config_var_value instead", varName, namespaceName)
+			return
+		}
+		ctx.receiver.newNode(&exprNode{&callExpr{
+			name:       addSoongConfigVarValue,
+			args:       []starlarkExpr{&stringLiteralExpr{namespaceName}, &stringLiteralExpr{varName}, val},
+			returnType: starlarkTypeVoid,
+		}})
+	}
+}
+
 func (ctx *parseContext) buildConcatExpr(a *mkparser.Assignment) *concatExpr {
 	xConcat := &concatExpr{}
 	var xItemList *listExpr
@@ -709,14 +805,20 @@
 		matchingPaths = ctx.findMatchingPaths(pathPattern)
 	} else {
 		// Heuristics -- if pattern starts from top, restrict it to the directories where
-		// we know inherit-product uses dynamically calculated path.
-		for _, t := range []string{"vendor/qcom", "vendor/google_devices"} {
-			pathPattern[0] = t
-			matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
+		// we know inherit-product uses dynamically calculated path. Restrict it even further
+		// for certain path which would yield too many useless matches
+		if len(varPath.chunks) == 2 && varPath.chunks[1] == "/BoardConfigVendor.mk" {
+			pathPattern[0] = "vendor/google_devices"
+			matchingPaths = ctx.findMatchingPaths(pathPattern)
+		} else {
+			for _, t := range []string{"vendor/qcom", "vendor/google_devices"} {
+				pathPattern[0] = t
+				matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
+			}
 		}
 	}
 	// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
-	const maxMatchingFiles = 100
+	const maxMatchingFiles = 150
 	if len(matchingPaths) > maxMatchingFiles {
 		ctx.errorf(v, "there are >%d files matching the pattern, please rewrite it", maxMatchingFiles)
 		return
@@ -1411,6 +1513,38 @@
 	return filepath.Join(ctx.outputDir, loadedModuleDir, loadedModuleName)
 }
 
+func (ctx *parseContext) addSoongNamespace(ns string) {
+	if _, ok := ctx.soongNamespaces[ns]; ok {
+		return
+	}
+	ctx.soongNamespaces[ns] = make(map[string]bool)
+}
+
+func (ctx *parseContext) hasSoongNamespace(name string) bool {
+	_, ok := ctx.soongNamespaces[name]
+	return ok
+}
+
+func (ctx *parseContext) updateSoongNamespace(replace bool, namespaceName string, varNames []string) {
+	ctx.addSoongNamespace(namespaceName)
+	vars := ctx.soongNamespaces[namespaceName]
+	if replace {
+		vars = make(map[string]bool)
+		ctx.soongNamespaces[namespaceName] = vars
+	}
+	for _, v := range varNames {
+		vars[v] = true
+	}
+}
+
+func (ctx *parseContext) hasNamespaceVar(namespaceName string, varName string) bool {
+	vars, ok := ctx.soongNamespaces[namespaceName]
+	if ok {
+		_, ok = vars[varName]
+	}
+	return ok
+}
+
 func (ss *StarlarkScript) String() string {
 	return NewGenerateContext(ss).emit()
 }
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 88c9c38..a14c7a4 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -666,7 +666,9 @@
 $(info $(dir $(lastword $(foobar))))
 $(info $(abspath foo/bar))
 $(info $(notdir foo/bar))
-
+$(call add_soong_config_namespace,snsconfig)
+$(call add_soong_config_var_value,snsconfig,imagetype,odm_image)
+PRODUCT_COPY_FILES := $(call copy-files,$(wildcard foo*.mk),etc)
 `,
 		expected: `load("//build/make/core:product_config.rbc", "rblf")
 
@@ -684,6 +686,9 @@
   rblf.mkinfo("product.mk", rblf.dir((_foobar).split()[-1]))
   rblf.mkinfo("product.mk", rblf.abspath("foo/bar"))
   rblf.mkinfo("product.mk", rblf.notdir("foo/bar"))
+  rblf.add_soong_config_namespace(g, "snsconfig")
+  rblf.add_soong_config_var_value(g, "snsconfig", "imagetype", "odm_image")
+  cfg["PRODUCT_COPY_FILES"] = rblf.copy_files(rblf.expand_wildcard("foo*.mk"), "etc")
 `,
 	},
 	{
@@ -759,6 +764,25 @@
 `,
 	},
 	{
+		desc:   "soong namespace assignments",
+		mkname: "product.mk",
+		in: `
+SOONG_CONFIG_NAMESPACES += cvd
+SOONG_CONFIG_cvd += launch_configs
+SOONG_CONFIG_cvd_launch_configs += cvd_config_auto.json
+SOONG_CONFIG_cvd += grub_config
+SOONG_CONFIG_cvd_grub_config += grub.cfg
+`,
+		expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+  cfg = rblf.cfg(handle)
+  rblf.add_soong_config_namespace(g, "cvd")
+  rblf.add_soong_config_var_value(g, "cvd", "launch_configs", "cvd_config_auto.json")
+  rblf.add_soong_config_var_value(g, "cvd", "grub_config", "grub.cfg")
+`,
+	},
+	{
 		desc:   "string split",
 		mkname: "product.mk",
 		in: `
diff --git a/mk2rbc/types.go b/mk2rbc/types.go
index 4a6d376..ebd52d8 100644
--- a/mk2rbc/types.go
+++ b/mk2rbc/types.go
@@ -31,6 +31,16 @@
 	starlarkTypeVoid    starlarkType = iota
 )
 
+type hiddenArgType int
+
+const (
+	// Some functions have an implicitly emitted first argument, which may be
+	// a global ('g') or configuration ('cfg') variable.
+	hiddenArgNone   hiddenArgType = iota
+	hiddenArgGlobal hiddenArgType = iota
+	hiddenArgConfig hiddenArgType = iota
+)
+
 type varClass int
 
 const (
diff --git a/rust/builder.go b/rust/builder.go
index 6c44166..a5b3ab9 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -332,8 +332,11 @@
 	rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
 	docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
 
-	// Silence warnings about renamed lints
-	rustdocFlags = append(rustdocFlags, " -A renamed_and_removed_lints")
+	// Silence warnings about renamed lints for third-party crates
+	modulePath := android.PathForModuleSrc(ctx).String()
+	if android.IsThirdPartyPath(modulePath) {
+		rustdocFlags = append(rustdocFlags, " -A renamed_and_removed_lints")
+	}
 
 	// Yes, the same out directory is used simultaneously by all rustdoc builds.
 	// This is what cargo does. The docs for individual crates get generated to
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index ca110a2..e527aea 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -6,7 +6,6 @@
 	// for an example.
 	// TODO(b/160223496): enable rustfmt globally.
 	RustAllowedPaths = []string{
-		"bionic/libc",
 		"device/google/cuttlefish",
 		"external/adhd",
 		"external/crosvm",
@@ -24,6 +23,7 @@
 		"system/extras/profcollectd",
 		"system/extras/simpleperf",
 		"system/hardware/interfaces/keystore2",
+		"system/librustutils",
 		"system/logging/rust",
 		"system/security",
 		"system/tools/aidl",
diff --git a/rust/config/global.go b/rust/config/global.go
index c390711..e5b334d 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.53.0"
+	RustDefaultVersion = "1.54.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
diff --git a/rust/coverage.go b/rust/coverage.go
index dac526a..050b811 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -55,7 +55,7 @@
 		flags.Coverage = true
 		coverage := ctx.GetDirectDepWithTag(CovLibraryName, cc.CoverageDepTag).(cc.LinkableInterface)
 		flags.RustFlags = append(flags.RustFlags,
-			"-Z instrument-coverage", "-g", "-C link-dead-code")
+			"-Z instrument-coverage", "-g")
 		flags.LinkFlags = append(flags.LinkFlags,
 			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
 		deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 4b6c9d4..f3cd375 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -56,7 +56,7 @@
 	fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
 	buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
 
-	rustcCoverageFlags := []string{"-Z instrument-coverage", " -g ", "-C link-dead-code"}
+	rustcCoverageFlags := []string{"-Z instrument-coverage", " -g "}
 	for _, flag := range rustcCoverageFlags {
 		missingErrorStr := "missing rustc flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
 		containsErrorStr := "contains rustc flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 3d14d51..a4ba4bd 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -47,6 +47,9 @@
 	"-C llvm-args=-sanitizer-coverage-trace-geps",
 	"-C llvm-args=-sanitizer-coverage-prune-blocks=0",
 
+	// See https://github.com/rust-fuzz/cargo-fuzz/pull/193
+	"-C link-dead-code",
+
 	// Sancov breaks with lto
 	// TODO: Remove when https://bugs.llvm.org/show_bug.cgi?id=41734 is resolved and sancov works with LTO
 	"-C lto=no",