Merge changes Ieb4ffa10,I9458cbc4

* changes:
  soong_ui: Do not clean the OutDir path multiple times.
  soong_ui: Construct the proper MODULES-IN-<dir name> for m* build commands.
diff --git a/Android.bp b/Android.bp
index 1b68adb..4893de6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -81,6 +81,7 @@
     ],
     testSrcs: [
         "android/android_test.go",
+        "android/androidmk_test.go",
         "android/arch_test.go",
         "android/config_test.go",
         "android/expand_test.go",
@@ -291,6 +292,7 @@
         "java/testing.go",
     ],
     testSrcs: [
+        "java/androidmk_test.go",
         "java/app_test.go",
         "java/device_host_converter_test.go",
         "java/dexpreopt_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 9bc2692..1f1bd70 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -191,15 +191,7 @@
 		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
 		if archStr != "common" {
 			if amod.Target().NativeBridge {
-				// TODO: Unhardcode these rules.
-				guestArchStr := archStr
-				hostArchStr := ""
-				if guestArchStr == "arm" {
-					hostArchStr = "x86"
-				} else if guestArchStr == "arm64" {
-					hostArchStr = "x86_64"
-				}
-
+				hostArchStr := amod.Target().NativeBridgeHostArchName
 				if hostArchStr != "" {
 					a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
 				}
@@ -391,6 +383,31 @@
 	return nil
 }
 
+func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) {
+	// Get the preamble content through AndroidMkEntries logic.
+	entries := AndroidMkEntries{
+		Class:           data.Class,
+		SubName:         data.SubName,
+		DistFile:        data.DistFile,
+		OutputFile:      data.OutputFile,
+		Disabled:        data.Disabled,
+		Include:         data.Include,
+		Required:        data.Required,
+		Host_required:   data.Host_required,
+		Target_required: data.Target_required,
+	}
+	entries.fillInEntries(config, bpPath, mod)
+
+	// preamble doesn't need the footer content.
+	entries.footer = bytes.Buffer{}
+	entries.write(&data.preamble)
+
+	// copy entries back to data since it is used in Custom
+	data.Required = entries.Required
+	data.Host_required = entries.Host_required
+	data.Target_required = entries.Target_required
+}
+
 func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
 	provider AndroidMkDataProvider) error {
 
@@ -404,22 +421,7 @@
 		data.Include = "$(BUILD_PREBUILT)"
 	}
 
-	// Get the preamble content through AndroidMkEntries logic.
-	entries := AndroidMkEntries{
-		Class:           data.Class,
-		SubName:         data.SubName,
-		DistFile:        data.DistFile,
-		OutputFile:      data.OutputFile,
-		Disabled:        data.Disabled,
-		Include:         data.Include,
-		Required:        data.Required,
-		Host_required:   data.Host_required,
-		Target_required: data.Target_required,
-	}
-	entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
-	// preamble doesn't need the footer content.
-	entries.footer = bytes.Buffer{}
-	entries.write(&data.preamble)
+	data.fillInData(ctx.Config(), ctx.BlueprintFile(mod), mod)
 
 	prefix := ""
 	if amod.ArchSpecific() {
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
new file mode 100644
index 0000000..0bb455b
--- /dev/null
+++ b/android/androidmk_test.go
@@ -0,0 +1,82 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"io"
+	"reflect"
+	"testing"
+)
+
+type customModule struct {
+	ModuleBase
+	data AndroidMkData
+}
+
+func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (m *customModule) AndroidMk() AndroidMkData {
+	return AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
+			m.data = data
+		},
+	}
+}
+
+func customModuleFactory() Module {
+	module := &customModule{}
+	InitAndroidModule(module)
+	return module
+}
+
+func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
+	config := TestConfig(buildDir, nil)
+	config.inMake = true // Enable androidmk Singleton
+
+	ctx := NewTestContext()
+	ctx.RegisterSingletonType("androidmk", SingletonFactoryAdaptor(AndroidMkSingleton))
+	ctx.RegisterModuleType("custom", ModuleFactoryAdaptor(customModuleFactory))
+	ctx.Register()
+
+	bp := `
+	custom {
+		name: "foo",
+		required: ["bar"],
+		host_required: ["baz"],
+		target_required: ["qux"],
+	}
+	`
+
+	ctx.MockFileSystem(map[string][]byte{
+		"Android.bp": []byte(bp),
+	})
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	m := ctx.ModuleForTests("foo", "").Module().(*customModule)
+
+	assertEqual := func(expected interface{}, actual interface{}) {
+		if !reflect.DeepEqual(expected, actual) {
+			t.Errorf("%q expected, but got %q", expected, actual)
+		}
+	}
+	assertEqual([]string{"bar"}, m.data.Required)
+	assertEqual([]string{"baz"}, m.data.Host_required)
+	assertEqual([]string{"qux"}, m.data.Target_required)
+}
diff --git a/android/arch.go b/android/arch.go
index 46e582c..44c3f48 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -691,9 +691,11 @@
 )
 
 type Target struct {
-	Os           OsType
-	Arch         Arch
-	NativeBridge NativeBridgeSupport
+	Os                       OsType
+	Arch                     Arch
+	NativeBridge             NativeBridgeSupport
+	NativeBridgeHostArchName string
+	NativeBridgeRelativePath string
 }
 
 func (target Target) String() string {
@@ -1403,7 +1405,8 @@
 	var targetErr error
 
 	addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string,
-		nativeBridgeEnabled NativeBridgeSupport) {
+		nativeBridgeEnabled NativeBridgeSupport, nativeBridgeHostArchName *string,
+		nativeBridgeRelativePath *string) {
 		if targetErr != nil {
 			return
 		}
@@ -1413,12 +1416,21 @@
 			targetErr = err
 			return
 		}
+		nativeBridgeRelativePathStr := String(nativeBridgeRelativePath)
+		nativeBridgeHostArchNameStr := String(nativeBridgeHostArchName)
+
+		// Use guest arch as relative install path by default
+		if nativeBridgeEnabled && nativeBridgeRelativePathStr == "" {
+			nativeBridgeRelativePathStr = arch.ArchType.String()
+		}
 
 		targets[os] = append(targets[os],
 			Target{
-				Os:           os,
-				Arch:         arch,
-				NativeBridge: nativeBridgeEnabled,
+				Os:                       os,
+				Arch:                     arch,
+				NativeBridge:             nativeBridgeEnabled,
+				NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
+				NativeBridgeRelativePath: nativeBridgeRelativePathStr,
 			})
 	}
 
@@ -1426,14 +1438,14 @@
 		return nil, fmt.Errorf("No host primary architecture set")
 	}
 
-	addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled)
+	addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
 
 	if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
-		addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled)
+		addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
 	}
 
 	if Bool(config.Host_bionic) {
-		addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled)
+		addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
 	}
 
 	if String(variables.CrossHost) != "" {
@@ -1446,10 +1458,10 @@
 			return nil, fmt.Errorf("No cross-host primary architecture set")
 		}
 
-		addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled)
+		addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
 
 		if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
-			addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled)
+			addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
 		}
 	}
 
@@ -1460,12 +1472,12 @@
 		}
 
 		addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
-			variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled)
+			variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil)
 
 		if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
 			addTarget(Android, *variables.DeviceSecondaryArch,
 				variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
-				variables.DeviceSecondaryAbi, NativeBridgeDisabled)
+				variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
 
 			deviceArches := targets[Android]
 			if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
@@ -1476,7 +1488,8 @@
 		if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
 			addTarget(Android, *variables.NativeBridgeArch,
 				variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
-				variables.NativeBridgeAbi, NativeBridgeEnabled)
+				variables.NativeBridgeAbi, NativeBridgeEnabled, variables.DeviceArch,
+				variables.NativeBridgeRelativePath)
 		}
 
 		if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
