Merge "Remove obsolete environment variables from ninja.go allowlist."
diff --git a/cc/builder.go b/cc/builder.go
index 439e372..5545a5b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -568,8 +568,11 @@
 			ccCmd = "clang++"
 			moduleFlags = cppflags
 			moduleToolingFlags = toolingCppflags
+		case ".h", ".hpp":
+			ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
+			continue
 		default:
-			ctx.ModuleErrorf("File %s has unknown extension", srcFile)
+			ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .s, .S, .c, .cpp, .cc, .cxx, .mm", srcFile)
 			continue
 		}
 
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 563ce76..a548452 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -21,7 +21,6 @@
 	"android.hardware.automotive.occupant_awareness-ndk_platform",
 	"android.hardware.light-ndk_platform",
 	"android.hardware.identity-ndk_platform",
-	"android.hardware.keymint-ndk_platform",
 	"android.hardware.keymint-unstable-ndk_platform",
 	"android.hardware.nfc@1.2",
 	"android.hardware.power-ndk_platform",
diff --git a/cc/strip.go b/cc/strip.go
index 1f10a74..b1f34bb 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -23,19 +23,23 @@
 // StripProperties defines the type of stripping applied to the module.
 type StripProperties struct {
 	Strip struct {
-		// whether to disable all stripping.
+		// none forces all stripping to be disabled.
+		// Device modules default to stripping enabled leaving mini debuginfo.
+		// Host modules default to stripping disabled, but can be enabled by setting any other
+		// strip boolean property.
 		None *bool `android:"arch_variant"`
 
-		// whether to strip everything, including the mini debug info.
+		// all forces stripping everything, including the mini debug info.
 		All *bool `android:"arch_variant"`
 
-		// whether to keep the symbols.
+		// keep_symbols enables stripping but keeps all symbols.
 		Keep_symbols *bool `android:"arch_variant"`
 
-		// keeps only the symbols defined here.
+		// keep_symbols_list specifies a list of symbols to keep if keep_symbols is enabled.
+		// If it is unset then all symbols are kept.
 		Keep_symbols_list []string `android:"arch_variant"`
 
-		// whether to keep the symbols and the debug frames.
+		// keep_symbols_and_debug_frame enables stripping but keeps all symbols and debug frames.
 		Keep_symbols_and_debug_frame *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
@@ -47,8 +51,12 @@
 
 // NeedsStrip determines if stripping is required for a module.
 func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool {
-	// TODO(ccross): enable host stripping when Kati is enabled? Make never had support for stripping host binaries.
-	return (!actx.Config().KatiEnabled() || actx.Device()) && !Bool(stripper.StripProperties.Strip.None)
+	forceDisable := Bool(stripper.StripProperties.Strip.None)
+	defaultEnable := (!actx.Config().KatiEnabled() || actx.Device())
+	forceEnable := Bool(stripper.StripProperties.Strip.All) ||
+		Bool(stripper.StripProperties.Strip.Keep_symbols) ||
+		Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame)
+	return !forceDisable && (forceEnable || defaultEnable)
 }
 
 func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index e6643f5..df31d60 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -13,6 +13,7 @@
 		"external/rust",
 		"external/vm_tools/p9",
 		"frameworks/native/libs/binder/rust",
+		"packages/modules/DnsResolver",
 		"packages/modules/Virtualization",
 		"prebuilts/rust",
 		"system/bt",
diff --git a/rust/project_json.go b/rust/project_json.go
index 8d9e50c..c4d60ad 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -75,12 +75,16 @@
 	android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
 }
 
-// librarySource finds the main source file (.rs) for a crate.
-func librarySource(ctx android.SingletonContext, rModule *Module, rustLib *libraryDecorator) (string, bool) {
-	srcs := rustLib.baseCompiler.Properties.Srcs
+// crateSource finds the main source file (.rs) for a crate.
+func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) {
+	srcs := comp.Properties.Srcs
 	if len(srcs) != 0 {
 		return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
 	}
+	rustLib, ok := rModule.compiler.(*libraryDecorator)
+	if !ok {
+		return "", false
+	}
 	if !rustLib.source() {
 		return "", false
 	}
@@ -132,8 +136,15 @@
 	if rModule.compiler == nil {
 		return 0, "", false
 	}
-	rustLib, ok := rModule.compiler.(*libraryDecorator)
-	if !ok {
+	var comp *baseCompiler
+	switch c := rModule.compiler.(type) {
+	case *libraryDecorator:
+		comp = c.baseCompiler
+	case *binaryDecorator:
+		comp = c.baseCompiler
+	case *testDecorator:
+		comp = c.binaryDecorator.baseCompiler
+	default:
 		return 0, "", false
 	}
 	moduleName := ctx.ModuleName(module)
@@ -146,12 +157,12 @@
 		return cInfo.ID, crateName, true
 	}
 	crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
-	rootModule, ok := librarySource(ctx, rModule, rustLib)
+	rootModule, ok := crateSource(ctx, rModule, comp)
 	if !ok {
 		return 0, "", false
 	}
 	crate.RootModule = rootModule
-	crate.Edition = rustLib.baseCompiler.edition()
+	crate.Edition = comp.edition()
 
 	deps := make(map[string]int)
 	singleton.mergeDependencies(ctx, module, &crate, deps)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 16699c1..aff1697 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -67,6 +67,37 @@
 	return crates
 }
 
