Merge "Allow guava to use java_host_for_device"
diff --git a/Android.bp b/Android.bp
index a4e6e7d..6b59f04 100644
--- a/Android.bp
+++ b/Android.bp
@@ -37,6 +37,7 @@
         "blueprint-bootstrap",
         "soong",
         "soong-env",
+        "soong-shared",
     ],
     srcs: [
         "android/androidmk.go",
diff --git a/android/config.go b/android/config.go
index 0c9f957..0191e38 100644
--- a/android/config.go
+++ b/android/config.go
@@ -405,6 +405,10 @@
 	return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
 }
 
+func (c *config) PrebuiltBuildTool(ctx PathContext, tool string) Path {
+	return PathForSource(ctx, "prebuilts/build-tools", c.PrebuiltOS(), "bin", tool)
+}
+
 func (c *config) CpPreserveSymlinksFlags() string {
 	switch runtime.GOOS {
 	case "darwin":
@@ -1048,3 +1052,7 @@
 func (c *config) ProductHiddenAPIStubsTest() []string {
 	return c.productVariables.ProductHiddenAPIStubsTest
 }
+
+func (c *deviceConfig) TargetFSConfigGen() *string {
+	return c.config.productVariables.TargetFSConfigGen
+}
diff --git a/android/paths.go b/android/paths.go
index 8cc7057..0f20b84 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1267,16 +1267,23 @@
 // MaybeRel performs the same function as filepath.Rel, but reports errors to a PathContext, and returns false if
 // targetPath is not inside basePath.
 func MaybeRel(ctx PathContext, basePath string, targetPath string) (string, bool) {
+	rel, isRel, err := maybeRelErr(basePath, targetPath)
+	if err != nil {
+		reportPathError(ctx, err)
+	}
+	return rel, isRel
+}
+
+func maybeRelErr(basePath string, targetPath string) (string, bool, error) {
 	// filepath.Rel returns an error if one path is absolute and the other is not, handle that case first.
 	if filepath.IsAbs(basePath) != filepath.IsAbs(targetPath) {
-		return "", false
+		return "", false, nil
 	}
 	rel, err := filepath.Rel(basePath, targetPath)
 	if err != nil {
-		reportPathError(ctx, err)
-		return "", false
+		return "", false, err
 	} else if rel == ".." || strings.HasPrefix(rel, "../") || strings.HasPrefix(rel, "/") {
-		return "", false
+		return "", false, nil
 	}
-	return rel, true
+	return rel, true, nil
 }
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 2d0fac1..4a3b022 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -21,6 +21,8 @@
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
+
+	"android/soong/shared"
 )
 
 // RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
@@ -30,6 +32,8 @@
 	installs       RuleBuilderInstalls
 	temporariesSet map[WritablePath]bool
 	restat         bool
+	sbox           bool
+	sboxOutDir     WritablePath
 	missingDeps    []string
 }
 
@@ -73,11 +77,36 @@
 }
 
 // Restat marks the rule as a restat rule, which will be passed to ModuleContext.Rule in BuildParams.Restat.
+//
+// Restat is not compatible with Sbox()
 func (r *RuleBuilder) Restat() *RuleBuilder {
+	if r.sbox {
+		panic("Restat() is not compatible with Sbox()")
+	}
 	r.restat = true
 	return r
 }
 
+// Sbox marks the rule as needing to be wrapped by sbox. The WritablePath should point to the output
+// directory that sbox will wipe. It should not be written to by any other rule. sbox will ensure
+// that all outputs have been written, and will discard any output files that were not specified.
+//
+// Sbox is not compatible with Restat()
+func (r *RuleBuilder) Sbox(outputDir WritablePath) *RuleBuilder {
+	if r.sbox {
+		panic("Sbox() may not be called more than once")
+	}
+	if len(r.commands) > 0 {
+		panic("Sbox() may not be called after Command()")
+	}
+	if r.restat {
+		panic("Sbox() is not compatible with Restat()")
+	}
+	r.sbox = true
+	r.sboxOutDir = outputDir
+	return r
+}
+
 // Install associates an output of the rule with an install location, which can be retrieved later using
 // RuleBuilder.Installs.
 func (r *RuleBuilder) Install(from Path, to string) {
@@ -88,7 +117,10 @@
 // created by this method.  That can be mutated through their methods in any order, as long as the mutations do not
 // race with any call to Build.
 func (r *RuleBuilder) Command() *RuleBuilderCommand {
-	command := &RuleBuilderCommand{}
+	command := &RuleBuilderCommand{
+		sbox:       r.sbox,
+		sboxOutDir: r.sboxOutDir,
+	}
 	r.commands = append(r.commands, command)
 	return command
 }
@@ -120,12 +152,16 @@
 // that are also outputs of another command in the same RuleBuilder are filtered out.
 func (r *RuleBuilder) Inputs() Paths {
 	outputs := r.outputSet()
+	depFiles := r.depFileSet()
 
 	inputs := make(map[string]Path)
 	for _, c := range r.commands {
 		for _, input := range c.inputs {
-			if _, isOutput := outputs[input.String()]; !isOutput {
-				inputs[input.String()] = input
+			inputStr := input.String()
+			if _, isOutput := outputs[inputStr]; !isOutput {
+				if _, isDepFile := depFiles[inputStr]; !isDepFile {
+					inputs[input.String()] = input
+				}
 			}
 		}
 	}
@@ -171,6 +207,16 @@
 	return outputList
 }
 
+func (r *RuleBuilder) depFileSet() map[string]WritablePath {
+	depFiles := make(map[string]WritablePath)
+	for _, c := range r.commands {
+		for _, depFile := range c.depFiles {
+			depFiles[depFile.String()] = depFile
+		}
+	}
+	return depFiles
+}
+
 // DepFiles returns the list of paths that were passed to the RuleBuilderCommand methods that take depfile paths, such
 // as RuleBuilderCommand.DepFile or RuleBuilderCommand.FlagWithDepFile.
 func (r *RuleBuilder) DepFiles() WritablePaths {
@@ -237,9 +283,9 @@
 var _ BuilderContext = SingletonContext(nil)
 
 func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
-	return (&RuleBuilderCommand{}).
+	return r.Command().
 		Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).
-		Flags(depFiles.Strings())
+		Inputs(depFiles.Paths())
 }
 
 // Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
@@ -259,9 +305,6 @@
 		return
 	}
 
