Add build tracing

This creates a rotating build.trace.gz in the out directory that can be
loaded with chrome://tracing. It'll include start and end timings for
make/soong/kati/ninja, and it will import and time-correct the ninja log
files.

Test: m -j; load out/build.trace.gz in chrome://tracing
Test: multiproduct_kati -keep; load out/multiproduct*/build.trace.gz
Change-Id: Ic060fa9515eb88d95dbe16712479dae9dffcf626
diff --git a/ui/build/context.go b/ui/build/context.go
index 59474f5..8144e58 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -18,8 +18,10 @@
 	"context"
 	"io"
 	"os"
+	"time"
 
 	"android/soong/ui/logger"
+	"android/soong/ui/tracer"
 )
 
 type StdioInterface interface {
@@ -55,10 +57,41 @@
 // Context combines a context.Context, logger.Logger, and StdIO redirection.
 // These all are agnostic of the current build, and may be used for multiple
 // builds, while the Config objects contain per-build information.
-type Context *ContextImpl
+type Context struct{ *ContextImpl }
 type ContextImpl struct {
 	context.Context
 	logger.Logger
 
 	StdioInterface
+
+	Thread tracer.Thread
+	Tracer tracer.Tracer
+}
+
+// BeginTrace starts a new Duration Event.
+func (c ContextImpl) BeginTrace(name string) {
+	if c.Tracer != nil {
+		c.Tracer.Begin(name, c.Thread)
+	}
+}
+
+// EndTrace finishes the last Duration Event.
+func (c ContextImpl) EndTrace() {
+	if c.Tracer != nil {
+		c.Tracer.End(c.Thread)
+	}
+}
+
+// CompleteTrace writes a trace with a beginning and end times.
+func (c ContextImpl) CompleteTrace(name string, begin, end uint64) {
+	if c.Tracer != nil {
+		c.Tracer.Complete(name, c.Thread, begin, end)
+	}
+}
+
+// ImportNinjaLog imports a .ninja_log file into the tracer.
+func (c ContextImpl) ImportNinjaLog(filename string, startOffset time.Time) {
+	if c.Tracer != nil {
+		c.Tracer.ImportNinjaLog(c.Thread, filename, startOffset)
+	}
 }