@@ -1484,7 +1497,10 @@
 			addTarget(Android, *variables.NativeBridgeSecondaryArch,
 				variables.NativeBridgeSecondaryArchVariant,
 				variables.NativeBridgeSecondaryCpuVariant,
-				variables.NativeBridgeSecondaryAbi, NativeBridgeEnabled)
+				variables.NativeBridgeSecondaryAbi,
+				NativeBridgeEnabled,
+				variables.DeviceSecondaryArch,
+				variables.NativeBridgeSecondaryRelativePath)
 		}
 	}
 
diff --git a/android/config.go b/android/config.go
index c0ed50f..8ced93a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -240,10 +240,10 @@
 	config := testConfig.config
 
 	config.Targets[Android] = []Target{
-		{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
-		{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
-		{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled},
-		{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled},
+		{Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
+		{Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
+		{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64"},
+		{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm"},
 	}
 
 	return testConfig
@@ -255,10 +255,10 @@
 
 	config.Targets = map[OsType][]Target{
 		Fuchsia: []Target{
-			{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}, NativeBridgeDisabled},
+			{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}, NativeBridgeDisabled, "", ""},
 		},
 		BuildOs: []Target{
-			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
+			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
 		},
 	}
 
@@ -272,12 +272,12 @@
 
 	config.Targets = map[OsType][]Target{
 		Android: []Target{
-			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
-			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
+			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", ""},
+			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", ""},
 		},
 		BuildOs: []Target{
-			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
-			{BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled},
+			{BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""},
+			{BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled, "", ""},
 		},
 	}
 
diff --git a/android/expand.go b/android/expand.go
index 527c4ac..67fb4ee 100644
--- a/android/expand.go
+++ b/android/expand.go
@@ -18,12 +18,30 @@
 	"fmt"
 	"strings"
 	"unicode"
+
+	"github.com/google/blueprint/proptools"
 )
 
+// ExpandNinjaEscaped substitutes $() variables in a string
+// $(var) is passed to mapping(var), which should return the expanded value, a bool for whether the result should
+// be left unescaped when using in a ninja value (generally false, true if the expanded value is a ninja variable like
+// '${in}'), and an error.
+// $$ is converted to $, which is escaped back to $$.
+func ExpandNinjaEscaped(s string, mapping func(string) (string, bool, error)) (string, error) {
+	return expand(s, true, mapping)
+}
+
 // Expand substitutes $() variables in a string
-// $(var) is passed to Expander(var)
-// $$ is converted to $
+// $(var) is passed to mapping(var), which should return the expanded value and an error.
+// $$ is converted to $.
 func Expand(s string, mapping func(string) (string, error)) (string, error) {
+	return expand(s, false, func(s string) (string, bool, error) {
+		s, err := mapping(s)
+		return s, false, err
+	})
+}
+
+func expand(s string, ninjaEscape bool, mapping func(string) (string, bool, error)) (string, error) {
 	// based on os.Expand
 	buf := make([]byte, 0, 2*len(s))
 	i := 0
@@ -33,10 +51,13 @@
 				return "", fmt.Errorf("expected character after '$'")
 			}
 			buf = append(buf, s[i:j]...)
-			value, w, err := getMapping(s[j+1:], mapping)
+			value, ninjaVariable, w, err := getMapping(s[j+1:], mapping)
 			if err != nil {
 				return "", err
 			}
+			if !ninjaVariable && ninjaEscape {
+				value = proptools.NinjaEscape(value)
+			}
 			buf = append(buf, value...)
 			j += w
 			i = j + 1
@@ -45,26 +66,26 @@
 	return string(buf) + s[i:], nil
 }
 
-func getMapping(s string, mapping func(string) (string, error)) (string, int, error) {
+func getMapping(s string, mapping func(string) (string, bool, error)) (string, bool, int, error) {
 	switch s[0] {
 	case '(':
 		// Scan to closing brace
 		for i := 1; i < len(s); i++ {
 			if s[i] == ')' {
-				ret, err := mapping(strings.TrimSpace(s[1:i]))
-				return ret, i + 1, err
+				ret, ninjaVariable, err := mapping(strings.TrimSpace(s[1:i]))
+				return ret, ninjaVariable, i + 1, err
 			}
 		}
-		return "", len(s), fmt.Errorf("missing )")
+		return "", false, len(s), fmt.Errorf("missing )")
 	case '$':
-		return "$$", 1, nil
+		return "$", false, 1, nil
 	default:
 		i := strings.IndexFunc(s, unicode.IsSpace)
 		if i == 0 {
-			return "", 0, fmt.Errorf("unexpected character '%c' after '$'", s[0])
+			return "", false, 0, fmt.Errorf("unexpected character '%c' after '$'", s[0])
 		} else if i == -1 {
 			i = len(s)
 		}
-		return "", 0, fmt.Errorf("expected '(' after '$', did you mean $(%s)?", s[:i])
+		return "", false, 0, fmt.Errorf("expected '(' after '$', did you mean $(%s)?", s[:i])
 	}
 }
diff --git a/android/expand_test.go b/android/expand_test.go
index 128de8a..12179ed 100644
--- a/android/expand_test.go
+++ b/android/expand_test.go
@@ -20,88 +20,111 @@
 )
 
 var vars = map[string]string{
-	"var1": "abc",
-	"var2": "",
-	"var3": "def",
-	"💩":    "😃",
+	"var1":   "abc",
+	"var2":   "",
+	"var3":   "def",
+	"💩":      "😃",
+	"escape": "${in}",
 }
 
-func expander(s string) (string, error) {
+func expander(s string) (string, bool, error) {
 	if val, ok := vars[s]; ok {
-		return val, nil
+		return val, s == "escape", nil
 	} else {
-		return "", fmt.Errorf("unknown variable %q", s)
+		return "", false, fmt.Errorf("unknown variable %q", s)
 	}
 }
 
 var expandTestCases = []struct {
-	in  string
-	out string
-	err bool
+	in          string
+	out         string
+	out_escaped string
+	err         bool
 }{
 	{
-		in:  "$(var1)",
-		out: "abc",
+		in:          "$(var1)",
+		out:         "abc",
+		out_escaped: "abc",
 	},
 	{
-		in:  "$( var1 )",
-		out: "abc",
+		in:          "$( var1 )",
+		out:         "abc",
+		out_escaped: "abc",
 	},
 	{
-		in:  "def$(var1)",
-		out: "defabc",
+		in:          "def$(var1)",
+		out:         "defabc",
+		out_escaped: "defabc",
 	},
 	{
-		in:  "$(var1)def",
-		out: "abcdef",
+		in:          "$(var1)def",
+		out:         "abcdef",
+		out_escaped: "abcdef",
 	},
 	{
-		in:  "def$(var1)def",
-		out: "defabcdef",
+		in:          "def$(var1)def",
+		out:         "defabcdef",
+		out_escaped: "defabcdef",
 	},
 	{
-		in:  "$(var2)",
-		out: "",
+		in:          "$(var2)",
+		out:         "",
+		out_escaped: "",
 	},
 	{
-		in:  "def$(var2)",
-		out: "def",
+		in:          "def$(var2)",
+		out:         "def",
+		out_escaped: "def",
 	},
 	{
-		in:  "$(var2)def",
-		out: "def",
+		in:          "$(var2)def",
+		out:         "def",
+		out_escaped: "def",
 	},
 	{
-		in:  "def$(var2)def",
-		out: "defdef",
+		in:          "def$(var2)def",
+		out:         "defdef",
+		out_escaped: "defdef",
 	},
 	{
-		in:  "$(var1)$(var3)",
-		out: "abcdef",
+		in:          "$(var1)$(var3)",
+		out:         "abcdef",
+		out_escaped: "abcdef",
 	},
 	{
-		in:  "$(var1)g$(var3)",
-		out: "abcgdef",
+		in:          "$(var1)g$(var3)",
+		out:         "abcgdef",
+		out_escaped: "abcgdef",
 	},
 	{
-		in:  "$$",
-		out: "$$",
+		in:          "$$",
+		out:         "$",
+		out_escaped: "$$",
 	},
 	{
-		in:  "$$(var1)",
-		out: "$$(var1)",
+		in:          "$$(var1)",
+		out:         "$(var1)",
+		out_escaped: "$$(var1)",
 	},
 	{
-		in:  "$$$(var1)",
-		out: "$$abc",
+		in:          "$$$(var1)",
+		out:         "$abc",
+		out_escaped: "$$abc",
 	},
 	{
-		in:  "$(var1)$$",
-		out: "abc$$",
+		in:          "$(var1)$$",
+		out:         "abc$",
+		out_escaped: "abc$$",
 	},
 	{
-		in:  "$(💩)",
-		out: "😃",
+		in:          "$(💩)",
+		out:         "😃",
+		out_escaped: "😃",
+	},
+	{
+		in:          "$$a$(escape)$$b",
+		out:         "$a${in}$b",
+		out_escaped: "$$a${in}$$b",
 	},
 
 	// Errors
@@ -141,7 +164,10 @@
 
 func TestExpand(t *testing.T) {
 	for _, test := range expandTestCases {
-		got, err := Expand(test.in, expander)
+		got, err := Expand(test.in, func(s string) (string, error) {
+			s, _, err := expander(s)
+			return s, err
+		})
 		if err != nil && !test.err {
 			t.Errorf("%q: unexpected error %s", test.in, err.Error())
 		} else if err == nil && test.err {
@@ -151,3 +177,16 @@
 		}
 	}
 }
+
+func TestExpandNinjaEscaped(t *testing.T) {
+	for _, test := range expandTestCases {
+		got, err := ExpandNinjaEscaped(test.in, expander)
+		if err != nil && !test.err {
+			t.Errorf("%q: unexpected error %s", test.in, err.Error())
+		} else if err == nil && test.err {
+			t.Errorf("%q: expected error, got %q", test.in, got)
+		} else if !test.err && got != test.out_escaped {
+			t.Errorf("%q: expected %q, got %q", test.in, test.out, got)
+		}
+	}
+}
diff --git a/android/notices.go b/android/notices.go
index 8503593..7b61d65 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -42,8 +42,8 @@
 	})
 
 	generateNoticeRule = pctx.AndroidStaticRule("generateNoticeRule", blueprint.RuleParams{
-		Command: `rm -rf $$(dirname $txtOut) $$(dirname htmlOut) $$(dirname $out) && ` +
-			`mkdir -p $$(dirname $txtOut) $$(dirname htmlOut)  $$(dirname $out) && ` +
+		Command: `rm -rf $$(dirname $txtOut) $$(dirname $htmlOut) $$(dirname $out) && ` +
+			`mkdir -p $$(dirname $txtOut) $$(dirname $htmlOut)  $$(dirname $out) && ` +
 			`${generate_notice} --text-output $txtOut --html-output $htmlOut -t "$title" -s $inputDir && ` +
 			`${minigzip} -c $htmlOut > $out`,
 		CommandDeps: []string{"${generate_notice}", "${minigzip}"},
diff --git a/android/path_properties.go b/android/path_properties.go
index af7af59..6b1cdb3 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -35,16 +35,17 @@
 
 	props := m.base().generalProperties
 
+	var pathProperties []string
 	for _, ps := range props {
-		pathProperties := pathPropertiesForPropertyStruct(ctx, ps)
-		pathProperties = FirstUniqueStrings(pathProperties)
+		pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...)
+	}
 
-		for _, s := range pathProperties {
-			if m, t := SrcIsModuleWithTag(s); m != "" {
-				ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
-			}
+	pathProperties = FirstUniqueStrings(pathProperties)
+
+	for _, s := range pathProperties {
+		if m, t := SrcIsModuleWithTag(s); m != "" {
+			ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
 		}
-
 	}
 }
 
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index e98c136..59bfa6c 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -28,12 +28,17 @@
 		Qux string
 	}
 
+	// A second property struct with a duplicate property name
+	props2 struct {
+		Foo string `android:"path"`
+	}
+
 	sourceDeps []string
 }
 
 func pathDepsMutatorTestModuleFactory() Module {
 	module := &pathDepsMutatorTestModule{}
-	module.AddProperties(&module.props)
+	module.AddProperties(&module.props, &module.props2)
 	InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
 	return module
 }
@@ -44,6 +49,13 @@
 			p.sourceDeps = append(p.sourceDeps, ctx.OtherModuleName(dep))
 		}
 	})