-	tools := r.Tools()
-	commands := r.Commands()
-
 	var depFile WritablePath
 	var depFormat blueprint.Deps
 	if depFiles := r.DepFiles(); len(depFiles) > 0 {
@@ -269,37 +312,75 @@
 		depFormat = blueprint.DepsGCC
 		if len(depFiles) > 1 {
 			// Add a command locally that merges all depfiles together into the first depfile.
-			cmd := r.depFileMergerCmd(ctx, depFiles)
-			commands = append(commands, string(cmd.buf))
-			tools = append(tools, cmd.tools...)
+			r.depFileMergerCmd(ctx, depFiles)
+
+			if r.sbox {
+				// Check for Rel() errors, as all depfiles should be in the output dir
+				for _, path := range depFiles[1:] {
+					Rel(ctx, r.sboxOutDir.String(), path.String())
+				}
+			}
 		}
 	}
 
+	tools := r.Tools()
+	commands := r.Commands()
+	outputs := r.Outputs()
+
+	if len(commands) == 0 {
+		return
+	}
+	if len(outputs) == 0 {
+		panic("No outputs specified from any Commands")
+	}
+
+	commandString := strings.Join(proptools.NinjaEscapeList(commands), " && ")
+
+	if r.sbox {
+		sboxOutputs := make([]string, len(outputs))
+		for i, output := range outputs {
+			sboxOutputs[i] = "__SBOX_OUT_DIR__/" + Rel(ctx, r.sboxOutDir.String(), output.String())
+		}
+
+		if depFile != nil {
+			sboxOutputs = append(sboxOutputs, "__SBOX_OUT_DIR__/"+Rel(ctx, r.sboxOutDir.String(), depFile.String()))
+		}
+
+		commandString = proptools.ShellEscape(commandString)
+		if !strings.HasPrefix(commandString, `'`) {
+			commandString = `'` + commandString + `'`
+		}
+
+		sboxCmd := &RuleBuilderCommand{}
+		sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")).
+			Flag("-c").Text(commandString).
+			Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
+			Flag("--output-root").Text(r.sboxOutDir.String()).
+			Flags(sboxOutputs)
+
+		commandString = string(sboxCmd.buf)
+		tools = append(tools, sboxCmd.tools...)
+	}
+
 	// Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to
 	// ImplicitOutputs.  RuleBuilder never uses "$out", so the distinction between Outputs and ImplicitOutputs
 	// doesn't matter.
-	var output WritablePath
-	var implicitOutputs WritablePaths
-	if outputs := r.Outputs(); len(outputs) > 0 {
-		output = outputs[0]
-		implicitOutputs = outputs[1:]
-	}
+	output := outputs[0]
+	implicitOutputs := outputs[1:]
 
-	if len(commands) > 0 {
-		ctx.Build(pctx, BuildParams{
-			Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
-				Command:     strings.Join(proptools.NinjaEscapeList(commands), " && "),
-				CommandDeps: tools.Strings(),
-				Restat:      r.restat,
-			}),
-			Implicits:       r.Inputs(),
-			Output:          output,
-			ImplicitOutputs: implicitOutputs,
-			Depfile:         depFile,
-			Deps:            depFormat,
-			Description:     desc,
-		})
-	}
+	ctx.Build(pctx, BuildParams{
+		Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
+			Command:     commandString,
+			CommandDeps: tools.Strings(),
+			Restat:      r.restat,
+		}),
+		Implicits:       r.Inputs(),
+		Output:          output,
+		ImplicitOutputs: implicitOutputs,
+		Depfile:         depFile,
+		Deps:            depFormat,
+		Description:     desc,
+	})
 }
 
 // RuleBuilderCommand is a builder for a command in a command line.  It can be mutated by its methods to add to the
@@ -312,6 +393,28 @@
 	outputs  WritablePaths
 	depFiles WritablePaths
 	tools    Paths
+
+	sbox       bool
+	sboxOutDir WritablePath
+}
+
+func (c *RuleBuilderCommand) addInput(path Path) string {
+	if c.sbox {
+		if rel, isRel, _ := maybeRelErr(c.sboxOutDir.String(), path.String()); isRel {
+			return "__SBOX_OUT_DIR__/" + rel
+		}
+	}
+	c.inputs = append(c.inputs, path)
+	return path.String()
+}
+
+func (c *RuleBuilderCommand) outputStr(path Path) string {
+	if c.sbox {
+		// Errors will be handled in RuleBuilder.Build where we have a context to report them
+		rel, _, _ := maybeRelErr(c.sboxOutDir.String(), path.String())
+		return "__SBOX_OUT_DIR__/" + rel
+	}
+	return path.String()
 }
 
 // Text adds the specified raw text to the command line.  The text should not contain input or output paths or the
@@ -378,8 +481,7 @@
 // Input adds the specified input path to the command line.  The path will also be added to the dependencies returned by
 // RuleBuilder.Inputs.
 func (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand {
-	c.inputs = append(c.inputs, path)
-	return c.Text(path.String())
+	return c.Text(c.addInput(path))
 }
 
 // Inputs adds the specified input paths to the command line, separated by spaces.  The paths will also be added to the
@@ -394,14 +496,16 @@
 // Implicit adds the specified input path to the dependencies returned by RuleBuilder.Inputs without modifying the
 // command line.
 func (c *RuleBuilderCommand) Implicit(path Path) *RuleBuilderCommand {
-	c.inputs = append(c.inputs, path)
+	c.addInput(path)
 	return c
 }
 
 // Implicits adds the specified input paths to the dependencies returned by RuleBuilder.Inputs without modifying the
 // command line.
 func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand {
-	c.inputs = append(c.inputs, paths...)
+	for _, path := range paths {
+		c.addInput(path)
+	}
 	return c
 }
 
@@ -409,7 +513,7 @@
 // RuleBuilder.Outputs.
 func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
 	c.outputs = append(c.outputs, path)
-	return c.Text(path.String())
+	return c.Text(c.outputStr(path))
 }
 
 // Outputs adds the specified output paths to the command line, separated by spaces.  The paths will also be added to