+// validateCrate ensures that a crate can be parsed as a map.
+func validateCrate(t *testing.T, crate interface{}) map[string]interface{} {
+	c, ok := crate.(map[string]interface{})
+	if !ok {
+		t.Fatalf("Unexpected type for crate: %v", c)
+	}
+	return c
+}
+
+// validateDependencies parses the dependencies for a crate. It returns a list
+// of the dependencies name.
+func validateDependencies(t *testing.T, crate map[string]interface{}) []string {
+	var dependencies []string
+	deps, ok := crate["deps"].([]interface{})
+	if !ok {
+		t.Errorf("Unexpected format for deps: %v", crate["deps"])
+	}
+	for _, dep := range deps {
+		d, ok := dep.(map[string]interface{})
+		if !ok {
+			t.Errorf("Unexpected format for dependency: %v", dep)
+		}
+		name, ok := d["name"].(string)
+		if !ok {
+			t.Errorf("Dependency is missing the name key: %v", d)
+		}
+		dependencies = append(dependencies, name)
+	}
+	return dependencies
+}
+
 func TestProjectJsonDep(t *testing.T) {
 	bp := `
 	rust_library {
@@ -85,6 +116,29 @@
 	validateJsonCrates(t, jsonContent)
 }
 
+func TestProjectJsonBinary(t *testing.T) {
+	bp := `
+	rust_binary {
+		name: "liba",
+		srcs: ["a/src/lib.rs"],
+		crate_name: "a"
+	}
+	`
+	jsonContent := testProjectJson(t, bp)
+	crates := validateJsonCrates(t, jsonContent)
+	for _, c := range crates {
+		crate := validateCrate(t, c)
+		rootModule, ok := crate["root_module"].(string)
+		if !ok {
+			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+		}
+		if rootModule == "a/src/lib.rs" {
+			return
+		}
+	}
+	t.Errorf("Entry for binary %q not found: %s", "a", jsonContent)
+}
+
 func TestProjectJsonBindGen(t *testing.T) {
 	bp := `
 	rust_library {
@@ -116,10 +170,7 @@
 	jsonContent := testProjectJson(t, bp)
 	crates := validateJsonCrates(t, jsonContent)
 	for _, c := range crates {
-		crate, ok := c.(map[string]interface{})
-		if !ok {
-			t.Fatalf("Unexpected type for crate: %v", c)
-		}
+		crate := validateCrate(t, c)
 		rootModule, ok := crate["root_module"].(string)
 		if !ok {
 			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
@@ -133,16 +184,8 @@
 		}
 		// Check that libbindings1 does not depend on itself.
 		if strings.Contains(rootModule, "libbindings1") {
-			deps, ok := crate["deps"].([]interface{})
-			if !ok {
-				t.Errorf("Unexpected format for deps: %v", crate["deps"])
-			}
-			for _, dep := range deps {
-				d, ok := dep.(map[string]interface{})
-				if !ok {
-					t.Errorf("Unexpected format for dep: %v", dep)
-				}
-				if d["name"] == "bindings1" {
+			for _, depName := range validateDependencies(t, crate) {
+				if depName == "bindings1" {
 					t.Errorf("libbindings1 depends on itself")
 				}
 			}
@@ -171,20 +214,18 @@
 	`
 	jsonContent := testProjectJson(t, bp)
 	crates := validateJsonCrates(t, jsonContent)
-	for _, crate := range crates {
-		c := crate.(map[string]interface{})
-		if c["root_module"] == "b/src/lib.rs" {
-			deps, ok := c["deps"].([]interface{})
-			if !ok {
-				t.Errorf("Unexpected format for deps: %v", c["deps"])
-			}
+	for _, c := range crates {
+		crate := validateCrate(t, c)
+		rootModule, ok := crate["root_module"].(string)
+		if !ok {
+			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+		}
+		// Make sure that b has 2 different dependencies.
+		if rootModule == "b/src/lib.rs" {
 			aCount := 0
-			for _, dep := range deps {
-				d, ok := dep.(map[string]interface{})
-				if !ok {
-					t.Errorf("Unexpected format for dep: %v", dep)
-				}
-				if d["name"] == "a" {
+			deps := validateDependencies(t, crate)
+			for _, depName := range deps {
+				if depName == "a" {
 					aCount++
 				}
 			}
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 2d36f67..fac0461 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -24,6 +24,28 @@
 	"android/soong/ui/metrics"
 )
 
+func getBazelInfo(ctx Context, config Config, bazelExecutable string, query string) string {
+	infoCmd := Command(ctx, config, "bazel", bazelExecutable)
+
+	if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+		infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
+	}
+
+	// Obtain the output directory path in the execution root.
+	infoCmd.Args = append(infoCmd.Args,
+		"info",
+		query,
+	)
+
+	infoCmd.Environment.Set("DIST_DIR", config.DistDir())
+	infoCmd.Environment.Set("SHELL", "/bin/bash")
+
+	infoCmd.Dir = filepath.Join(config.OutDir(), "..")
+
+	queryResult := strings.TrimSpace(string(infoCmd.OutputOrFatal()))
+	return queryResult
+}
+
 // Main entry point to construct the Bazel build command line, environment
 // variables and post-processing steps (e.g. converge output directories)
 func runBazel(ctx Context, config Config) {
@@ -76,16 +98,36 @@
 		"--slim_profile=true",
 	)
 
-	// Append custom build flags to the Bazel command. Changes to these flags
-	// may invalidate Bazel's analysis cache.
-	if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
-		cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
-	}
+	if config.UseRBE() {
+		for _, envVar := range []string{
+			// RBE client
+			"RBE_compare",
+			"RBE_exec_strategy",
+			"RBE_invocation_id",
+			"RBE_log_dir",
+			"RBE_platform",
+			"RBE_remote_accept_cache",
+			"RBE_remote_update_cache",
+			"RBE_server_address",
+			// TODO: remove old FLAG_ variables.
+			"FLAG_compare",
+			"FLAG_exec_root",
+			"FLAG_exec_strategy",
+			"FLAG_invocation_id",
+			"FLAG_log_dir",
+			"FLAG_platform",
+			"FLAG_remote_accept_cache",
+			"FLAG_remote_update_cache",
+			"FLAG_server_address",
+		} {
+			cmd.Args = append(cmd.Args,
+				"--action_env="+envVar)
+		}
 
-	// Append the label of the default ninja_build target.
-	cmd.Args = append(cmd.Args,
-		"//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
-	)
+		// We need to calculate --RBE_exec_root ourselves
+		ctx.Println("Getting Bazel execution_root...")
+		cmd.Args = append(cmd.Args, "--action_env=RBE_exec_root="+getBazelInfo(ctx, config, bazelExecutable, "execution_root"))
+	}
 
 	// Ensure that the PATH environment variable value used in the action
 	// environment is the restricted set computed from soong_ui, and not a
@@ -95,6 +137,18 @@
 		cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
 	}
 
+	// Append custom build flags to the Bazel command. Changes to these flags
+	// may invalidate Bazel's analysis cache.
+	// These should be appended as the final args, so that they take precedence.
+	if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
+		cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
+	}
+
+	// Append the label of the default ninja_build target.
+	cmd.Args = append(cmd.Args,
+		"//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
+	)
+
 	cmd.Environment.Set("DIST_DIR", config.DistDir())
 	cmd.Environment.Set("SHELL", "/bin/bash")
 
@@ -113,24 +167,8 @@
 	// Ensure that the $OUT_DIR contains the expected set of files by symlinking
 	// the files from the execution root's output direction into $OUT_DIR.
 
-	// Obtain the Bazel output directory for ninja_build.
-	infoCmd := Command(ctx, config, "bazel", bazelExecutable)
-
-	if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
-		infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
-	}
-
-	// Obtain the output directory path in the execution root.
-	infoCmd.Args = append(infoCmd.Args,
-		"info",
-		"output_path",
-	)
-
-	infoCmd.Environment.Set("DIST_DIR", config.DistDir())
-	infoCmd.Environment.Set("SHELL", "/bin/bash")
-	infoCmd.Dir = filepath.Join(config.OutDir(), "..")
-	ctx.Status.Status("Getting Bazel Info..")
-	outputBasePath := string(infoCmd.OutputOrFatal())
+	ctx.Println("Getting Bazel output_path...")
+	outputBasePath := getBazelInfo(ctx, config, bazelExecutable, "output_path")
 	// TODO: Don't hardcode out/ as the bazel output directory. This is
 	// currently hardcoded as ninja_build.output_root.
 	bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")