+
+	if p.props.Foo != "" {
+		// Make sure there is only one dependency on a module listed in a property present in multiple property structs
+		if ctx.GetDirectDepWithTag(SrcIsModule(p.props.Foo), sourceOrOutputDepTag("")) == nil {
+			ctx.ModuleErrorf("GetDirectDepWithTag failed")
+		}
+	}
 }
 
 func TestPathDepsMutator(t *testing.T) {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index ad7c4aa..b674153 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -215,3 +215,7 @@
 	}
 	return value.String()
 }
+
+func (p *Prebuilt) SourceExists() bool {
+	return p.properties.SourceExists
+}
diff --git a/android/proto.go b/android/proto.go
index 5247c68..c8ade45 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -135,7 +135,7 @@
 	}
 
 	rule.Command().
-		Tool(ctx.Config().HostToolPath(ctx, "aprotoc")).
+		BuiltTool(ctx, "aprotoc").
 		FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()).
 		FlagWithDepFile("--dependency_out=", depFile).
 		FlagWithArg("-I ", protoBase).
@@ -145,5 +145,5 @@
 		ImplicitOutputs(outputs)
 
 	rule.Command().
-		Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).Flag(depFile.String())
+		BuiltTool(ctx, "dep_fixer").Flag(depFile.String())
 }
diff --git a/android/rule_builder.go b/android/rule_builder.go
index e53eb0d..1238ddc 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -263,11 +263,36 @@
 	return toolsList
 }
 
-// Commands returns a slice containing a the built command line for each call to RuleBuilder.Command.
+// RspFileInputs returns the list of paths that were passed to the RuleBuilderCommand.FlagWithRspFileInputList method.
+func (r *RuleBuilder) RspFileInputs() Paths {
+	var rspFileInputs Paths
+	for _, c := range r.commands {
+		if c.rspFileInputs != nil {
+			if rspFileInputs != nil {
+				panic("Multiple commands in a rule may not have rsp file inputs")
+			}
+			rspFileInputs = c.rspFileInputs
+		}
+	}
+
+	return rspFileInputs
+}
+
+// Commands returns a slice containing the built command line for each call to RuleBuilder.Command.
 func (r *RuleBuilder) Commands() []string {
 	var commands []string
 	for _, c := range r.commands {
-		commands = append(commands, c.buf.String())
+		commands = append(commands, c.String())
+	}
+	return commands
+}
+
+// NinjaEscapedCommands returns a slice containin the built command line after ninja escaping for each call to
+// RuleBuilder.Command.
+func (r *RuleBuilder) NinjaEscapedCommands() []string {
+	var commands []string
+	for _, c := range r.commands {
+		commands = append(commands, c.NinjaEscapedString())
 	}
 	return commands
 }
@@ -284,7 +309,7 @@
 
 func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
 	return r.Command().
-		Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).
+		BuiltTool(ctx, "dep_fixer").
 		Inputs(depFiles.Paths())
 }
 