@@ -426,7 +530,7 @@
 // commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the depfiles together.
 func (c *RuleBuilderCommand) DepFile(path WritablePath) *RuleBuilderCommand {
 	c.depFiles = append(c.depFiles, path)
-	return c.Text(path.String())
+	return c.Text(c.outputStr(path))
 }
 
 // ImplicitOutput adds the specified output path to the dependencies returned by RuleBuilder.Outputs without modifying
@@ -455,16 +559,18 @@
 // FlagWithInput adds the specified flag and input path to the command line, with no separator between them.  The path
 // will also be added to the dependencies returned by RuleBuilder.Inputs.
 func (c *RuleBuilderCommand) FlagWithInput(flag string, path Path) *RuleBuilderCommand {
-	c.inputs = append(c.inputs, path)
-	return c.Text(flag + path.String())
+	return c.Text(flag + c.addInput(path))
 }
 
 // FlagWithInputList adds the specified flag and input paths to the command line, with the inputs joined by sep
 // and no separator between the flag and inputs.  The input paths will also be added to the dependencies returned by
 // RuleBuilder.Inputs.
 func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths Paths, sep string) *RuleBuilderCommand {
-	c.inputs = append(c.inputs, paths...)
-	return c.FlagWithList(flag, paths.Strings(), sep)
+	strs := make([]string, len(paths))
+	for i, path := range paths {
+		strs[i] = c.addInput(path)
+	}
+	return c.FlagWithList(flag, strs, sep)
 }
 
 // FlagForEachInput adds the specified flag joined with each input path to the command line.  The input paths will also
@@ -481,14 +587,14 @@
 // will also be added to the outputs returned by RuleBuilder.Outputs.
 func (c *RuleBuilderCommand) FlagWithOutput(flag string, path WritablePath) *RuleBuilderCommand {
 	c.outputs = append(c.outputs, path)
-	return c.Text(flag + path.String())
+	return c.Text(flag + c.outputStr(path))
 }
 
 // FlagWithDepFile adds the specified flag and depfile path to the command line, with no separator between them.  The path
 // will also be added to the outputs returned by RuleBuilder.Outputs.
 func (c *RuleBuilderCommand) FlagWithDepFile(flag string, path WritablePath) *RuleBuilderCommand {
 	c.depFiles = append(c.depFiles, path)
-	return c.Text(flag + path.String())
+	return c.Text(flag + c.outputStr(path))
 }
 
 // String returns the command line.
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 7bad025..df0f256 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -22,6 +22,10 @@
 	"reflect"
 	"strings"
 	"testing"
+
+	"github.com/google/blueprint"
+
+	"android/soong/shared"
 )
 
 func pathContext() PathContext {
@@ -234,8 +238,6 @@
 }
 
 func TestRuleBuilder(t *testing.T) {
-	rule := NewRuleBuilder()
-
 	fs := map[string][]byte{
 		"dep_fixer": nil,
 		"input":     nil,
@@ -249,73 +251,114 @@
 
 	ctx := PathContextForTesting(TestConfig("out", nil), fs)
 
-	cmd := rule.Command().
-		DepFile(PathForOutput(ctx, "DepFile")).
-		Flag("Flag").
-		FlagWithArg("FlagWithArg=", "arg").
-		FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "depfile")).
-		FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
-		FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
-		Implicit(PathForSource(ctx, "Implicit")).
-		ImplicitDepFile(PathForOutput(ctx, "ImplicitDepFile")).
-		ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
-		Input(PathForSource(ctx, "Input")).
-		Output(PathForOutput(ctx, "Output")).
-		Text("Text").
-		Tool(PathForSource(ctx, "Tool"))
+	addCommands := func(rule *RuleBuilder) {
+		cmd := rule.Command().
+			DepFile(PathForOutput(ctx, "DepFile")).
+			Flag("Flag").
+			FlagWithArg("FlagWithArg=", "arg").
+			FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "depfile")).
+			FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
+			FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
+			Implicit(PathForSource(ctx, "Implicit")).
+			ImplicitDepFile(PathForOutput(ctx, "ImplicitDepFile")).
+			ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
+			Input(PathForSource(ctx, "Input")).
+			Output(PathForOutput(ctx, "Output")).
+			Text("Text").
+			Tool(PathForSource(ctx, "Tool"))
 
-	rule.Command().
-		Text("command2").
-		DepFile(PathForOutput(ctx, "depfile2")).
-		Input(PathForSource(ctx, "input2")).
-		Output(PathForOutput(ctx, "output2")).
-		Tool(PathForSource(ctx, "tool2"))
+		rule.Command().
+			Text("command2").
+			DepFile(PathForOutput(ctx, "depfile2")).
+			Input(PathForSource(ctx, "input2")).
+			Output(PathForOutput(ctx, "output2")).
+			Tool(PathForSource(ctx, "tool2"))
 
-	// Test updates to the first command after the second command has been started
-	cmd.Text("after command2")
-	// Test updating a command when the previous update did not replace the cmd variable
-	cmd.Text("old cmd")
+		// Test updates to the first command after the second command has been started
+		cmd.Text("after command2")
+		// Test updating a command when the previous update did not replace the cmd variable
+		cmd.Text("old cmd")
 
-	// Test a command that uses the output of a previous command as an input
-	rule.Command().
-		Text("command3").
-		Input(PathForSource(ctx, "input3")).
-		Input(PathForOutput(ctx, "output2")).
-		Output(PathForOutput(ctx, "output3"))
-
-	wantCommands := []string{
-		"out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
-		"command2 out/depfile2 input2 out/output2 tool2",
-		"command3 input3 out/output2 out/output3",
+		// Test a command that uses the output of a previous command as an input
+		rule.Command().
+			Text("command3").
+			Input(PathForSource(ctx, "input3")).
+			Input(PathForOutput(ctx, "output2")).
+			Output(PathForOutput(ctx, "output3"))
 	}
 
-	wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
-
 	wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
 	wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
 	wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
 	wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
 
