Merge "Stop dumping obsolete variables"
diff --git a/cc/cc.go b/cc/cc.go
index 0201404..fdfc221 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1195,6 +1195,11 @@
 		return false
 	}
 
+	// Coverage builds have extra symbols.
+	if ctx.mod.isCoverageVariant() {
+		return false
+	}
+
 	if ctx.ctx.Fuchsia() {
 		return false
 	}
diff --git a/java/builder.go b/java/builder.go
index 3a0247d..98f70cd 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -147,7 +147,12 @@
 
 	jarjar = pctx.AndroidStaticRule("jarjar",
 		blueprint.RuleParams{
-			Command:     "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JarjarCmd} process $rulesFile $in $out",
+			Command: "${config.JavaCmd} ${config.JavaVmFlags}" +
+				// b/146418363 Enable Android specific jarjar transformer to drop compat annotations
+				// for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
+				// avoids adding new hiddenapis after jarjar'ing.
+				" -DremoveAndroidCompatAnnotations=true" +
+				" -jar ${config.JarjarCmd} process $rulesFile $in $out",
 			CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
 		},
 		"rulesFile")
diff --git a/ui/build/build.go b/ui/build/build.go
index f3feac2..1122733 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -53,7 +53,6 @@
 {{end -}}
 pool highmem_pool
  depth = {{.HighmemParallel}}
-build _kati_always_build_: phony
 {{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
 subninja {{.KatiPackageNinjaFile}}
 {{end -}}
diff --git a/ui/build/exec.go b/ui/build/exec.go
index e435c53..053bbae 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -19,6 +19,8 @@
 	"io"
 	"os/exec"
 	"strings"
+	"syscall"
+	"time"
 )
 
 // Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
@@ -33,6 +35,8 @@
 	ctx    Context
 	config Config
 	name   string
+
+	started time.Time
 }
 
 func Command(ctx Context, config Config, name string, executable string, args ...string) *Cmd {
@@ -57,7 +61,20 @@
 		c.wrapSandbox()
 	}
 
-	c.ctx.Verboseln(c.Path, c.Args)
+	c.ctx.Verbosef("%q executing %q %v\n", c.name, c.Path, c.Args)
+	c.started = time.Now()
+}
+
+func (c *Cmd) report() {
+	if c.Cmd.ProcessState != nil {
+		rusage := c.Cmd.ProcessState.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),
+			c.Cmd.ProcessState.UserTime().Round(time.Millisecond),
+			c.Cmd.ProcessState.SystemTime().Round(time.Millisecond),
+			rusage.Maxrss/1024)
+	}
 }
 
 func (c *Cmd) Start() error {
@@ -68,21 +85,30 @@
 func (c *Cmd) Run() error {
 	c.prepare()
 	err := c.Cmd.Run()
+	c.report()
 	return err
 }
 
 func (c *Cmd) Output() ([]byte, error) {
 	c.prepare()
 	bytes, err := c.Cmd.Output()
+	c.report()
 	return bytes, err
 }
 
 func (c *Cmd) CombinedOutput() ([]byte, error) {
 	c.prepare()
 	bytes, err := c.Cmd.CombinedOutput()
+	c.report()
 	return bytes, err
 }
 
+func (c *Cmd) Wait() error {
+	err := c.Cmd.Wait()
+	c.report()
+	return err
+}
+
 // StartOrFatal is equivalent to Start, but handles the error with a call to ctx.Fatal
 func (c *Cmd) StartOrFatal() {
 	if err := c.Start(); err != nil {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 8796a4f..2eb7850 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -67,6 +67,7 @@
 		"--ninja_dir=" + config.OutDir(),
 		"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
 		"--no_ninja_prelude",
+		"--use_ninja_phony_output",
 		"--regen",
 		"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
 		"--detect_android_echo",
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index dfc3be1..1b13e5d 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -58,6 +58,7 @@
 	args = append(args, "-f", config.CombinedNinjaFile())
 
 	args = append(args,
+		"-o", "usesphonyoutputs=yes",
 		"-w", "dupbuild=err",
 		"-w", "missingdepfile=err")
 
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 9b8d648..2fbf381 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -119,7 +119,11 @@
 		cmd := Command(ctx, config, "soong "+name,
 			config.PrebuiltBuildTool("ninja"),
 			"-d", "keepdepfile",
+			"-o", "usesphonyoutputs=yes",
+			"-o", "preremoveoutputs=yes",
 			"-w", "dupbuild=err",
+			"-w", "outputdir=err",
+			"-w", "missingoutfile=err",
 			"-j", strconv.Itoa(config.Parallel()),
 			"--frontend_file", fifo,
 			"-f", filepath.Join(config.SoongOutDir(), file))
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 5109465..4ff9483 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -50,10 +50,10 @@
 	// Get a list of leaf nodes in the dependency graph from ninja
 	executable := config.PrebuiltBuildTool("ninja")
 
-	args := []string{}
-	args = append(args, config.NinjaArgs()...)
-	args = append(args, "-f", config.CombinedNinjaFile())
-	args = append(args, "-t", "targets", "rule")
+	common_args := []string{}
+	common_args = append(common_args, config.NinjaArgs()...)
+	common_args = append(common_args, "-f", config.CombinedNinjaFile())
+	args := append(common_args, "-t", "targets", "rule")
 
 	cmd := Command(ctx, config, "ninja", executable, args...)
 	stdout, err := cmd.StdoutPipe()
@@ -96,9 +96,31 @@
 		sb := &strings.Builder{}
 		title := "Dependencies in out found with no rule to create them:"
 		fmt.Fprintln(sb, title)
-		for _, dep := range danglingRulesList {
-			fmt.Fprintln(sb, "  ", dep)
+
+		report_lines := 1
+		for i, dep := range danglingRulesList {
+			if report_lines > 20 {
+				fmt.Fprintf(sb, "  ... and %d more\n", len(danglingRulesList)-i)
+				break
+			}
+			// It's helpful to see the reverse dependencies. ninja -t query is the
+			// best tool we got for that. Its output starts with the dependency
+			// itself.
+			query_cmd := Command(ctx, config, "ninja", executable,
+				append(common_args, "-t", "query", dep)...)
+			query_stdout, err := query_cmd.StdoutPipe()
+			if err != nil {
+				ctx.Fatal(err)
+			}
+			query_cmd.StartOrFatal()
+			scanner := bufio.NewScanner(query_stdout)
+			for scanner.Scan() {
+				report_lines++
+				fmt.Fprintln(sb, " ", scanner.Text())
+			}
+			query_cmd.WaitOrFatal()
 		}
+
 		ts.FinishAction(status.ActionResult{
 			Action: action,
 			Error:  fmt.Errorf(title),