@@ -324,7 +349,7 @@
 	}
 
 	tools := r.Tools()
-	commands := r.Commands()
+	commands := r.NinjaEscapedCommands()
 	outputs := r.Outputs()
 
 	if len(commands) == 0 {
@@ -334,7 +359,7 @@
 		panic("No outputs specified from any Commands")
 	}
 
-	commandString := strings.Join(proptools.NinjaEscapeList(commands), " && ")
+	commandString := strings.Join(commands, " && ")
 
 	if r.sbox {
 		sboxOutputs := make([]string, len(outputs))
@@ -352,7 +377,7 @@
 		}
 
 		sboxCmd := &RuleBuilderCommand{}
-		sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")).
+		sboxCmd.BuiltTool(ctx, "sbox").
 			Flag("-c").Text(commandString).
 			Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
 			Flag("--output-root").Text(r.sboxOutDir.String()).
@@ -363,17 +388,27 @@
 	}
 
 	// 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.
+	// ImplicitOutputs.  RuleBuilder only uses "$out" for the rsp file location, so the distinction between Outputs and
+	// ImplicitOutputs doesn't matter.
 	output := outputs[0]
 	implicitOutputs := outputs[1:]
 
+	var rspFile, rspFileContent string
+	rspFileInputs := r.RspFileInputs()
+	if rspFileInputs != nil {
+		rspFile = "$out.rsp"
+		rspFileContent = "$in"
+	}
+
 	ctx.Build(pctx, BuildParams{
 		Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
-			Command:     commandString,
-			CommandDeps: tools.Strings(),
-			Restat:      r.restat,
+			Command:        commandString,
+			CommandDeps:    tools.Strings(),
+			Restat:         r.restat,
+			Rspfile:        rspFile,
+			RspfileContent: rspFileContent,
 		}),
+		Inputs:          rspFileInputs,
 		Implicits:       r.Inputs(),
 		Output:          output,
 		ImplicitOutputs: implicitOutputs,
@@ -388,11 +423,15 @@
 // RuleBuilderCommand, so they can be used chained or unchained.  All methods that add text implicitly add a single
 // space as a separator from the previous method.
 type RuleBuilderCommand struct {
-	buf      strings.Builder
-	inputs   Paths
-	outputs  WritablePaths
-	depFiles WritablePaths
-	tools    Paths
+	buf           strings.Builder
+	inputs        Paths
+	outputs       WritablePaths
+	depFiles      WritablePaths
+	tools         Paths
+	rspFileInputs Paths
+
+	// spans [start,end) of the command that should not be ninja escaped
+	unescapedSpans [][2]int
 
 	sbox       bool
 	sboxOutDir WritablePath
@@ -478,6 +517,24 @@
 	return c.Text(path.String())
 }
 
+// BuiltTool adds the specified tool path that was built using a host Soong module to the command line.  The path will
+// be also added to the dependencies returned by RuleBuilder.Tools.
+//
+// It is equivalent to:
+//  cmd.Tool(ctx.Config().HostToolPath(ctx, tool))
+func (c *RuleBuilderCommand) BuiltTool(ctx PathContext, tool string) *RuleBuilderCommand {
+	return c.Tool(ctx.Config().HostToolPath(ctx, tool))
+}
+
+// PrebuiltBuildTool adds the specified tool path from prebuils/build-tools.  The path will be also added to the
+// dependencies returned by RuleBuilder.Tools.
+//
+// It is equivalent to:
+//  cmd.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool))
+func (c *RuleBuilderCommand) PrebuiltBuildTool(ctx PathContext, tool string) *RuleBuilderCommand {
+	return c.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool))
+}
+
 // 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 {
@@ -606,11 +663,56 @@
 	return c.Text(flag + c.outputStr(path))
 }
 
+// FlagWithRspFileInputList adds the specified flag and path to an rspfile to the command line, with no separator
+// between them.  The paths will be written to the rspfile.
+func (c *RuleBuilderCommand) FlagWithRspFileInputList(flag string, paths Paths) *RuleBuilderCommand {
+	if c.rspFileInputs != nil {
+		panic("FlagWithRspFileInputList cannot be called if rsp file inputs have already been provided")
+	}
+
+	// Use an empty slice if paths is nil, the non-nil slice is used as an indicator that the rsp file must be
+	// generated.
+	if paths == nil {
+		paths = Paths{}
+	}
+
+	c.rspFileInputs = paths
+
+	rspFile := "$out.rsp"
+	c.FlagWithArg(flag, rspFile)
+	c.unescapedSpans = append(c.unescapedSpans, [2]int{c.buf.Len() - len(rspFile), c.buf.Len()})
+	return c
+}
+
 // String returns the command line.
 func (c *RuleBuilderCommand) String() string {
 	return c.buf.String()
 }
 
+// String returns the command line.
+func (c *RuleBuilderCommand) NinjaEscapedString() string {
+	return ninjaEscapeExceptForSpans(c.String(), c.unescapedSpans)
+}
+
+func ninjaEscapeExceptForSpans(s string, spans [][2]int) string {
+	if len(spans) == 0 {
+		return proptools.NinjaEscape(s)
+	}
+
+	sb := strings.Builder{}
+	sb.Grow(len(s) * 11 / 10)
+
+	i := 0
+	for _, span := range spans {
+		sb.WriteString(proptools.NinjaEscape(s[i:span[0]]))
+		sb.WriteString(s[span[0]:span[1]])
+		i = span[1]
+	}
+	sb.WriteString(proptools.NinjaEscape(s[i:]))
+
+	return sb.String()
+}
+
 func ninjaNameEscape(s string) string {
 	b := []byte(s)
 	escaped := false
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index cfbc2ab..6eba4f1 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -38,6 +38,7 @@
 			"ls":      nil,
 			"turbine": nil,
 			"java":    nil,
+			"javac":   nil,
 		})
 }
 
@@ -235,6 +236,34 @@
 	// ls --sort=time,size
 }
 
+func ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
+	ctx := pathContext()
+	fmt.Println(NewRuleBuilder().Command().
+		Tool(PathForSource(ctx, "javac")).
+		FlagWithRspFileInputList("@", PathsForTesting("a.java", "b.java")).
+		NinjaEscapedString())
+	// Output:
+	// javac @$out.rsp
+}
+
+func ExampleRuleBuilderCommand_String() {
+	fmt.Println(NewRuleBuilder().Command().
+		Text("FOO=foo").
+		Text("echo $FOO").
+		String())
+	// Output:
+	// FOO=foo echo $FOO
+}
+
+func ExampleRuleBuilderCommand_NinjaEscapedString() {
+	fmt.Println(NewRuleBuilder().Command().
+		Text("FOO=foo").
+		Text("echo $FOO").
+		NinjaEscapedString())
+	// Output:
+	// FOO=foo echo $$FOO
+}
+
 func TestRuleBuilder(t *testing.T) {
 	fs := map[string][]byte{
 		"dep_fixer": nil,
@@ -503,3 +532,77 @@
 			"cp bar "+outFile, outFile, outFile+".d", true, nil)
 	})
 }