-	if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
-		t.Errorf("\nwant rule.Commands() = %#v\n                   got %#v", w, g)
-	}
+	t.Run("normal", func(t *testing.T) {
+		rule := NewRuleBuilder()
+		addCommands(rule)
 
-	if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
-		t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n                   got %#v", w, g)
-	}
+		wantCommands := []string{
+			"out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
+			"command2 out/depfile2 input2 out/output2 tool2",
+			"command3 input3 out/output2 out/output3",
+		}
 
-	if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
-		t.Errorf("\nwant rule.Inputs() = %#v\n                 got %#v", w, g)
-	}
-	if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
-		t.Errorf("\nwant rule.Outputs() = %#v\n                  got %#v", w, g)
-	}
-	if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
-		t.Errorf("\nwant rule.DepFiles() = %#v\n                  got %#v", w, g)
-	}
-	if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
-		t.Errorf("\nwant rule.Tools() = %#v\n                got %#v", w, g)
-	}
+		wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
+
+		if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
+			t.Errorf("\nwant rule.Commands() = %#v\n                   got %#v", w, g)
+		}
+
+		if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Inputs() = %#v\n                 got %#v", w, g)
+		}
+		if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Outputs() = %#v\n                  got %#v", w, g)
+		}
+		if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.DepFiles() = %#v\n                  got %#v", w, g)
+		}
+		if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Tools() = %#v\n                got %#v", w, g)
+		}
+
+		if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
+			t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n                   got %#v", w, g)
+		}
+	})
+
+	t.Run("sbox", func(t *testing.T) {
+		rule := NewRuleBuilder().Sbox(PathForOutput(ctx))
+		addCommands(rule)
+
+		wantCommands := []string{
+			"__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output Text Tool after command2 old cmd",
+			"command2 __SBOX_OUT_DIR__/depfile2 input2 __SBOX_OUT_DIR__/output2 tool2",
+			"command3 input3 __SBOX_OUT_DIR__/output2 __SBOX_OUT_DIR__/output3",
+		}
+
+		wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_OUT_DIR__/DepFile __SBOX_OUT_DIR__/depfile __SBOX_OUT_DIR__/ImplicitDepFile __SBOX_OUT_DIR__/depfile2"
+
+		if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
+			t.Errorf("\nwant rule.Commands() = %#v\n                   got %#v", w, g)
+		}
+
+		if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Inputs() = %#v\n                 got %#v", w, g)
+		}
+		if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Outputs() = %#v\n                  got %#v", w, g)
+		}
+		if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.DepFiles() = %#v\n                  got %#v", w, g)
+		}
+		if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
+			t.Errorf("\nwant rule.Tools() = %#v\n                got %#v", w, g)
+		}
+
+		if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
+			t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n                   got %#v", w, g)
+		}
+	})
 }
 
 func testRuleBuilderFactory() Module {
@@ -329,14 +372,19 @@
 	ModuleBase
 	properties struct {
 		Src string
+
+		Restat bool
+		Sbox   bool
 	}
 }
 
 func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	in := PathForSource(ctx, t.properties.Src)
 	out := PathForModuleOut(ctx, ctx.ModuleName())
+	outDep := PathForModuleOut(ctx, ctx.ModuleName()+".d")
+	outDir := PathForModuleOut(ctx)
 
-	testRuleBuilder_Build(ctx, in, out)
+	testRuleBuilder_Build(ctx, in, out, outDep, outDir, t.properties.Restat, t.properties.Sbox)
 }
 
 type testRuleBuilderSingleton struct{}
@@ -348,15 +396,23 @@
 func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
 	in := PathForSource(ctx, "bar")
 	out := PathForOutput(ctx, "baz")
-	testRuleBuilder_Build(ctx, in, out)
+	outDep := PathForOutput(ctx, "baz.d")
+	outDir := PathForOutput(ctx)
+	testRuleBuilder_Build(ctx, in, out, outDep, outDir, true, false)
 }
 
-func testRuleBuilder_Build(ctx BuilderContext, in Path, out WritablePath) {
+func testRuleBuilder_Build(ctx BuilderContext, in Path, out, outDep, outDir WritablePath, restat, sbox bool) {
 	rule := NewRuleBuilder()
 
-	rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out)
+	if sbox {
+		rule.Sbox(outDir)
+	}
 
-	rule.Restat()
+	rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out).ImplicitDepFile(outDep)
+
+	if restat {
+		rule.Restat()
+	}
 
 	rule.Build(pctx, ctx, "rule", "desc")
 }
