Merge "add flag_value.redacted" into main
diff --git a/android/arch.go b/android/arch.go
index 3224c3a..cd8882b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -975,12 +975,18 @@
 			panic(fmt.Errorf("unexpected tag format %q", field.Tag))
 		}
 		// these tags don't need to be present in the runtime generated struct type.
-		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path", "replace_instead_of_append"})
+		// However replace_instead_of_append does, because it's read by the blueprint
+		// property extending util functions, which can operate on these generated arch
+		// property structs.
+		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
 		if len(values) > 0 {
-			panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
+			if values[0] != "replace_instead_of_append" || len(values) > 1 {
+				panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
+			}
+			field.Tag = `android:"replace_instead_of_append"`
+		} else {
+			field.Tag = ``
 		}
-
-		field.Tag = ``
 		return true, field
 	}
 	return false, field
diff --git a/java/robolectric.go b/java/robolectric.go
index 9e8850c..18386c9 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -46,6 +46,7 @@
 var (
 	roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
 	roboRuntimesTag     = dependencyTag{name: "roboRuntimes"}
+	roboRuntimeOnlyTag  = dependencyTag{name: "roboRuntimeOnlyTag"}
 )
 
 type robolectricProperties struct {
@@ -70,6 +71,9 @@
 	// Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric
 	// to use.  /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
 	Upstream *bool
+
+	// Use strict mode to limit access of Robolectric API directly. See go/roboStrictMode
+	Strict_mode *bool
 }
 
 type robolectricTest struct {
@@ -112,7 +116,7 @@
 
 	if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
 		ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
-	} else {
+	} else if !proptools.Bool(r.robolectricProperties.Strict_mode) {
 		if proptools.Bool(r.robolectricProperties.Upstream) {
 			ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream")
 		} else {
@@ -120,6 +124,10 @@
 		}
 	}
 
+	if proptools.Bool(r.robolectricProperties.Strict_mode) {
+		ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
+	}
+
 	ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
 
 	ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
@@ -192,19 +200,25 @@
 		combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar)
 	}
 
-	handleLibDeps := func(dep android.Module) {
+	handleLibDeps := func(dep android.Module, runtimeOnly bool) {
 		m, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
-		r.libs = append(r.libs, ctx.OtherModuleName(dep))
+		if !runtimeOnly {
+			r.libs = append(r.libs, ctx.OtherModuleName(dep))
+		}
 		if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
 			combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars...)
 		}
 	}
 
 	for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
-		handleLibDeps(dep)
+		handleLibDeps(dep, false)
 	}
 	for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
-		handleLibDeps(dep)
+		handleLibDeps(dep, false)
+	}
+	// handle the runtimeOnly tag for strict_mode
+	for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
+		handleLibDeps(dep, true)
 	}
 
 	r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 0b26b80..fab5259 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 
 	"android/soong/android"
@@ -122,41 +123,65 @@
 	// stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point.
 	var outputs android.WritablePaths
 