+
+func Test_ninjaEscapeExceptForSpans(t *testing.T) {
+	type args struct {
+		s     string
+		spans [][2]int
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{
+			name: "empty",
+			args: args{
+				s: "",
+			},
+			want: "",
+		},
+		{
+			name: "unescape none",
+			args: args{
+				s: "$abc",
+			},
+			want: "$$abc",
+		},
+		{
+			name: "unescape all",
+			args: args{
+				s:     "$abc",
+				spans: [][2]int{{0, 4}},
+			},
+			want: "$abc",
+		},
+		{
+			name: "unescape first",
+			args: args{
+				s:     "$abc$",
+				spans: [][2]int{{0, 1}},
+			},
+			want: "$abc$$",
+		},
+		{
+			name: "unescape last",
+			args: args{
+				s:     "$abc$",
+				spans: [][2]int{{4, 5}},
+			},
+			want: "$$abc$",
+		},
+		{
+			name: "unescape middle",
+			args: args{
+				s:     "$a$b$c$",
+				spans: [][2]int{{2, 5}},
+			},
+			want: "$$a$b$c$$",
+		},
+		{
+			name: "unescape multiple",
+			args: args{
+				s:     "$a$b$c$",
+				spans: [][2]int{{2, 3}, {4, 5}},
+			},
+			want: "$$a$b$c$$",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := ninjaEscapeExceptForSpans(tt.args.s, tt.args.spans); got != tt.want {
+				t.Errorf("ninjaEscapeExceptForSpans() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/android/testing.go b/android/testing.go
index 44bee4b..12e30ec 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -382,3 +382,14 @@
 	entries.fillInEntries(config, bpPath, mod)
 	return entries
 }
+
+func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData {
+	var p AndroidMkDataProvider
+	var ok bool
+	if p, ok = mod.(AndroidMkDataProvider); !ok {
+		t.Errorf("module does not implmement AndroidMkDataProvider: " + mod.Name())
+	}
+	data := p.AndroidMk()
+	data.fillInData(config, bpPath, mod)
+	return data
+}
diff --git a/android/util.go b/android/util.go
index 3b8bc78..97bec10 100644
--- a/android/util.go
+++ b/android/util.go
@@ -115,6 +115,17 @@
 	return false
 }
 
+// IndexListPred returns the index of the element which in the given `list` satisfying the predicate, or -1 if there is no such element.
+func IndexListPred(pred func(s string) bool, list []string) int {
+	for i, l := range list {
+		if pred(l) {
+			return i
+		}
+	}
+
+	return -1
+}
+
 func FilterList(list []string, filter []string) (remainder []string, filtered []string) {
 	for _, l := range list {
 		if InList(l, filter) {
diff --git a/android/variable.go b/android/variable.go
index fcd92d4..47586a7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -165,15 +165,17 @@
 	DeviceSecondaryCpuVariant  *string  `json:",omitempty"`
 	DeviceSecondaryAbi         []string `json:",omitempty"`
 
-	NativeBridgeArch        *string  `json:",omitempty"`
-	NativeBridgeArchVariant *string  `json:",omitempty"`
-	NativeBridgeCpuVariant  *string  `json:",omitempty"`
-	NativeBridgeAbi         []string `json:",omitempty"`
+	NativeBridgeArch         *string  `json:",omitempty"`
+	NativeBridgeArchVariant  *string  `json:",omitempty"`
+	NativeBridgeCpuVariant   *string  `json:",omitempty"`
+	NativeBridgeAbi          []string `json:",omitempty"`
+	NativeBridgeRelativePath *string  `json:",omitempty"`
 
-	NativeBridgeSecondaryArch        *string  `json:",omitempty"`
-	NativeBridgeSecondaryArchVariant *string  `json:",omitempty"`
-	NativeBridgeSecondaryCpuVariant  *string  `json:",omitempty"`
-	NativeBridgeSecondaryAbi         []string `json:",omitempty"`
+	NativeBridgeSecondaryArch         *string  `json:",omitempty"`
+	NativeBridgeSecondaryArchVariant  *string  `json:",omitempty"`
+	NativeBridgeSecondaryCpuVariant   *string  `json:",omitempty"`
+	NativeBridgeSecondaryAbi          []string `json:",omitempty"`
+	NativeBridgeSecondaryRelativePath *string  `json:",omitempty"`
 
 	HostArch          *string `json:",omitempty"`
 	HostSecondaryArch *string `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index f95bd05..9701e2a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -656,8 +656,10 @@
 		dirInApex = "lib64"
 	}
 	dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
-	if cc.Target().NativeBridge == android.NativeBridgeEnabled || !cc.Arch().Native {
+	if !cc.Arch().Native {
 		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
+	} else if cc.Target().NativeBridge == android.NativeBridgeEnabled {
+		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
 	}
 	if handleSpecialLibs {
 		switch cc.Name() {
@@ -681,8 +683,10 @@
 
 func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
 	dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
-	if cc.Target().NativeBridge == android.NativeBridgeEnabled || !cc.Arch().Native {
+	if !cc.Arch().Native {
 		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
+	} else if cc.Target().NativeBridge == android.NativeBridgeEnabled {
+		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
 	}
 	fileToCopy = cc.OutputFile().Path()
 	return
@@ -1403,7 +1407,8 @@
 
 type PrebuiltProperties struct {
 	// the path to the prebuilt .apex file to import.
-	Source string `blueprint:"mutated"`
+	Source       string `blueprint:"mutated"`
+	ForceDisable bool   `blueprint:"mutated"`
 
 	Src  *string
 	Arch struct {
@@ -1432,6 +1437,23 @@
 }
 
 func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// If the device is configured to use flattened APEX, force disable the prebuilt because
+	// the prebuilt is a non-flattened one.
+	forceDisable := ctx.Config().FlattenApex()
+
+	// Force disable the prebuilts when we are doing unbundled build. We do unbundled build
+	// to build the prebuilts themselves.
+	forceDisable = forceDisable || ctx.Config().UnbundledBuild()
+
+	// b/137216042 don't use prebuilts when address sanitizer is on
+	forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
+		android.InList("hwaddress", ctx.Config().SanitizeDevice())
+
+	if forceDisable && p.prebuilt.SourceExists() {
+		p.properties.ForceDisable = true
+		return
+	}
+
 	// This is called before prebuilt_select and prebuilt_postdeps mutators
 	// The mutators requires that src to be set correctly for each arch so that
 	// arch variants are disabled when src is not provided for the arch.
@@ -1473,6 +1495,10 @@
 }
 
 func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if p.properties.ForceDisable {
+		return
+	}
+
 	// TODO(jungjw): Check the key validity.
 	p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
 	p.installDir = android.PathForModuleInstall(ctx, "apex")
diff --git a/cc/builder.go b/cc/builder.go
index ee40736..cbe2c88 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -78,7 +78,7 @@
 		blueprint.RuleParams{
 			// Without -no-pie, clang 7.0 adds -pie to link Android files,
 			// but -r and -pie cannot be used together.
-			Command:     "$ldCmd -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
+			Command:     "$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
 			CommandDeps: []string{"$ldCmd"},
 		},
 		"ldCmd", "ldFlags")
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index d9c96df..bcfae5d 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -63,7 +63,7 @@
 	}
 
 	x86_64ArchFeatureCflags = map[string][]string{
-		"ssse3":  []string{"-DUSE_SSSE3", "-mssse3"},
+		"ssse3":  []string{"-mssse3"},
 		"sse4":   []string{"-msse4"},
 		"sse4_1": []string{"-msse4.1"},
 		"sse4_2": []string{"-msse4.2"},
diff --git a/cc/config/x86_64_fuchsia_device.go b/cc/config/x86_64_fuchsia_device.go
index 79af00c..0f2013b 100644
--- a/cc/config/x86_64_fuchsia_device.go
+++ b/cc/config/x86_64_fuchsia_device.go
@@ -92,7 +92,7 @@
 }
 
 func (t *toolchainFuchsiaX8664) ToolchainClangCflags() string {
-	return "-DUSE_SSSE3 -mssse3"
+	return "-mssse3"
 }
 
 var toolchainFuchsiaSingleton Toolchain = &toolchainFuchsiaX8664{}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 6504758..64392dc 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -82,7 +82,7 @@
 	}
 
 	x86ArchFeatureCflags = map[string][]string{
-		"ssse3":  []string{"-DUSE_SSSE3", "-mssse3"},
+		"ssse3":  []string{"-mssse3"},
 		"sse4":   []string{"-msse4"},
 		"sse4_1": []string{"-msse4.1"},
 		"sse4_2": []string{"-msse4.2"},
diff --git a/cc/gen.go b/cc/gen.go
index 7516b28..e5c4194 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -99,7 +99,7 @@
 
 	cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison").
 		FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")).
-		Tool(ctx.Config().PrebuiltBuildTool(ctx, "bison")).
+		PrebuiltBuildTool(ctx, "bison").
 		Flag("-d").
 		Flags(flags).
 		FlagWithOutput("--defines=", headerFile).
@@ -121,7 +121,7 @@
 	headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
 
 	cmd := rule.Command()
-	cmd.Tool(ctx.Config().HostToolPath(ctx, "aidl-cpp")).
+	cmd.BuiltTool(ctx, "aidl-cpp").
 		FlagWithDepFile("-d", depFile).
 		Flag("--ninja").
 		Flag(aidlFlags).
diff --git a/cc/installer.go b/cc/installer.go
index cb261b7..a52ccf1 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -66,9 +66,12 @@
 	if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
 		dir = installer.dir64
 	}
-	if (!ctx.Host() && !ctx.Arch().Native) || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+	if !ctx.Host() && !ctx.Arch().Native {
 		dir = filepath.Join(dir, ctx.Arch().ArchType.String())
 	}
+	if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+		dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
+	}
 	if installer.location == InstallInData && ctx.useVndk() {
 		dir = filepath.Join(dir, "vendor")
 	}
diff --git a/cc/linker.go b/cc/linker.go
index dda2fcb..fa3b0a6 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -483,7 +483,7 @@
 		Input:       in,
 		Output:      out,
 		Args: map[string]string{
-			"buildNumberFromFile": ctx.Config().BuildNumberFromFile(),
+			"buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
 		},
 	})
 }
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 0eb9a74..c59f53a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -445,7 +445,6 @@
 			// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
 			flags.LdFlags = append(flags.LdFlags, "-Wl,--no-as-needed")
 		} else {
-			flags.CFlags = append(flags.CFlags, "-mllvm", "-asan-globals=0")
 			if ctx.bootstrap() {
 				flags.DynamicLinker = "/system/bin/bootstrap/linker_asan"
 			} else {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b0657ff..411da05 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -284,12 +284,12 @@
 
 	referencedDepfile := false
 
-	rawCommand, err := android.Expand(task.cmd, func(name string) (string, error) {
+	rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
 		// report the error directly without returning an error to android.Expand to catch multiple errors in a
 		// single run
-		reportError := func(fmt string, args ...interface{}) (string, error) {
+		reportError := func(fmt string, args ...interface{}) (string, bool, error) {
 			ctx.PropertyErrorf("cmd", fmt, args...)
-			return "SOONG_ERROR", nil
+			return "SOONG_ERROR", false, nil
 		}
 
 		switch name {
@@ -304,19 +304,19 @@
 				return reportError("default label %q has multiple files, use $(locations %s) to reference it",
 					firstLabel, firstLabel)
 			}
-			return locationLabels[firstLabel][0], nil
+			return locationLabels[firstLabel][0], false, nil
 		case "in":
-			return "${in}", nil
+			return "${in}", true, nil
 		case "out":
-			return "__SBOX_OUT_FILES__", nil
+			return "__SBOX_OUT_FILES__", false, nil
 		case "depfile":
 			referencedDepfile = true
 			if !Bool(g.properties.Depfile) {
 				return reportError("$(depfile) used without depfile property")
 			}
-			return "__SBOX_DEPFILE__", nil
+			return "__SBOX_DEPFILE__", false, nil
 		case "genDir":
-			return "__SBOX_OUT_DIR__", nil
+			return "__SBOX_OUT_DIR__", false, nil
 		default:
 			if strings.HasPrefix(name, "location ") {
 				label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -327,7 +327,7 @@
 						return reportError("label %q has multiple files, use $(locations %s) to reference it",
 							label, label)
 					}
-					return paths[0], nil
+					return paths[0], false, nil
 				} else {
 					return reportError("unknown location label %q", label)
 				}
@@ -337,7 +337,7 @@
 					if len(paths) == 0 {
 						return reportError("label %q has no files", label)
 					}
-					return strings.Join(paths, " "), nil
+					return strings.Join(paths, " "), false, nil
 				} else {
 					return reportError("unknown locations label %q", label)
 				}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
new file mode 100644
index 0000000..107837d
--- /dev/null
+++ b/java/androidmk_test.go
@@ -0,0 +1,184 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"android/soong/android"
+	"bytes"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+type testAndroidMk struct {
+	*testing.T
+	body []byte
+}
+type testAndroidMkModule struct {
+	*testing.T
+	props map[string]string
+}
+
+func newTestAndroidMk(t *testing.T, r io.Reader) *testAndroidMk {
+	t.Helper()
+	buf, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal("failed to open read Android.mk.", err)
+	}
+	return &testAndroidMk{
+		T:    t,
+		body: buf,
+	}
+}
+
+func parseAndroidMkProps(lines []string) map[string]string {
+	props := make(map[string]string)
+	for _, line := range lines {
+		line = strings.TrimLeft(line, " ")
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		tokens := strings.Split(line, " ")
+		if tokens[1] == "+=" {
+			props[tokens[0]] += " " + strings.Join(tokens[2:], " ")
+		} else {
+			props[tokens[0]] = strings.Join(tokens[2:], " ")
+		}
+	}
+	return props
+}
+
+func (t *testAndroidMk) moduleFor(moduleName string) *testAndroidMkModule {
+	t.Helper()
+	lines := strings.Split(string(t.body), "\n")
+	index := android.IndexList("LOCAL_MODULE := "+moduleName, lines)
+	if index == -1 {
+		t.Fatalf("%q is not found.", moduleName)
+	}
+	lines = lines[index:]
+	includeIndex := android.IndexListPred(func(line string) bool {
+		return strings.HasPrefix(line, "include")
+	}, lines)
+	if includeIndex == -1 {
+		t.Fatalf("%q is not properly defined. (\"include\" not found).", moduleName)
+	}
+	props := parseAndroidMkProps(lines[:includeIndex])
+	return &testAndroidMkModule{
+		T:     t.T,
+		props: props,
+	}
+}
+
+func (t *testAndroidMkModule) hasRequired(dep string) {
+	t.Helper()
+	required, ok := t.props["LOCAL_REQUIRED_MODULES"]
+	if !ok {
+		t.Error("LOCAL_REQUIRED_MODULES is not found.")
+		return
+	}
+	if !android.InList(dep, strings.Split(required, " ")) {
+		t.Errorf("%q is expected in LOCAL_REQUIRED_MODULES, but not found in %q.", dep, required)
+	}
+}
+
+func (t *testAndroidMkModule) hasNoRequired(dep string) {
+	t.Helper()
+	required, ok := t.props["LOCAL_REQUIRED_MODULES"]
+	if !ok {
+		return
+	}
+	if android.InList(dep, strings.Split(required, " ")) {
+		t.Errorf("%q is not expected in LOCAL_REQUIRED_MODULES, but found.", dep)
+	}
+}
+
+func getAndroidMk(t *testing.T, ctx *android.TestContext, config android.Config, name string) *testAndroidMk {
+	t.Helper()
+	lib, _ := ctx.ModuleForTests(name, "android_common").Module().(*Library)
+	data := android.AndroidMkDataForTest(t, config, "", lib)
+	w := &bytes.Buffer{}
+	data.Custom(w, name, "", "", data)
+	return newTestAndroidMk(t, w)
+}
+
+func TestRequired(t *testing.T) {
+	config := testConfig(nil)
+	ctx := testContext(config, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			required: ["libfoo"],
+		}
+	`, nil)
+	run(t, ctx, config)
+
+	mk := getAndroidMk(t, ctx, config, "foo")
+	mk.moduleFor("foo").hasRequired("libfoo")
+}
+
+func TestHostdex(t *testing.T) {
+	config := testConfig(nil)
+	ctx := testContext(config, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			hostdex: true,
+		}
+	`, nil)
+	run(t, ctx, config)
+
+	mk := getAndroidMk(t, ctx, config, "foo")
+	mk.moduleFor("foo")
+	mk.moduleFor("foo-hostdex")
+}
+
+func TestHostdexRequired(t *testing.T) {
+	config := testConfig(nil)
+	ctx := testContext(config, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			hostdex: true,
+			required: ["libfoo"],
+		}
+	`, nil)
+	run(t, ctx, config)
+
+	mk := getAndroidMk(t, ctx, config, "foo")
+	mk.moduleFor("foo").hasRequired("libfoo")
+	mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+}
+
+func TestHostdexSpecificRequired(t *testing.T) {
+	config := testConfig(nil)
+	ctx := testContext(config, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			hostdex: true,
+			target: {
+				hostdex: {
+					required: ["libfoo"],
+				},
+			},
+		}
+	`, nil)
+	run(t, ctx, config)
+
+	mk := getAndroidMk(t, ctx, config, "foo")
+	mk.moduleFor("foo").hasNoRequired("libfoo")
+	mk.moduleFor("foo-hostdex").hasRequired("libfoo")
+}
diff --git a/java/app.go b/java/app.go
index 3442658..a679e88 100644
--- a/java/app.go
+++ b/java/app.go
@@ -816,7 +816,7 @@
 	rule := android.NewRuleBuilder()
 	rule.Command().
 		Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
-		Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+		BuiltTool(ctx, "zip2zip").
 		FlagWithInput("-i ", inputPath).
 		FlagWithOutput("-o ", outputPath).
 		FlagWithArg("-0 ", "'lib/**/*.so'").
@@ -843,7 +843,7 @@
 	rule := android.NewRuleBuilder()
 	rule.Command().
 		Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
-		Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+		BuiltTool(ctx, "zip2zip").
 		FlagWithInput("-i ", inputPath).
 		FlagWithOutput("-o ", outputPath).
 		FlagWithArg("-0 ", "'classes*.dex'").
@@ -1067,7 +1067,7 @@
 	outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
 
 	rule := android.NewRuleBuilder()
-	cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")).
+	cmd := rule.Command().BuiltTool(ctx, "manifest_check").
 		Flag("--enforce-uses-libraries").
 		Input(manifest).
 		FlagWithOutput("-o ", outputFile)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index fe468a9..4ef5bcf 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -229,7 +229,7 @@
 	if image.zip != nil {
 		rule := android.NewRuleBuilder()
 		rule.Command().
-			Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+			BuiltTool(ctx, "soong_zip").
 			FlagWithOutput("-o ", image.zip).
 			FlagWithArg("-C ", image.dir.String()).
 			FlagWithInputList("-f ", allFiles, " -f ")
@@ -438,7 +438,7 @@
 		rule := android.NewRuleBuilder()
 		rule.Command().
 			// TODO: for now, use the debug version for better error reporting
-			Tool(ctx.Config().HostToolPath(ctx, "oatdumpd")).
+			BuiltTool(ctx, "oatdumpd").
 			FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":").
 			FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":").
 			FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]).
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 25101de..ae810e1 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -500,6 +500,7 @@
 	}
 }
 
+// javadoc converts .java source files to documentation using javadoc.
 func JavadocFactory() android.Module {
 	module := &Javadoc{}
 
@@ -509,6 +510,7 @@
 	return module
 }
 
+// javadoc_host converts .java source files to documentation using javadoc.
 func JavadocHostFactory() android.Module {
 	module := &Javadoc{}
 
@@ -798,7 +800,7 @@
 			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
 			"stubsDir":          android.PathForModuleOut(ctx, "stubsDir").String(),
 			"srcJars":           strings.Join(j.srcJars.Strings(), " "),
-			"opts":              opts,
+			"opts":              proptools.NinjaEscape(opts),
 			"bootclasspathArgs": bootClasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepathArgs":    sourcepathArgs,
@@ -831,6 +833,7 @@
 	apiFilePath android.Path
 }
 
+// droiddoc converts .java source files to documentation using doclava or dokka.
 func DroiddocFactory() android.Module {
 	module := &Droiddoc{}
 
@@ -841,6 +844,7 @@
 	return module
 }
 
+// droiddoc_host converts .java source files to documentation using doclava or dokka.
 func DroiddocHostFactory() android.Module {
 	module := &Droiddoc{}
 
@@ -918,7 +922,7 @@
 	args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
 		"-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
 		"-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
-		`-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
+		`-hdf page.now "$(` + date + ` @$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
 
 	if String(d.properties.Custom_template) == "" {
 		// TODO: This is almost always droiddoc-templates-sdk
@@ -1095,7 +1099,7 @@
 			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
 			"stubsDir":          android.PathForModuleOut(ctx, "stubsDir").String(),
 			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
-			"opts":              opts,
+			"opts":              proptools.NinjaEscape(opts),
 			"bootclasspathArgs": bootclasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepathArgs":    sourcepathArgs,
@@ -1117,7 +1121,7 @@
 		Args: map[string]string{
 			"msg":                   msg,
 			"classpath":             checkApiClasspath.FormJavaClassPath(""),
-			"opts":                  opts,
+			"opts":                  proptools.NinjaEscape(opts),
 			"apiFile":               apiFile.String(),
 			"apiFileToCheck":        d.apiFile.String(),
 			"removedApiFile":        removedApiFile.String(),
@@ -1140,7 +1144,7 @@
 			"stubsDir":      android.PathForModuleOut(ctx, "dokka-stubsDir").String(),
 			"srcJars":       strings.Join(d.Javadoc.srcJars.Strings(), " "),
 			"classpathArgs": classpathArgs,
-			"opts":          opts,
+			"opts":          proptools.NinjaEscape(opts),
 			"docZip":        d.Javadoc.docZip.String(),
 		},
 	})
@@ -1258,6 +1262,9 @@
 	jdiffStubsSrcJar android.WritablePath
 }
 
+// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
+// documented, filtering out hidden classes and methods.  The resulting .java files are intended to be passed to
+// a droiddoc module to generate documentation.
 func DroidstubsFactory() android.Module {
 	module := &Droidstubs{}
 
@@ -1268,6 +1275,10 @@
 	return module
 }
 
+// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
+// to be documented, filtering out hidden classes and methods.  The resulting .java files are intended to be
+// passed to a droiddoc_host module to generate documentation.  Use a droidstubs_host instead of a droidstubs
+// module when symbols needed by the source files are provided by java_library_host modules.
 func DroidstubsHostFactory() android.Module {
 	module := &Droidstubs{}
 
@@ -1558,7 +1569,7 @@
 			"bootclasspathArgs": bootclasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepathArgs":    sourcepathArgs,
-			"opts":              opts,
+			"opts":              proptools.NinjaEscape(opts),
 		},
 	})
 }
@@ -1581,7 +1592,7 @@
 			"bootclasspathArgs": bootclasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepathArgs":    sourcepathArgs,
-			"opts":              opts,
+			"opts":              proptools.NinjaEscape(opts),
 			"msg":               msg,
 		},
 	})
@@ -1602,7 +1613,7 @@
 			"srcJarDir":         android.PathForModuleOut(ctx, "jdiff-srcjars").String(),
 			"stubsDir":          android.PathForModuleOut(ctx, "jdiff-stubsDir").String(),
 			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
-			"opts":              opts,
+			"opts":              proptools.NinjaEscape(opts),
 			"bootclasspathArgs": bootclasspathArgs,
 			"classpathArgs":     classpathArgs,
 			"sourcepathArgs":    sourcepathArgs,
@@ -1781,6 +1792,7 @@
 	dir  android.Path
 }
 
+// droiddoc_exported_dir exports a directory of html templates or nullability annotations for use by doclava.
 func ExportedDroiddocDirFactory() android.Module {
 	module := &ExportedDroiddocDir{}
 	module.AddProperties(&module.properties)
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index cf9f492..c83dda1 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -64,7 +64,7 @@
 	stubFlagsRule(ctx)
 
 	// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
-	if ctx.Config().FrameworksBaseDirExists(ctx) && !ctx.Config().UnbundledBuild() {
+	if ctx.Config().FrameworksBaseDirExists(ctx) {
 		h.flags = flagsRule(ctx)
 		h.metadata = metadataRule(ctx)
 	} else {
@@ -97,7 +97,7 @@
 	// Add the android.test.base to the set of stubs only if the android.test.base module is on
 	// the boot jars list as the runtime will only enforce hiddenapi access against modules on
 	// that list.
-	if inList("android.test.base", ctx.Config().BootJars()) {
+	if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().UnbundledBuildUsePrebuiltSdks() {
 		publicStubModules = append(publicStubModules, "android.test.base.stubs")
 	}
 
diff --git a/java/java.go b/java/java.go
index 7c84e76..a49aad7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1322,11 +1322,9 @@
 			return
 		}
 
-		if !ctx.Config().UnbundledBuild() {
-			// Hidden API CSV generation and dex encoding
-			dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
-				j.deviceProperties.UncompressDex)
-		}
+		// Hidden API CSV generation and dex encoding
+		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
+			j.deviceProperties.UncompressDex)
 
 		// merge dex jar with resources if necessary
 		if j.resourceJar != nil {
@@ -2042,7 +2040,7 @@
 // dex_import module
 
 type DexImportProperties struct {
-	Jars []string
+	Jars []string `android:"path"`
 }
 
 type DexImport struct {
@@ -2070,10 +2068,6 @@
 	return j.prebuilt.Name(j.ModuleBase.Name())
 }
 
-func (j *DexImport) DepsMutator(ctx android.BottomUpMutatorContext) {
-	android.ExtractSourcesDeps(ctx, j.properties.Jars)
-}
-
 func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	if len(j.properties.Jars) != 1 {
 		ctx.PropertyErrorf("jars", "exactly one jar must be provided")
@@ -2094,14 +2088,14 @@
 
 		// use zip2zip to uncompress classes*.dex files
 		rule.Command().
-			Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+			BuiltTool(ctx, "zip2zip").
 			FlagWithInput("-i ", inputJar).
 			FlagWithOutput("-o ", temporary).
 			FlagWithArg("-0 ", "'classes*.dex'")
 
 		// use zipalign to align uncompressed classes*.dex files
 		rule.Command().
-			Tool(ctx.Config().HostToolPath(ctx, "zipalign")).
+			BuiltTool(ctx, "zipalign").
 			Flag("-f").
 			Text("4").
 			Input(temporary).
diff --git a/java/proto.go b/java/proto.go
index 37de1d2..0ec6499 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -34,7 +34,7 @@
 	// Proto generated java files have an unknown package name in the path, so package the entire output directory
 	// into a srcjar.
 	rule.Command().
-		Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+		BuiltTool(ctx, "soong_zip").
 		Flag("-jar").
 		FlagWithOutput("-o ", srcJarFile).
 		FlagWithArg("-C ", outDir.String()).
diff --git a/java/sdk.go b/java/sdk.go
index 7b79a49..d1e2ae4 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -296,7 +296,7 @@
 			rule.Command().
 				Text("rm -f").Output(aidl)
 			rule.Command().
-				Tool(ctx.Config().HostToolPath(ctx, "sdkparcelables")).
+				BuiltTool(ctx, "sdkparcelables").
 				Input(jar).
 				Output(aidl)
 
diff --git a/java/sdk_library.go b/java/sdk_library.go
index b4a3f29..d38088d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -63,12 +63,6 @@
 	javaSdkLibrariesLock sync.Mutex
 )
 
-// java_sdk_library is to make a Java library that implements optional platform APIs to apps.
-// It is actually a wrapper of several modules: 1) stubs library that clients are linked against
-// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
-// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the
-// classpath at runtime if requested via <uses-library>.
-//
 // TODO: these are big features that are currently missing
 // 1) disallowing linking to the runtime shared lib
 // 2) HTML generation
@@ -155,16 +149,21 @@
 var _ SdkLibraryDependency = (*SdkLibrary)(nil)
 
 func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
 	// Add dependencies to the stubs library
-	ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
+	if useBuiltStubs {
+		ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
+	}
 	ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
 
 	sdkDep := decodeSdkDep(ctx, sdkContext(&module.Library))
 	if sdkDep.hasStandardLibs() {
-		ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
+		if useBuiltStubs {
+			ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
+			ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
+		}
 		ctx.AddVariationDependencies(nil, systemApiFileTag, module.docsName(apiScopeSystem))
 		ctx.AddVariationDependencies(nil, testApiFileTag, module.docsName(apiScopeTest))
-		ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
 	}
 
 	module.Library.deps(ctx)
@@ -746,6 +745,11 @@
 	module.Library.Module.deviceProperties.IsSDKLibrary = true
 }
 
+// java_sdk_library is a special Java library that provides optional platform APIs to apps.
+// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients
+// are linked against to, 2) droiddoc module that internally generates API stubs source files,
+// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding
+// the runtime lib to the classpath at runtime if requested via <uses-library>.
 func SdkLibraryFactory() android.Module {
 	module := &SdkLibrary{}
 	module.InitSdkLibraryProperties()
@@ -787,6 +791,7 @@
 
 var _ SdkLibraryDependency = (*sdkLibraryImport)(nil)
 
+// java_sdk_library_import imports a prebuilt java_sdk_library.
 func sdkLibraryImportFactory() android.Module {
 	module := &sdkLibraryImport{}
 
diff --git a/python/proto.go b/python/proto.go
index 85ed1a5..b71e047 100644
--- a/python/proto.go
+++ b/python/proto.go
@@ -34,7 +34,7 @@
 	// Proto generated python files have an unknown package name in the path, so package the entire output directory
 	// into a srcszip.
 	zipCmd := rule.Command().
-		Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+		BuiltTool(ctx, "soong_zip").
 		FlagWithOutput("-o ", srcsZipFile)
 	if pkgPath != "" {
 		zipCmd.FlagWithArg("-P ", pkgPath)
diff --git a/scripts/jar-wrapper.sh b/scripts/jar-wrapper.sh
index 71c1d90..b468041 100644
--- a/scripts/jar-wrapper.sh
+++ b/scripts/jar-wrapper.sh
@@ -48,11 +48,11 @@
     exit 1
 fi
 
-javaOpts=""
+declare -a javaOpts=()
 while expr "x$1" : 'x-J' >/dev/null; do
-    opt=`expr "$1" : '-J\(.*\)'`
-    javaOpts="${javaOpts} -${opt}"
+    opt=`expr "$1" : '-J-\{0,1\}\(.*\)'`
+    javaOpts+=("-${opt}")
     shift
 done
 
-exec java ${javaOpts} -jar ${jardir}/${jarfile} "$@"
+exec java "${javaOpts[@]}" -jar ${jardir}/${jarfile} "$@"