@@ -372,6 +428,12 @@
 		rule_builder_test {
 			name: "foo",
 			src: "bar",
+			restat: true,
+		}
+		rule_builder_test {
+			name: "foo_sbox",
+			src: "bar",
+			sbox: true,
 		}
 	`
 
@@ -391,9 +453,18 @@
 	_, errs = ctx.PrepareBuildActions(config)
 	FailIfErrored(t, errs)
 
-	check := func(t *testing.T, params TestingBuildParams, wantOutput string) {
-		if len(params.RuleParams.CommandDeps) != 1 || params.RuleParams.CommandDeps[0] != "cp" {
-			t.Errorf("want RuleParams.CommandDeps = [%q], got %q", "cp", params.RuleParams.CommandDeps)
+	check := func(t *testing.T, params TestingBuildParams, wantCommand, wantOutput, wantDepfile string, wantRestat bool, extraCmdDeps []string) {
+		if params.RuleParams.Command != wantCommand {
+			t.Errorf("\nwant RuleParams.Command = %q\n                      got %q", wantCommand, params.RuleParams.Command)
+		}
+
+		wantDeps := append([]string{"cp"}, extraCmdDeps...)
+		if !reflect.DeepEqual(params.RuleParams.CommandDeps, wantDeps) {
+			t.Errorf("\nwant RuleParams.CommandDeps = %q\n                          got %q", wantDeps, params.RuleParams.CommandDeps)
+		}
+
+		if params.RuleParams.Restat != wantRestat {
+			t.Errorf("want RuleParams.Restat = %v, got %v", wantRestat, params.RuleParams.Restat)
 		}
 
 		if len(params.Implicits) != 1 || params.Implicits[0].String() != "bar" {
@@ -404,17 +475,39 @@
 			t.Errorf("want Output = %q, got %q", wantOutput, params.Output)
 		}
 
-		if !params.RuleParams.Restat {
-			t.Errorf("want RuleParams.Restat = true, got %v", params.RuleParams.Restat)
+		if len(params.ImplicitOutputs) != 0 {
+			t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
+		}
+
+		if params.Depfile.String() != wantDepfile {
+			t.Errorf("want Depfile = %q, got %q", wantDepfile, params.Depfile)
+		}
+
+		if params.Deps != blueprint.DepsGCC {
+			t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
 		}
 	}
 
 	t.Run("module", func(t *testing.T) {
+		outFile := filepath.Join(buildDir, ".intermediates", "foo", "foo")
 		check(t, ctx.ModuleForTests("foo", "").Rule("rule"),
-			filepath.Join(buildDir, ".intermediates", "foo", "foo"))
+			"cp bar "+outFile,
+			outFile, outFile+".d", true, nil)
+	})
+	t.Run("sbox", func(t *testing.T) {
+		outDir := filepath.Join(buildDir, ".intermediates", "foo_sbox")
+		outFile := filepath.Join(outDir, "foo_sbox")
+		sbox := filepath.Join(buildDir, "host", config.PrebuiltOS(), "bin/sbox")
+		sandboxPath := shared.TempDirForOutDir(buildDir)
+
+		cmd := sbox + ` -c 'cp bar __SBOX_OUT_DIR__/foo_sbox' --sandbox-path ` + sandboxPath + " --output-root " + outDir + " __SBOX_OUT_DIR__/foo_sbox __SBOX_OUT_DIR__/foo_sbox.d"
+
+		check(t, ctx.ModuleForTests("foo_sbox", "").Rule("rule"),
+			cmd, outFile, outFile+".d", false, []string{sbox})
 	})
 	t.Run("singleton", func(t *testing.T) {
+		outFile := filepath.Join(buildDir, "baz")
 		check(t, ctx.SingletonForTests("rule_builder_test").Rule("rule"),
-			filepath.Join(buildDir, "baz"))
+			"cp bar "+outFile, outFile, outFile+".d", true, nil)
 	})
 }
diff --git a/android/variable.go b/android/variable.go
index 16d7b13..666f29f 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -287,6 +287,8 @@
 	ProductHiddenAPIStubs       []string `json:",omitempty"`
 	ProductHiddenAPIStubsSystem []string `json:",omitempty"`
 	ProductHiddenAPIStubsTest   []string `json:",omitempty"`
+
+	TargetFSConfigGen *string `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index e0932af..b54ad5e 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -131,7 +131,7 @@
 			"LOCAL_OVERRIDES_MODULES":             "overrides",
 			"LOCAL_LDLIBS":                        "host_ldlibs",
 			"LOCAL_CLANG_CFLAGS":                  "clang_cflags",
-			"LOCAL_YACCFLAGS":                     "yaccflags",
+			"LOCAL_YACCFLAGS":                     "yacc.flags",
 			"LOCAL_SANITIZE_RECOVER":              "sanitize.recover",
 			"LOCAL_LOGTAGS_FILES":                 "logtags",
 			"LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers",
diff --git a/apex/key.go b/apex/key.go
index a627e4b..229d593 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -55,8 +55,7 @@
 func apexKeyFactory() android.Module {
 	module := &apexKey{}
 	module.AddProperties(&module.properties)
-	// This module is device-only
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
 	return module
 }
 
diff --git a/cc/builder.go b/cc/builder.go
index 65369d6..87db645 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -239,7 +239,6 @@
 	cppFlags        string
 	ldFlags         string
 	libFlags        string
-	yaccFlags       string
 	tidyFlags       string
 	sAbiFlags       string
 	yasmFlags       string
@@ -262,6 +261,8 @@
 	proto            android.ProtoFlags
 	protoC           bool
 	protoOptionsFile bool
+
+	yacc *YaccProperties
 }
 
 type Objects struct {
diff --git a/cc/cc.go b/cc/cc.go
index 0668fd9..bec39ca 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -136,7 +136,6 @@
 	ConlyFlags      []string // Flags that apply to C source files
 	CppFlags        []string // Flags that apply to C++ source files
 	ToolingCppFlags []string // Flags that apply to C++ source files parsed by clang LibTooling tools
-	YaccFlags       []string // Flags that apply to Yacc source files
 	aidlFlags       []string // Flags that apply to aidl source files
 	rsFlags         []string // Flags that apply to renderscript source files
 	LdFlags         []string // Flags that apply to linker command lines
@@ -165,6 +164,8 @@
 	proto            android.ProtoFlags
 	protoC           bool // Whether to use C instead of C++
 	protoOptionsFile bool // Whether to look for a .options file next to the .proto
+
+	Yacc *YaccProperties
 }
 
 type ObjectLinkerProperties struct {
diff --git a/cc/compiler.go b/cc/compiler.go
index f9af4d8..7667ae7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -57,9 +57,6 @@
 	// compiling with clang
 	Clang_asflags []string `android:"arch_variant"`
 
-	// list of module-specific flags that will be used for .y and .yy compiles
-	Yaccflags []string
-
 	// the instruction set architecture to use to compile the C/C++
 	// module.
 	Instruction_set *string `android:"arch_variant"`
@@ -103,6 +100,8 @@
 	// if set to false, use -std=c++* instead of -std=gnu++*
 	Gnu_extensions *bool
 
+	Yacc *YaccProperties
+
 	Aidl struct {
 		// list of directories that will be added to the aidl include paths.
 		Include_dirs []string
@@ -275,7 +274,8 @@
 	flags.ConlyFlags = append(flags.ConlyFlags, esc(compiler.Properties.Conlyflags)...)
 	flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Asflags)...)
 	flags.YasmFlags = append(flags.YasmFlags, esc(compiler.Properties.Asflags)...)
-	flags.YaccFlags = append(flags.YaccFlags, esc(compiler.Properties.Yaccflags)...)
+
+	flags.Yacc = compiler.Properties.Yacc
 
 	// Include dir cflags
 	localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
diff --git a/cc/config/global.go b/cc/config/global.go
index 78f24f2..8fc9ff2 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -83,6 +83,7 @@
 		"-Wl,--warn-shared-textrel",
 		"-Wl,--fatal-warnings",
 		"-Wl,--no-undefined-version",