-	rule := android.NewRuleBuilder(pctx, ctx)
+	for i, shard := range android.ShardPaths(protoFiles, 50) {
+		rule := android.NewRuleBuilder(pctx, ctx)
 
-	for _, protoFile := range protoFiles {
-		// Since we're iterating over the protoFiles already, make sure they're not redeclared in grpcFiles
-		if android.InList(protoFile.String(), grpcFiles.Strings()) {
-			ctx.PropertyErrorf("protos",
-				"A proto can only be added once to either grpc_protos or protos. %q is declared in both properties",
-				protoFile.String())
+		for _, protoFile := range shard {
+			// Since we're iterating over the protoFiles already, make sure they're not redeclared in grpcFiles
+			if android.InList(protoFile.String(), grpcFiles.Strings()) {
+				ctx.PropertyErrorf("protos",
+					"A proto can only be added once to either grpc_protos or protos. %q is declared in both properties",
+					protoFile.String())
+			}
+
+			protoName := strings.TrimSuffix(protoFile.Base(), ".proto")
+			proto.protoNames = append(proto.protoNames, protoName)
+
+			protoOut := android.PathForModuleOut(ctx, protoName+".rs")
+			depFile := android.PathForModuleOut(ctx, protoName+".d")
+
+			ruleOutputs := android.WritablePaths{protoOut, depFile}
+
+			android.ProtoRule(rule, protoFile, protoFlags, protoFlags.Deps, outDir, depFile, ruleOutputs)
+			outputs = append(outputs, ruleOutputs...)
 		}
 
-		protoName := strings.TrimSuffix(protoFile.Base(), ".proto")
-		proto.protoNames = append(proto.protoNames, protoName)
+		ruleName := "protoc"
+		ruleDesc := "protoc"
+		if i > 0 {
+			ruleName += "_" + strconv.Itoa(i+1)
+			ruleDesc += " " + strconv.Itoa(i+1)
+		}
 
-		protoOut := android.PathForModuleOut(ctx, protoName+".rs")
-		depFile := android.PathForModuleOut(ctx, protoName+".d")
-
-		ruleOutputs := android.WritablePaths{protoOut, depFile}
-
-		android.ProtoRule(rule, protoFile, protoFlags, protoFlags.Deps, outDir, depFile, ruleOutputs)
-		outputs = append(outputs, ruleOutputs...)
+		rule.Build(ruleName, ruleDesc)
 	}
 
-	for _, grpcFile := range grpcFiles {
-		grpcName := strings.TrimSuffix(grpcFile.Base(), ".proto")
-		proto.grpcNames = append(proto.grpcNames, grpcName)
+	for i, shard := range android.ShardPaths(grpcFiles, 50) {
+		rule := android.NewRuleBuilder(pctx, ctx)
 
-		// GRPC protos produce two files, a proto.rs and a proto_grpc.rs
-		protoOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+".rs"))
-		grpcOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+grpcSuffix+".rs"))
-		depFile := android.PathForModuleOut(ctx, grpcName+".d")
+		for _, grpcFile := range shard {
+			grpcName := strings.TrimSuffix(grpcFile.Base(), ".proto")
+			proto.grpcNames = append(proto.grpcNames, grpcName)
 
-		ruleOutputs := android.WritablePaths{protoOut, grpcOut, depFile}
+			// GRPC protos produce two files, a proto.rs and a proto_grpc.rs
+			protoOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+".rs"))
+			grpcOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+grpcSuffix+".rs"))
+			depFile := android.PathForModuleOut(ctx, grpcName+".d")
 
-		android.ProtoRule(rule, grpcFile, grpcProtoFlags, grpcProtoFlags.Deps, outDir, depFile, ruleOutputs)
-		outputs = append(outputs, ruleOutputs...)
+			ruleOutputs := android.WritablePaths{protoOut, grpcOut, depFile}
+
+			android.ProtoRule(rule, grpcFile, grpcProtoFlags, grpcProtoFlags.Deps, outDir, depFile, ruleOutputs)
+			outputs = append(outputs, ruleOutputs...)
+		}
+
+		ruleName := "protoc_grpc"
+		ruleDesc := "protoc grpc"
+		if i > 0 {
+			ruleName += "_" + strconv.Itoa(i+1)
+			ruleDesc += " " + strconv.Itoa(i+1)
+		}
+
+		rule.Build(ruleName, ruleDesc)
 	}
 
 	// Check that all proto base filenames are unique as outputs are written to the same directory.
@@ -168,8 +193,6 @@
 
 	android.WriteFileRule(ctx, stemFile, proto.genModFileContents())
 
-	rule.Build("protoc_"+ctx.ModuleName(), "protoc "+ctx.ModuleName())
-
 	// stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point.
 	proto.BaseSourceProvider.OutputFiles = append(android.Paths{stemFile}, outputs.Paths()...)