Merge "bazel overlay: fix regression to "list of string" bpdocs type."
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index e5b91e5..8c70a56 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -235,6 +235,7 @@
 libc_headers(minSdkVersion:apex_inherit)
 libc_headers_arch(minSdkVersion:apex_inherit)
 libcap(minSdkVersion:29)
+libclang_rt.hwasan-aarch64-android.llndk(minSdkVersion:(no version))
 libcodec2(minSdkVersion:29)
 libcodec2_headers(minSdkVersion:29)
 libcodec2_hidl@1.0(minSdkVersion:29)
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 803e0c5..ee9fc81 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -100,6 +100,8 @@
 			"new_allowed_deps": newAllowedDeps.String(),
 		},
 	})
+
+	ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
 }
 
 func (s *apexDepsInfoSingleton) MakeVars(ctx android.MakeVarsContext) {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 3db2d65..09af649 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -32,7 +32,7 @@
 	bindgenClangVersion = "clang-r383902c"
 
 	//TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
-	_ = pctx.SourcePathVariable("bindgenCmd", "out/host/${config.HostPrebuiltTag}/bin/bindgen")
+	_ = pctx.HostBinToolVariable("bindgenCmd", "bindgen")
 	_ = pctx.SourcePathVariable("bindgenClang",
 		"${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/bin/clang")
 	_ = pctx.SourcePathVariable("bindgenLibClang",
diff --git a/rust/protobuf.go b/rust/protobuf.go
index ebb1c3c..28a4597 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -22,9 +22,18 @@
 	defaultProtobufFlags = []string{""}
 )
 
+type PluginType int
+
+const (
+	Protobuf PluginType = iota
+	Grpc
+)
+
 func init() {
 	android.RegisterModuleType("rust_protobuf", RustProtobufFactory)
 	android.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
+	android.RegisterModuleType("rust_grpcio", RustGrpcioFactory)
+	android.RegisterModuleType("rust_grpcio_host", RustGrpcioHostFactory)
 }
 
 var _ SourceProvider = (*protobufDecorator)(nil)
@@ -41,15 +50,18 @@
 	*BaseSourceProvider
 
 	Properties ProtobufProperties
+	plugin     PluginType
 }
 
 func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
 	var protoFlags android.ProtoFlags
-	pluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+	var pluginPath android.Path
 
 	protoFlags.OutTypeFlag = "--rust_out"
+	outDir := android.PathForModuleOut(ctx)
 
-	protoFlags.Flags = append(protoFlags.Flags, " --plugin="+pluginPath.String())
+	pluginPath, protoFlags = proto.setupPlugin(ctx, protoFlags, outDir)
+
 	protoFlags.Flags = append(protoFlags.Flags, defaultProtobufFlags...)
 	protoFlags.Flags = append(protoFlags.Flags, proto.Properties.Proto_flags...)
 
@@ -60,7 +72,6 @@
 		ctx.PropertyErrorf("proto", "invalid path to proto file")
 	}
 
-	outDir := android.PathForModuleOut(ctx)
 	stem := proto.BaseSourceProvider.getStem(ctx)
 	// rust protobuf-codegen output <stem>.rs
 	stemFile := android.PathForModuleOut(ctx, stem+".rs")
@@ -79,6 +90,23 @@
 	return modFile
 }
 
+func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Path, android.ProtoFlags) {
+	var pluginPath android.Path
+
+	if proto.plugin == Protobuf {
+		pluginPath = ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+		protoFlags.Flags = append(protoFlags.Flags, "--plugin="+pluginPath.String())
+	} else if proto.plugin == Grpc {
+		pluginPath = ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
+		protoFlags.Flags = append(protoFlags.Flags, "--grpc_out="+outDir.String())
+		protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-grpc="+pluginPath.String())
+	} else {
+		ctx.ModuleErrorf("Unknown protobuf plugin type requested")
+	}
+
+	return pluginPath, protoFlags
+}
+
 func (proto *protobufDecorator) SourceProviderProps() []interface{} {
 	return append(proto.BaseSourceProvider.SourceProviderProps(), &proto.Properties)
 }
@@ -104,10 +132,34 @@
 	return module.Init()
 }
 