+		"-Wl,--exclude-libs,libgcc.a",
 	}
 
 	deviceGlobalLldflags = append(ClangFilterUnknownLldflags(deviceGlobalLdflags),
diff --git a/cc/gen.go b/cc/gen.go
index 0c3d089..ae761d0 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -24,21 +24,12 @@
 
 func init() {
 	pctx.SourcePathVariable("lexCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/flex")
-	pctx.SourcePathVariable("yaccCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/bison")
-	pctx.SourcePathVariable("yaccDataDir", "prebuilts/build-tools/common/bison")
 
 	pctx.HostBinToolVariable("aidlCmd", "aidl-cpp")
 	pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp")
 }
 
 var (
-	yacc = pctx.AndroidStaticRule("yacc",
-		blueprint.RuleParams{
-			Command:     "BISON_PKGDATADIR=$yaccDataDir $yaccCmd -d $yaccFlags --defines=$hFile -o $out $in",
-			CommandDeps: []string{"$yaccCmd"},
-		},
-		"yaccFlags", "hFile")
-
 	lex = pctx.AndroidStaticRule("lex",
 		blueprint.RuleParams{
 			Command:     "$lexCmd -o$out $in",
@@ -70,22 +61,57 @@
 		"windmcCmd")
 )
 
-func genYacc(ctx android.ModuleContext, yaccFile android.Path, outFile android.ModuleGenPath, yaccFlags string) (headerFile android.ModuleGenPath) {
-	headerFile = android.GenPathWithExt(ctx, "yacc", yaccFile, "h")
+type YaccProperties struct {
+	// list of module-specific flags that will be used for .y and .yy compiles
+	Flags []string
 
-	ctx.Build(pctx, android.BuildParams{
-		Rule:           yacc,
-		Description:    "yacc " + yaccFile.Rel(),
-		Output:         outFile,
-		ImplicitOutput: headerFile,
-		Input:          yaccFile,
-		Args: map[string]string{
-			"yaccFlags": yaccFlags,
-			"hFile":     headerFile.String(),
-		},
-	})
+	// whether the yacc files will produce a location.hh file
+	Gen_location_hh *bool
 
-	return headerFile
+	// whether the yacc files will product a position.hh file
+	Gen_position_hh *bool
+}
+
+func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile android.Path,
+	outFile android.ModuleGenPath, props *YaccProperties) (headerFiles android.Paths) {
+
+	outDir := android.PathForModuleGen(ctx, "yacc")
+	headerFile := android.GenPathWithExt(ctx, "yacc", yaccFile, "h")
+	ret := android.Paths{headerFile}
+
+	cmd := rule.Command()
+
+	// Fix up #line markers to not use the sbox temporary directory
+	sedCmd := "sed -i.bak 's#__SBOX_OUT_DIR__#" + outDir.String() + "#'"
+	rule.Command().Text(sedCmd).Input(outFile)
+	rule.Command().Text(sedCmd).Input(headerFile)
+
+	var flags []string
+	if props != nil {
+		flags = props.Flags
+
+		if Bool(props.Gen_location_hh) {
+			locationHeader := outFile.InSameDir(ctx, "location.hh")
+			ret = append(ret, locationHeader)
+			cmd.ImplicitOutput(locationHeader)
+			rule.Command().Text(sedCmd).Input(locationHeader)
+		}
+		if Bool(props.Gen_position_hh) {
+			positionHeader := outFile.InSameDir(ctx, "position.hh")
+			ret = append(ret, positionHeader)
+			cmd.ImplicitOutput(positionHeader)
+			rule.Command().Text(sedCmd).Input(positionHeader)
+		}
+	}
+
+	cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison").
+		Tool(ctx.Config().PrebuiltBuildTool(ctx, "bison")).
+		Flag("-d").
+		Flags(flags).
+		FlagWithOutput("--defines=", headerFile).
+		Flag("-o").Output(outFile).Input(yaccFile)
+
+	return ret
 }
 
 func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths {
@@ -159,19 +185,26 @@
 	buildFlags builderFlags) (android.Paths, android.Paths) {
 
 	var deps android.Paths
-
 	var rsFiles android.Paths
 
+	var yaccRule_ *android.RuleBuilder
+	yaccRule := func() *android.RuleBuilder {
+		if yaccRule_ == nil {
+			yaccRule_ = android.NewRuleBuilder().Sbox(android.PathForModuleGen(ctx, "yacc"))
+		}
+		return yaccRule_
+	}
+
 	for i, srcFile := range srcFiles {
 		switch srcFile.Ext() {
 		case ".y":
 			cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c")
 			srcFiles[i] = cFile
-			deps = append(deps, genYacc(ctx, srcFile, cFile, buildFlags.yaccFlags))
+			deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...)
 		case ".yy":
 			cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp")
 			srcFiles[i] = cppFile
-			deps = append(deps, genYacc(ctx, srcFile, cppFile, buildFlags.yaccFlags))
+			deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...)
 		case ".l":
 			cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c")
 			srcFiles[i] = cFile
@@ -203,6 +236,10 @@
 		}
 	}
 
+	if yaccRule_ != nil {
+		yaccRule_.Build(pctx, ctx, "yacc", "gen yacc")
+	}
+
 	if len(rsFiles) > 0 {
 		deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...)
 	}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 5a36b7f..3e25481 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -189,6 +189,14 @@
 	return module
 }
 
+// llndk_library creates a stub llndk shared library based on the provided
+// version file. Example:
+//
+//    llndk_library {
+//        name: "libfoo",
+//        symbol_file: "libfoo.map.txt",
+//        export_include_dirs: ["include_vndk"],
+//    }
 func LlndkLibraryFactory() android.Module {
 	module := NewLLndkStubLibrary()
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
@@ -203,6 +211,8 @@
 	return name + llndkHeadersSuffix
 }
 
+// llndk_headers contains a set of c/c++ llndk headers files which are imported
+// by other soongs cc modules.
 func llndkHeadersFactory() android.Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.HeaderOnly()
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 5e45c1a..4065128 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -159,6 +159,16 @@
 	}
 }
 