+func RustGrpcioFactory() android.Module {
+	module, _ := NewRustGrpcio(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// A host-only variant of rust_protobuf. Refer to rust_protobuf for more details.
+func RustGrpcioHostFactory() android.Module {
+	module, _ := NewRustGrpcio(android.HostSupported)
+	return module.Init()
+}
+
 func NewRustProtobuf(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
 	protobuf := &protobufDecorator{
 		BaseSourceProvider: NewSourceProvider(),
 		Properties:         ProtobufProperties{},
+		plugin:             Protobuf,
+	}
+
+	module := NewSourceProviderModule(hod, protobuf, false)
+
+	return module, protobuf
+}
+
+func NewRustGrpcio(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
+	protobuf := &protobufDecorator{
+		BaseSourceProvider: NewSourceProvider(),
+		Properties:         ProtobufProperties{},
+		plugin:             Grpc,
 	}
 
 	module := NewSourceProviderModule(hod, protobuf, false)
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index bd11a5a..7c39071 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -15,8 +15,10 @@
 package rust
 
 import (
-	"android/soong/android"
+	"strings"
 	"testing"
+
+	"android/soong/android"
 )
 
 func TestRustProtobuf(t *testing.T) {
@@ -28,12 +30,41 @@
 			source_stem: "buf",
 		}
 	`)
-	// Check that there's a rule to generate the expected output
-	_ = ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
-
 	// Check that libprotobuf is added as a dependency.
 	librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
 	if !android.InList("libprotobuf", librust_proto.Properties.AndroidMkDylibs) {
 		t.Errorf("libprotobuf dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
 	}
+
+	// Make sure the correct plugin is being used.
+	librust_proto_out := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
+	cmd := librust_proto_out.RuleParams.Command
+	if w := "protoc-gen-rust"; !strings.Contains(cmd, w) {
+		t.Errorf("expected %q in %q", w, cmd)
+	}
+
+}
+
+func TestRustGrpcio(t *testing.T) {
+	ctx := testRust(t, `
+		rust_grpcio {
+			name: "librust_grpcio",
+			proto: "buf.proto",
+			crate_name: "rust_grpcio",
+			source_stem: "buf",
+		}
+	`)
+
+	// Check that libprotobuf is added as a dependency.
+	librust_grpcio_module := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_dylib").Module().(*Module)
+	if !android.InList("libprotobuf", librust_grpcio_module.Properties.AndroidMkDylibs) {
+		t.Errorf("libprotobuf dependency missing for rust_grpcio (dependency missing from AndroidMkDylibs)")
+	}
+
+	// Make sure the correct plugin is being used.
+	librust_grpcio_out := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_source").Output("buf.rs")
+	cmd := librust_grpcio_out.RuleParams.Command
+	if w := "protoc-gen-grpc"; !strings.Contains(cmd, w) {
+		t.Errorf("expected %q in %q", w, cmd)
+	}
 }
diff --git a/rust/testing.go b/rust/testing.go
index 42b0da1..4a1894c 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -132,6 +132,8 @@
 	ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
 	ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
 	ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
+	ctx.RegisterModuleType("rust_grpcio", RustGrpcioFactory)
+	ctx.RegisterModuleType("rust_grpcio_host", RustGrpcioHostFactory)
 	ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
 	ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
 	ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index c5702c0..978553d 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -15,6 +15,8 @@
 package build
 
 import (
+	"io/ioutil"
+	"os"
 	"path/filepath"
 	"strings"
 )
@@ -32,12 +34,6 @@
 	bazelExecutable := filepath.Join("tools", "bazel")
 	args := []string{
 		"build",
-		"--verbose_failures",
-		"--show_progress_rate_limit=0.05",
-		"--color=yes",
-		"--curses=yes",
-		"--show_timestamps",
-		"--announce_rc",
 		"--output_groups=" + outputGroups,
 		"//:" + config.TargetProduct() + "-" + config.TargetBuildVariant(),
 	}
@@ -51,4 +47,57 @@
 	cmd.Dir = filepath.Join(config.OutDir(), "..")
 	ctx.Status.Status("Starting Bazel..")
 	cmd.RunAndStreamOrFatal()
+
+	// Obtain the Bazel output directory for ninja_build.
+	infoArgs := []string{
+		"info",
+		"output_path",
+	}
+
+	infoCmd := Command(ctx, config, "bazel", bazelExecutable, infoArgs...)
+
+	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())
+	// TODO: Don't hardcode out/ as the bazel output directory. This is
+	// currently hardcoded as ninja_build.output_root.
+	bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
+
+	symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
+}
+
+// For all files F recursively under rootPath/relativePath, creates symlinks
+// such that OutDir/F resolves to rootPath/F via symlinks.
+func symlinkOutdir(ctx Context, config Config, rootPath string, relativePath string) {
+	destDir := filepath.Join(rootPath, relativePath)
+	os.MkdirAll(destDir, 0755)
+	files, err := ioutil.ReadDir(destDir)
+	if err != nil {
+		ctx.Fatal(err)
+	}
+	for _, f := range files {
+		destPath := filepath.Join(destDir, f.Name())
+		srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
+		if statResult, err := os.Stat(srcPath); err == nil {
+			if statResult.Mode().IsDir() && f.IsDir() {
+				// Directory under OutDir already exists, so recurse on its contents.
+				symlinkOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
+			} else if !statResult.Mode().IsDir() && !f.IsDir() {
+				// File exists both in source and destination, and it's not a directory
+				// in either location. Do nothing.
+				// This can arise for files which are generated under OutDir outside of
+				// soong_build, such as .bootstrap files.
+			} else {
+				// File is a directory in one location but not the other. Raise an error.
+				ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath)
+			}
+		} else if os.IsNotExist(err) {
+			// Create symlink srcPath -> fullDestPath.
+			os.Symlink(destPath, srcPath)
+		} else {
+			ctx.Fatalf("Unable to stat %s: %s", srcPath, err)
+		}
+	}
 }
diff --git a/ui/build/exec.go b/ui/build/exec.go
index 053bbae..8f92269 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -66,8 +66,11 @@
 }
 
 func (c *Cmd) report() {
-	if c.Cmd.ProcessState != nil {
-		rusage := c.Cmd.ProcessState.SysUsage().(*syscall.Rusage)
+	if state := c.Cmd.ProcessState; state != nil {
+		if c.ctx.Metrics != nil {
+			c.ctx.Metrics.EventTracer.AddProcResInfo(c.name, state)
+		}
+		rusage := state.SysUsage().(*syscall.Rusage)
 		c.ctx.Verbosef("%q finished with exit code %d (%s real, %s user, %s system, %dMB maxrss)",
 			c.name, c.Cmd.ProcessState.ExitCode(),
 			time.Since(c.started).Round(time.Millisecond),
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index 5a62847..6becfd1 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -15,6 +15,8 @@
 package metrics
 
 import (
+	"os"
+	"syscall"
 	"time"
 
 	"android/soong/ui/metrics/metrics_proto"
@@ -31,11 +33,15 @@
 
 	// the time that the event started to occur.
 	start time.Time
+
+	// The list of process resource information that was executed
+	procResInfo []*soong_metrics_proto.ProcessResourceInfo
 }
 
 type EventTracer interface {
 	Begin(name, desc string, thread tracer.Thread)
 	End(thread tracer.Thread) soong_metrics_proto.PerfInfo
+	AddProcResInfo(string, *os.ProcessState)
 }
 
 type eventTracerImpl struct {
@@ -48,6 +54,34 @@
 	return time.Now()
 }
 
+// AddProcResInfo adds information on an executed process such as max resident set memory
+// and the number of voluntary context switches.
+func (t *eventTracerImpl) AddProcResInfo(name string, state *os.ProcessState) {
+	if len(t.activeEvents) < 1 {
+		return
+	}
+
+	rusage := state.SysUsage().(*syscall.Rusage)
+	// The implementation of the metrics system is a stacked based system. The steps of the
+	// build system in the UI layer is sequential so the Begin function is invoked when a
+	// function (or scoped code) is invoked. That is translated to a new event which is added
+	// at the end of the activeEvents array. When the invoking function is completed, End is
+	// invoked which is a pop operation from activeEvents.
+	curEvent := &t.activeEvents[len(t.activeEvents)-1]
+	curEvent.procResInfo = append(curEvent.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
+		Name:             proto.String(name),
+		UserTimeMicros:   proto.Uint64(uint64(rusage.Utime.Usec)),
+		SystemTimeMicros: proto.Uint64(uint64(rusage.Stime.Usec)),
+		MinorPageFaults:  proto.Uint64(uint64(rusage.Minflt)),
+		MajorPageFaults:  proto.Uint64(uint64(rusage.Majflt)),
+		// ru_inblock and ru_oublock are measured in blocks of 512 bytes.
+		IoInputKb:                  proto.Uint64(uint64(rusage.Inblock / 2)),
+		IoOutputKb:                 proto.Uint64(uint64(rusage.Oublock / 2)),
+		VoluntaryContextSwitches:   proto.Uint64(uint64(rusage.Nvcsw)),
+		InvoluntaryContextSwitches: proto.Uint64(uint64(rusage.Nivcsw)),
+	})
+}
+
 func (t *eventTracerImpl) Begin(name, desc string, _ tracer.Thread) {
 	t.activeEvents = append(t.activeEvents, event{name: name, desc: desc, start: _now()})
 }
@@ -61,9 +95,10 @@
 	realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
 
 	return soong_metrics_proto.PerfInfo{
-		Desc:      proto.String(lastEvent.desc),
-		Name:      proto.String(lastEvent.name),
-		StartTime: proto.Uint64(uint64(lastEvent.start.UnixNano())),
-		RealTime:  proto.Uint64(realTime),
+		Desc:                  proto.String(lastEvent.desc),
+		Name:                  proto.String(lastEvent.name),
+		StartTime:             proto.Uint64(uint64(lastEvent.start.UnixNano())),
+		RealTime:              proto.Uint64(realTime),
+		ProcessesResourceInfo: lastEvent.procResInfo,
 	}
 }