+// ndk_headers installs the sets of ndk headers defined in the srcs property
+// to the sysroot base + "usr/include" + to directory + directory component.
+// ndk_headers requires the license file to be specified. Example:
+//
+//    Given:
+//    sysroot base = "ndk/sysroot"
+//    from = "include/foo"
+//    to = "bar"
+//    header = "include/foo/woodly/doodly.h"
+//    output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
 func ndkHeadersFactory() android.Module {
 	module := &headerModule{}
 	module.AddProperties(&module.properties)
@@ -278,6 +288,11 @@
 	return timestampFile
 }
 
+// versioned_ndk_headers preprocesses the headers with the bionic versioner:
+// https://android.googlesource.com/platform/bionic/+/master/tools/versioner/README.md.
+// Unlike the ndk_headers soong module, versioned_ndk_headers operates on a
+// directory level specified in `from` property. This is only used to process
+// the bionic/libc/include directory.
 func versionedNdkHeadersFactory() android.Module {
 	module := &versionedHeaderModule{}
 
@@ -360,6 +375,8 @@
 	}
 }
 
+// preprocessed_ndk_headers preprocesses all the ndk headers listed in the srcs
+// property by executing the command defined in the preprocessor property.
 func preprocessedNdkHeadersFactory() android.Module {
 	module := &preprocessedHeadersModule{}
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 7199467..c63b200 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -377,6 +377,8 @@
 	return module
 }
 
+// ndk_library creates a stub library that exposes dummy implementation
+// of functions and variables for use at build time only.
 func ndkLibraryFactory() android.Module {
 	module := newStubLibrary()
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
diff --git a/cc/stl.go b/cc/stl.go
index e59f677..1a5dd79 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -245,7 +245,10 @@
 		ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
 		flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String())
 	case "ndk_libc++_shared", "ndk_libc++_static":
-		// Nothing.
+		if ctx.Arch().ArchType == android.Arm {
+			// Make sure the _Unwind_XXX symbols are not re-exported.
+			flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind.a")
+		}
 	case "":
 		// None or error.
 		if !ctx.toolchain().Bionic() {
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index ae08b1c..6494a26 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -48,6 +48,9 @@
 	return append(props, &library.Properties)
 }
 
+// toolchain_library is used internally by the build tool to link the specified
+// static library in src property to the device libraries that are shipped with
+// gcc.
 func ToolchainLibraryFactory() android.Module {
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
diff --git a/cc/util.go b/cc/util.go
index 5dcbaef..3862728 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -67,7 +67,6 @@
 		toolingCppFlags: strings.Join(in.ToolingCppFlags, " "),
 		conlyFlags:      strings.Join(in.ConlyFlags, " "),
 		cppFlags:        strings.Join(in.CppFlags, " "),
-		yaccFlags:       strings.Join(in.YaccFlags, " "),
 		aidlFlags:       strings.Join(in.aidlFlags, " "),
 		rsFlags:         strings.Join(in.rsFlags, " "),
 		ldFlags:         strings.Join(in.LdFlags, " "),
@@ -87,6 +86,8 @@
 		proto:            in.proto,
 		protoC:           in.protoC,
 		protoOptionsFile: in.protoOptionsFile,
+
+		yacc: in.Yacc,
 	}
 }
 
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index da41cbc..2072ad9 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -122,6 +122,15 @@
 	return stub.libraryDecorator.link(ctx, flags, deps, objs)
 }
 
+// vendor_public_library creates a stub shared library for a vendor public
+// library. This stub library is a build-time only artifact that provides
+// symbols that are exposed from a vendor public library. Example:
+//
+//    vendor_public_library {
+//        name: "libfoo",
+//        symbol_file: "libfoo.map.txt",
+//        export_public_headers: ["libfoo_headers"],
+//    }
 func vendorPublicLibraryFactory() android.Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.BuildOnlyShared()
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index a399b28..c2ad944 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -328,6 +328,9 @@
     {{- if .IsAar}}
     min_sdk_version: "{{.MinSdkVersion}}",
     static_libs: [
+        {{- range .BpJarDeps}}
+        "{{.}}",
+        {{- end}}
         {{- range .BpAarDeps}}
         "{{.}}",
         {{- end}}
@@ -349,7 +352,7 @@
     {{- end}}
     static_libs: [
         "{{.BpName}}-nodeps",
-         {{- range .BpJarDeps}}
+        {{- range .BpJarDeps}}
         "{{.}}",
         {{- end}}
         {{- range .BpAarDeps}}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 4167edb..4ac9295 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -56,7 +56,7 @@
 	}
 
 	fmt.Fprintf(os.Stderr,
-		"Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> --overwrite [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
+		"Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
 			"\n"+
 			"Deletes <outputRoot>,"+
 			"runs <commandToRun>,"+
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index d011e77..9424b6c 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -152,7 +152,6 @@
 <html>
 <head>
 <title>Build Docs</title>
-<link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/vc67ef93e81a468795c57df87eca3f8427d65cbe85f09fbb51c82a12b89aa3d7e/androidsource/css/app.css">
 <style>
 #main {
   padding: 48px;
@@ -165,6 +164,99 @@
 td {
   word-wrap:break-word;
 }
+
+/* The following entries are copied from source.android.com's css file. */
+td,td code {
+    color: #202124
+}
+
+th,th code {
+    color: #fff;
+    font: 500 16px/24px Roboto,sans-serif
+}
+
+td,table.responsive tr:not(.alt) td td:first-child,table.responsive td tr:not(.alt) td:first-child {
+    background: rgba(255,255,255,.95);
+    vertical-align: top
+}
+
+td,td code {
+    padding: 7px 8px 8px
+}
+
+tr {
+    border: 0;
+    background: #78909c;
+    border-top: 1px solid #cfd8dc
+}
+
+th,td {
+    border: 0;
+    margin: 0;
+    text-align: left
+}
+
+th {
+    height: 48px;
+    padding: 8px;
+    vertical-align: middle
+}
+
+table {
+    border: 0;
+    border-collapse: collapse;
+    border-spacing: 0;
+    font: 14px/20px Roboto,sans-serif;
+    margin: 16px 0;
+    width: 100%
+}
+
+h1 {
+    color: #80868b;
+    font: 300 34px/40px Roboto,sans-serif;
+    letter-spacing: -0.01em;
+    margin: 40px 0 20px
+}
+
+h1,h2,h3,h4,h5,h6 {
+    overflow: hidden;
+    padding: 0;
+    text-overflow: ellipsis
+}
+
+:link,:visited {
+    color: #039be5;
+    outline: 0;
+    text-decoration: none
+}
+
+body,html {
+    color: #202124;
+    font: 400 16px/24px Roboto,sans-serif;
+    -moz-osx-font-smoothing: grayscale;
+    -webkit-font-smoothing: antialiased;
+    height: 100%;
+    margin: 0;
+    -webkit-text-size-adjust: 100%;
+    -moz-text-size-adjust: 100%;
+    -ms-text-size-adjust: 100%;
+    text-size-adjust: 100%
+}
+
+html {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box
+}
+
+*,*::before,*::after {
+    -webkit-box-sizing: inherit;
+    box-sizing: inherit
+}
+
+body,div,dl,dd,form,img,input,figure,menu {
+    margin: 0;
+    padding: 0
+}
 </style>
 {{template "copyBaseUrl"}}
 </head>
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index a23b477..cb2ea9f 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -57,6 +57,7 @@
 	dir          android.OutputPath
 	symbolsDir   android.OutputPath
 	images       map[android.ArchType]android.OutputPath
+	zip          android.WritablePath
 }
 
 type bootImage struct {
@@ -187,6 +188,8 @@
 
 	profile := bootImageProfileRule(ctx, image, missingDeps)
 
+	var allFiles android.Paths
+
 	if !global.DisablePreopt {
 		targets := ctx.Config().Targets[android.Android]
 		if ctx.Config().SecondArchIsTranslated() {
@@ -194,15 +197,27 @@
 		}
 
 		for _, target := range targets {
-			buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+			files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+			allFiles = append(allFiles, files.Paths()...)
 		}
 	}
 
+	if image.zip != nil {
+		rule := android.NewRuleBuilder()
+		rule.Command().
+			Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+			FlagWithOutput("-o ", image.zip).
+			FlagWithArg("-C ", image.dir.String()).
+			FlagWithInputList("-f ", allFiles, " -f ")
+
+		rule.Build(pctx, ctx, "zip_"+image.name, "zip "+image.name+" image")
+	}
+
 	return image
 }
 
 func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
-	arch android.ArchType, profile android.Path, missingDeps []string) {
+	arch android.ArchType, profile android.Path, missingDeps []string) android.WritablePaths {
 
 	global := dexpreoptGlobalConfig(ctx)
 
@@ -290,6 +305,8 @@
 	var vdexInstalls android.RuleBuilderInstalls
 	var unstrippedInstalls android.RuleBuilderInstalls
 
+	var zipFiles android.WritablePaths
+
 	// dex preopt on the bootclasspath produces multiple files.  The first dex file
 	// is converted into to 'name'.art (to match the legacy assumption that 'name'.art
 	// exists), and the rest are converted to 'name'-<jar>.art.
@@ -308,6 +325,8 @@
 
 		extraFiles = append(extraFiles, art, oat, vdex, unstrippedOat)
 
+		zipFiles = append(zipFiles, art, oat, vdex)
+
 		// Install the .oat and .art files.
 		rule.Install(art, filepath.Join(installDir, art.Base()))
 		rule.Install(oat, filepath.Join(installDir, oat.Base()))
@@ -331,6 +350,8 @@
 	image.installs[arch] = rule.Installs()
 	image.vdexInstalls[arch] = vdexInstalls
 	image.unstrippedInstalls[arch] = unstrippedInstalls
+
+	return zipFiles
 }
 
 const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -443,15 +464,25 @@
 		ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
 		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPaths.Strings(), " "))
 		ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocations, " "))
+		ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+image.name, image.zip.String())
 
 		var imageNames []string
 		for _, current := range append(d.otherImages, image) {
 			imageNames = append(imageNames, current.name)
+			var arches []android.ArchType
 			for arch, _ := range current.images {
+				arches = append(arches, arch)
+			}
+
+			sort.Slice(arches, func(i, j int) bool { return arches[i].String() < arches[j].String() })
+
+			for _, arch := range arches {
 				ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.vdexInstalls[arch].String())
 				ctx.Strict("DEXPREOPT_IMAGE_"+current.name+"_"+arch.String(), current.images[arch].String())
 				ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.installs[arch].String())
 				ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.unstrippedInstalls[arch].String())
+				if current.zip != nil {
+				}
 			}
 		}
 		ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 409b4b1..b30bd00 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -111,6 +111,7 @@
 		dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars")
 		symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_unstripped")
 		images := make(map[android.ArchType]android.OutputPath)
+		zip := dir.Join(ctx, "boot.zip")
 
 		for _, target := range ctx.Config().Targets[android.Android] {
 			images[target.Arch.ArchType] = dir.Join(ctx,
@@ -125,6 +126,7 @@
 			dir:          dir,
 			symbolsDir:   symbolsDir,
 			images:       images,
+			zip:          zip,
 		}
 	}).(bootImageConfig)
 }
diff --git a/java/kotlin.go b/java/kotlin.go
index 054998f..54c6b0e 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -27,11 +27,12 @@
 
 var kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
 	blueprint.RuleParams{
-		Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" && mkdir -p "$classesDir" "$srcJarDir" && ` +
+		Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
+			`mkdir -p "$classesDir" "$srcJarDir" "$emptyDir" && ` +
 			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 			`${config.GenKotlinBuildFileCmd} $classpath $classesDir $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
 			`${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` +
-			`-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile && ` +
+			`-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile -kotlin-home $emptyDir && ` +
 			`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` +
 			`rm -rf "$srcJarDir"`,
 		CommandDeps: []string{
@@ -49,7 +50,7 @@
 		Rspfile:        "$out.rsp",
 		RspfileContent: `$in`,
 	},
-	"kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile")
+	"kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir")
 
 // kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
 func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -73,6 +74,7 @@
 			"classesDir":      android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
 			"srcJarDir":       android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
 			"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
+			"emptyDir":        android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
 			// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
 			"kotlinJvmTarget": "1.8",
 		},