Merge "Put kotlin classes in header jar"
diff --git a/OWNERS b/OWNERS
index 121a441..edd2557 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,11 +1,3 @@
-ccross@android.com
-dwillemsen@google.com
-nanzhang@google.com
-
-per-file * = ccross@android.com
-per-file * = dwillemsen@google.com
-per-file * = nanzhang@google.com
-per-file *gen_stub_libs.py = danalbert@google.com
-per-file ndk_*.go = danalbert@google.com
-per-file clang.go = srhines@google.com
-per-file global.go = srhines@google.com
+per-file * = ccross@android.com,dwillemsen@google.com,nanzhang@google.com
+per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
+per-file clang.go,global.go,tidy.go = srhines@google.com, chh@google.com
diff --git a/android/androidmk.go b/android/androidmk.go
index 9f711bf..1d11161 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -242,7 +242,7 @@
 		if Bool(amod.commonProperties.Product_specific) {
 			fmt.Fprintln(&data.preamble, "LOCAL_PRODUCT_MODULE := true")
 		}
-		if Bool(amod.commonProperties.ProductServices_specific) {
+		if Bool(amod.commonProperties.Product_services_specific) {
 			fmt.Fprintln(&data.preamble, "LOCAL_PRODUCT_SERVICES_MODULE := true")
 		}
 		if amod.commonProperties.Owner != nil {
diff --git a/android/config.go b/android/config.go
index 0015c02..3a2a005 100644
--- a/android/config.go
+++ b/android/config.go
@@ -767,7 +767,7 @@
 	if c.config.productVariables.ProductServicesPath != nil {
 		return *c.config.productVariables.ProductServicesPath
 	}
-	return "product-services"
+	return "product_services"
 }
 
 func (c *deviceConfig) BtConfigIncludeDir() string {
diff --git a/android/module.go b/android/module.go
index ac7e606..a058199 100644
--- a/android/module.go
+++ b/android/module.go
@@ -243,9 +243,9 @@
 	Product_specific *bool
 
 	// whether this module provides services owned by the OS provider to the core platform. When set
-	// to true, it is installed into  /product-services (or /system/product-services if
-	// product-services partition does not exist).
-	ProductServices_specific *bool
+	// to true, it is installed into  /product_services (or /system/product_services if
+	// product_services partition does not exist).
+	Product_services_specific *bool
 
 	// Whether this module is installed to recovery partition
 	Recovery *bool
@@ -548,7 +548,7 @@
 }
 
 func (a *ModuleBase) ProductServicesSpecific() bool {
-	return Bool(a.commonProperties.ProductServices_specific)
+	return Bool(a.commonProperties.Product_services_specific)
 }
 
 func (a *ModuleBase) Enabled() bool {
@@ -661,7 +661,7 @@
 	var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
 	var deviceSpecific = Bool(a.commonProperties.Device_specific)
 	var productSpecific = Bool(a.commonProperties.Product_specific)
-	var productServicesSpecific = Bool(a.commonProperties.ProductServices_specific)
+	var productServicesSpecific = Bool(a.commonProperties.Product_services_specific)
 
 	msg := "conflicting value set here"
 	if socSpecific && deviceSpecific {
diff --git a/android/paths_test.go b/android/paths_test.go
index ff0eeb3..fbeccb1 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -293,7 +293,7 @@
 			out: "target/product/test_device/product/bin/my_test",
 		},
 		{
-			name: "product-services binary",
+			name: "product_services binary",
 			ctx: &moduleInstallPathContextImpl{
 				androidBaseContextImpl: androidBaseContextImpl{
 					target: deviceTarget,
@@ -301,7 +301,7 @@
 				},
 			},
 			in:  []string{"bin", "my_test"},
-			out: "target/product/test_device/product-services/bin/my_test",
+			out: "target/product/test_device/product_services/bin/my_test",
 		},
 
 		{
@@ -353,7 +353,7 @@
 		},
 
 		{
-			name: "product-services native test binary",
+			name: "product_services native test binary",
 			ctx: &moduleInstallPathContextImpl{
 				androidBaseContextImpl: androidBaseContextImpl{
 					target: deviceTarget,
@@ -414,7 +414,7 @@
 		},
 
 		{
-			name: "sanitized product-services binary",
+			name: "sanitized product_services binary",
 			ctx: &moduleInstallPathContextImpl{
 				androidBaseContextImpl: androidBaseContextImpl{
 					target: deviceTarget,
@@ -423,7 +423,7 @@
 				inSanitizerDir: true,
 			},
 			in:  []string{"bin", "my_test"},
-			out: "target/product/test_device/data/asan/product-services/bin/my_test",
+			out: "target/product/test_device/data/asan/product_services/bin/my_test",
 		},
 
 		{
@@ -478,7 +478,7 @@
 			out: "target/product/test_device/data/asan/data/nativetest/my_test",
 		},
 		{
-			name: "sanitized product-services native test binary",
+			name: "sanitized product_services native test binary",
 			ctx: &moduleInstallPathContextImpl{
 				androidBaseContextImpl: androidBaseContextImpl{
 					target: deviceTarget,
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index 55a72a6..046512f 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -24,6 +24,10 @@
 
 func init() {
 	RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
+
+	PreDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
+	})
 }
 
 type prebuiltEtcProperties struct {
@@ -32,6 +36,11 @@
 
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
+
+	// Make this module available when building for recovery.
+	Recovery_available *bool
+
+	InRecovery bool `blueprint:"mutated"`
 }
 
 type PrebuiltEtc struct {
@@ -44,6 +53,18 @@
 	additionalDependencies *Paths
 }
 
+func (p *PrebuiltEtc) inRecovery() bool {
+	return p.properties.InRecovery || p.ModuleBase.InstallInRecovery()
+}
+
+func (p *PrebuiltEtc) onlyInRecovery() bool {
+	return p.ModuleBase.InstallInRecovery()
+}
+
+func (p *PrebuiltEtc) InstallInRecovery() bool {
+	return p.inRecovery()
+}
+
 func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
 	if p.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
@@ -71,13 +92,18 @@
 func (p *PrebuiltEtc) AndroidMk() AndroidMkData {
 	return AndroidMkData{
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
+			nameSuffix := ""
+			if p.inRecovery() && !p.onlyInRecovery() {
+				nameSuffix = ".recovery"
+			}
 			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
 			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
-			fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+			fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
 			fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
 			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
 			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.sourceFilePath.String())
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
+			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
@@ -101,3 +127,46 @@
 	InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
 	return module
 }
+
+const (
+	// coreMode is the variant for modules to be installed to system.
+	coreMode = "core"
+
+	// recoveryMode means a module to be installed to recovery image.
+	recoveryMode = "recovery"
+)
+
+// prebuiltEtcMutator creates the needed variants to install the module to
+// system or recovery.
+func prebuiltEtcMutator(mctx BottomUpMutatorContext) {
+	m, ok := mctx.Module().(*PrebuiltEtc)
+	if !ok {
+		return
+	}
+
+	var coreVariantNeeded bool = true
+	var recoveryVariantNeeded bool = false
+	if Bool(m.properties.Recovery_available) {
+		recoveryVariantNeeded = true
+	}
+
+	if m.ModuleBase.InstallInRecovery() {
+		recoveryVariantNeeded = true
+		coreVariantNeeded = false
+	}
+
+	var variants []string
+	if coreVariantNeeded {
+		variants = append(variants, coreMode)
+	}
+	if recoveryVariantNeeded {
+		variants = append(variants, recoveryMode)
+	}
+	mod := mctx.CreateVariations(variants...)
+	for i, v := range variants {
+		if v == recoveryMode {
+			m := mod[i].(*PrebuiltEtc)
+			m.properties.InRecovery = true
+		}
+	}
+}
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
new file mode 100644
index 0000000..9244647
--- /dev/null
+++ b/android/prebuilt_etc_test.go
@@ -0,0 +1,93 @@
+// Copyright 2018 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/ioutil"
+	"os"
+	"testing"
+)
+
+func testPrebuiltEtc(t *testing.T, bp string) *TestContext {
+	config, buildDir := setUp(t)
+	defer tearDown(buildDir)
+	ctx := NewTestArchContext()
+	ctx.RegisterModuleType("prebuilt_etc", ModuleFactoryAdaptor(PrebuiltEtcFactory))
+	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
+	})
+	ctx.Register()
+	mockFiles := map[string][]byte{
+		"Android.bp": []byte(bp),
+		"foo.conf":   nil,
+		"bar.conf":   nil,
+		"baz.conf":   nil,
+	}
+	ctx.MockFileSystem(mockFiles)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	return ctx
+}
+
+func setUp(t *testing.T) (config Config, buildDir string) {
+	buildDir, err := ioutil.TempDir("", "soong_prebuilt_etc_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	config = TestArchConfig(buildDir, nil)
+	return
+}
+
+func tearDown(buildDir string) {
+	os.RemoveAll(buildDir)
+}
+
+func TestPrebuiltEtcVariants(t *testing.T) {
+	ctx := testPrebuiltEtc(t, `
+		prebuilt_etc {
+			name: "foo.conf",
+			src: "foo.conf",
+		}
+		prebuilt_etc {
+			name: "bar.conf",
+			src: "bar.conf",
+			recovery_available: true,
+		}
+		prebuilt_etc {
+			name: "baz.conf",
+			src: "baz.conf",
+			recovery: true,
+		}
+	`)
+
+	foo_variants := ctx.ModuleVariantsForTests("foo.conf")
+	if len(foo_variants) != 1 {
+		t.Errorf("expected 1, got %#v", foo_variants)
+	}
+
+	bar_variants := ctx.ModuleVariantsForTests("bar.conf")
+	if len(bar_variants) != 2 {
+		t.Errorf("expected 2, got %#v", bar_variants)
+	}
+
+	baz_variants := ctx.ModuleVariantsForTests("baz.conf")
+	if len(baz_variants) != 1 {
+		t.Errorf("expected 1, got %#v", bar_variants)
+	}
+}
diff --git a/cc/builder.go b/cc/builder.go
index 51d3195..7d207b0 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -150,10 +150,12 @@
 		},
 		"crossCompile")
 
+	_ = pctx.SourcePathVariable("tidyPath", "build/soong/scripts/clang-tidy.sh")
+
 	clangTidy = pctx.AndroidStaticRule("clangTidy",
 		blueprint.RuleParams{
-			Command:     "rm -f $out && ${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
-			CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
+			Command:     "rm -f $out && CLANG_TIDY=${config.ClangBin}/clang-tidy $tidyPath $tidyFlags $in -- $cFlags && touch $out",
+			CommandDeps: []string{"${config.ClangBin}/clang-tidy", "$tidyPath"},
 		},
 		"cFlags", "tidyFlags")
 
@@ -234,29 +236,30 @@
 }
 
 type builderFlags struct {
-	globalFlags    string
-	arFlags        string
-	asFlags        string
-	cFlags         string
-	toolingCFlags  string // A separate set of Cflags for clang LibTooling tools
-	conlyFlags     string
-	cppFlags       string
-	ldFlags        string
-	libFlags       string
-	yaccFlags      string
-	protoFlags     string
-	protoOutParams string
-	tidyFlags      string
-	sAbiFlags      string
-	yasmFlags      string
-	aidlFlags      string
-	rsFlags        string
-	toolchain      config.Toolchain
-	clang          bool
-	tidy           bool
-	coverage       bool
-	sAbiDump       bool
-	protoRoot      bool
+	globalFlags     string
+	arFlags         string
+	asFlags         string
+	cFlags          string
+	toolingCFlags   string // A separate set of cFlags for clang LibTooling tools
+	toolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
+	conlyFlags      string
+	cppFlags        string
+	ldFlags         string
+	libFlags        string
+	yaccFlags       string
+	protoFlags      string
+	protoOutParams  string
+	tidyFlags       string
+	sAbiFlags       string
+	yasmFlags       string
+	aidlFlags       string
+	rsFlags         string
+	toolchain       config.Toolchain
+	clang           bool
+	tidy            bool
+	coverage        bool
+	sAbiDump        bool
+	protoRoot       bool
 
 	systemIncludeFlags string
 
@@ -328,7 +331,7 @@
 	toolingCppflags := strings.Join([]string{
 		commonFlags,
 		flags.toolingCFlags,
-		flags.cppFlags,
+		flags.toolingCppFlags,
 	}, " ")
 
 	cppflags := strings.Join([]string{
diff --git a/cc/cc.go b/cc/cc.go
index bde8041..7f65640 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -46,6 +46,9 @@
 		ctx.TopDown("asan_deps", sanitizerDepsMutator(asan))
 		ctx.BottomUp("asan", sanitizerMutator(asan)).Parallel()
 
+		ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
+		ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
+
 		ctx.TopDown("cfi_deps", sanitizerDepsMutator(cfi))
 		ctx.BottomUp("cfi", sanitizerMutator(cfi)).Parallel()
 
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 36afc68..186d790 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -93,8 +93,10 @@
 })
 
 var ClangLibToolingUnknownCflags = []string{
+	// Remove -flto and other flto dependent flags.
 	"-flto*",
 	"-fsanitize*",
+	"-fwhole-program-vtables",
 }
 
 func init() {
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index 3d1a0a0..67f92a2 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -19,18 +19,6 @@
 	"strings"
 )
 
-// clang-tidy doesn't recognize every flag that clang does. This is unlikely to
-// be a complete list, but we can populate this with the ones we know to avoid
-// issues with clang-diagnostic-unused-command-line-argument.
-// b/111885396: -flto affected header include directory;
-// -fsanitize and -fwhole-program-vtables need -flto.
-var ClangTidyUnknownCflags = sorted([]string{
-	"-Wa,%",
-	"-flto",
-	"-fsanitize=%",
-	"-fwhole-program-vtables",
-})
-
 func init() {
 	// Most Android source files are not clang-tidy clean yet.
 	// Global tidy checks include only google*, performance*,
@@ -42,6 +30,7 @@
 		}
 		return strings.Join([]string{
 			"-*",
+			"clang-diagnostic-unused-command-line-argument",
 			"google*",
 			"misc-macro-parentheses",
 			"performance*",
@@ -58,6 +47,7 @@
 		}
 		return strings.Join([]string{
 			"-*",
+			"clang-diagnostic-unused-command-line-argument",
 			"google*",
 			"-google-build-using-namespace",
 			"-google-default-arguments",
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index a360a17..39b5df4 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -226,6 +226,14 @@
 	return SanitizerRuntimeLibrary(t, "asan")
 }
 
+func HWAddressSanitizerRuntimeLibrary(t Toolchain) string {
+	return SanitizerRuntimeLibrary(t, "hwasan")
+}
+
+func HWAddressSanitizerStaticLibrary(t Toolchain) string {
+	return SanitizerRuntimeLibrary(t, "hwasan_static")
+}
+
 func UndefinedBehaviorSanitizerRuntimeLibrary(t Toolchain) string {
 	return SanitizerRuntimeLibrary(t, "ubsan_standalone")
 }
diff --git a/cc/makevars.go b/cc/makevars.go
index 88d4639..c3ff4ce 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -75,7 +75,6 @@
 	ctx.Strict("LLVM_OBJCOPY", "${config.ClangBin}/llvm-objcopy")
 	ctx.Strict("LLVM_STRIP", "${config.ClangBin}/llvm-strip")
 	ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy")
-	ctx.Strict("CLANG_TIDY_UNKNOWN_CFLAGS", strings.Join(config.ClangTidyUnknownCflags, " "))
 	ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " "))
 
 	ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}")
@@ -300,6 +299,8 @@
 
 		if target.Os.Class == android.Device {
 			ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so"))
+			ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerRuntimeLibrary(toolchain), ".so"))
+			ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_STATIC_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerStaticLibrary(toolchain), ".a"))
 			ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so"))
 			ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
 			ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 144fc09..80b5c6a 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -132,6 +132,10 @@
 		}
 	})
 
+	// Include only a single copy of each license file. The Bionic NOTICE is
+	// long and is referenced by multiple Bionic modules.
+	licensePaths = android.FirstUniquePaths(licensePaths)
+
 	combinedLicense := getNdkInstallBase(ctx).Join(ctx, "NOTICE")
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        android.Cat,
diff --git a/cc/sabi.go b/cc/sabi.go
index 42b2f35..72a3c5c 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -71,6 +71,7 @@
 	// Assuming that the cflags which clang LibTooling tools cannot
 	// understand have not been converted to ninja variables yet.
 	flags.ToolingCFlags = filterOutWithPrefix(flags.CFlags, config.ClangLibToolingUnknownCflags)
+	flags.ToolingCppFlags = filterOutWithPrefix(flags.CppFlags, config.ClangLibToolingUnknownCflags)
 
 	// RSClang does not support recent mcpu option likes exynos-m2.
 	// So we need overriding mcpu option when we want to use it.
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 1037181..a522a60 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -36,12 +36,15 @@
 	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
 	asanLibs    = []string{"libasan"}
 
+	hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than="}
+
 	cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
 		"-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
 	cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
 		"-Wl,-plugin-opt,O1"}
-	cfiExportsMapPath  = "build/soong/cc/config/cfi_exports.map"
-	cfiStaticLibsMutex sync.Mutex
+	cfiExportsMapPath     = "build/soong/cc/config/cfi_exports.map"
+	cfiStaticLibsMutex    sync.Mutex
+	hwasanStaticLibsMutex sync.Mutex
 
 	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
 	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"}
@@ -59,6 +62,7 @@
 
 const (
 	asan sanitizerType = iota + 1
+	hwasan
 	tsan
 	intOverflow
 	cfi
@@ -68,6 +72,8 @@
 	switch t {
 	case asan:
 		return "asan"
+	case hwasan:
+		return "hwasan"
 	case tsan:
 		return "tsan"
 	case intOverflow:
@@ -85,8 +91,9 @@
 		Never *bool `android:"arch_variant"`
 
 		// main sanitizers
-		Address *bool `android:"arch_variant"`
-		Thread  *bool `android:"arch_variant"`
+		Address   *bool `android:"arch_variant"`
+		Thread    *bool `android:"arch_variant"`
+		Hwaddress *bool `android:"arch_variant"`
 
 		// local sanitizers
 		Undefined        *bool    `android:"arch_variant"`
@@ -131,6 +138,7 @@
 
 func init() {
 	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
+	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
 }
 
 func (sanitize *sanitize) props() []interface{} {
@@ -216,6 +224,10 @@
 			s.Scudo = boolPtr(true)
 		}
 
+		if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
+			s.Hwaddress = boolPtr(true)
+		}
+
 		if len(globalSanitizers) > 0 {
 			ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
 		}
@@ -256,8 +268,13 @@
 		s.Diag.Cfi = nil
 	}
 
+	// HWASan requires AArch64 hardware feature (top-byte-ignore).
+	if ctx.Arch().ArchType != android.Arm64 {
+		s.Hwaddress = nil
+	}
+
 	// Also disable CFI if ASAN is enabled.
-	if Bool(s.Address) {
+	if Bool(s.Address) || Bool(s.Hwaddress) {
 		s.Cfi = nil
 		s.Diag.Cfi = nil
 	}
@@ -278,6 +295,11 @@
 		s.Diag.Cfi = nil
 	}
 
+	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
+	if ctx.inRecovery() {
+		s.Hwaddress = nil
+	}
+
 	if ctx.staticBinary() {
 		s.Address = nil
 		s.Coverage = nil
@@ -297,15 +319,20 @@
 
 	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
 		Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
-		Bool(s.Scudo)) {
+		Bool(s.Scudo) || Bool(s.Hwaddress)) {
 		sanitize.Properties.SanitizerEnabled = true
 	}
 
 	// Disable Scudo if ASan or TSan is enabled.
-	if Bool(s.Address) || Bool(s.Thread) {
+	if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) {
 		s.Scudo = nil
 	}
 
+	if Bool(s.Hwaddress) {
+		s.Address = nil
+		s.Thread = nil
+	}
+
 	if Bool(s.Coverage) {
 		if !Bool(s.Address) {
 			ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
@@ -407,6 +434,11 @@
 		diagSanitizers = append(diagSanitizers, "address")
 	}
 
+	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+		flags.CFlags = append(flags.CFlags, hwasanCflags...)
+		sanitizers = append(sanitizers, "hwaddress")
+	}
+
 	if Bool(sanitize.Properties.Sanitize.Thread) {
 		sanitizers = append(sanitizers, "thread")
 	}
@@ -494,6 +526,8 @@
 	runtimeLibrary := ""
 	if Bool(sanitize.Properties.Sanitize.Address) {
 		runtimeLibrary = config.AddressSanitizerRuntimeLibrary(ctx.toolchain())
+	} else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+		runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(ctx.toolchain())
 	} else if Bool(sanitize.Properties.Sanitize.Thread) {
 		runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
 	} else if Bool(sanitize.Properties.Sanitize.Scudo) {
@@ -542,6 +576,9 @@
 	if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Cfi) {
 		ret.SubName += ".cfi"
 	}
+	if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Hwaddress) {
+		ret.SubName += ".hwasan"
+	}
 }
 
 func (sanitize *sanitize) inSanitizerDir() bool {
@@ -552,6 +589,8 @@
 	switch t {
 	case asan:
 		return sanitize.Properties.Sanitize.Address
+	case hwasan:
+		return sanitize.Properties.Sanitize.Hwaddress
 	case tsan:
 		return sanitize.Properties.Sanitize.Thread
 	case intOverflow:
@@ -565,12 +604,14 @@
 
 func (sanitize *sanitize) isUnsanitizedVariant() bool {
 	return !sanitize.isSanitizerEnabled(asan) &&
+		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan) &&
 		!sanitize.isSanitizerEnabled(cfi)
 }
 
 func (sanitize *sanitize) isVariantOnProductionDevice() bool {
 	return !sanitize.isSanitizerEnabled(asan) &&
+		!sanitize.isSanitizerEnabled(hwasan) &&
 		!sanitize.isSanitizerEnabled(tsan)
 }
 
@@ -581,6 +622,8 @@
 		if !b {
 			sanitize.Properties.Sanitize.Coverage = nil
 		}
+	case hwasan:
+		sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
 	case tsan:
 		sanitize.Properties.Sanitize.Thread = boolPtr(b)
 	case intOverflow:
@@ -625,7 +668,7 @@
 	return ok && t.library || t == reuseObjTag
 }
 
-// Propagate asan requirements down from binaries
+// Propagate sanitizer requirements down from binaries
 func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
 	return func(mctx android.TopDownMutatorContext) {
 		if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
@@ -636,7 +679,11 @@
 				if d, ok := child.(*Module); ok && d.sanitize != nil &&
 					!Bool(d.sanitize.Properties.Sanitize.Never) &&
 					!d.sanitize.isSanitizerExplicitlyDisabled(t) {
-					if (t == cfi && d.static()) || t != cfi {
+					if t == cfi || t == hwasan {
+						if d.static() {
+							d.sanitize.Properties.SanitizeDep = true
+						}
+					} else {
 						d.sanitize.Properties.SanitizeDep = true
 					}
 				}
@@ -728,6 +775,34 @@
 						modules[1].(*Module).Properties.PreventInstall = true
 						modules[1].(*Module).Properties.HideFromMake = true
 					}
+				} else if t == hwasan {
+					if mctx.Device() {
+						// CFI and HWASAN are currently mutually exclusive so disable
+						// CFI if this is an HWASAN variant.
+						modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+					}
+
+					if c.static() {
+						if c.useVndk() {
+							hwasanVendorStaticLibs := hwasanVendorStaticLibs(mctx.Config())
+							hwasanStaticLibsMutex.Lock()
+							*hwasanVendorStaticLibs = append(*hwasanVendorStaticLibs, c.Name())
+							hwasanStaticLibsMutex.Unlock()
+						} else {
+							hwasanStaticLibs := hwasanStaticLibs(mctx.Config())
+							hwasanStaticLibsMutex.Lock()
+							*hwasanStaticLibs = append(*hwasanStaticLibs, c.Name())
+							hwasanStaticLibsMutex.Unlock()
+						}
+					} else {
+						if isSanitizerEnabled {
+							modules[0].(*Module).Properties.PreventInstall = true
+							modules[0].(*Module).Properties.HideFromMake = true
+						} else {
+							modules[1].(*Module).Properties.PreventInstall = true
+							modules[1].(*Module).Properties.HideFromMake = true
+						}
+					}
 				}
 			}
 			c.sanitize.Properties.SanitizeDep = false
@@ -741,8 +816,21 @@
 	}).(*[]string)
 }
 
+func hwasanStaticLibs(config android.Config) *[]string {
+	return config.Once("hwasanStaticLibs", func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
+func hwasanVendorStaticLibs(config android.Config) *[]string {
+	return config.Once("hwasanVendorStaticLibs", func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
 func enableMinimalRuntime(sanitize *sanitize) bool {
 	if !Bool(sanitize.Properties.Sanitize.Address) &&
+		!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
 		!Bool(sanitize.Properties.Sanitize.Scudo) &&
 		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
 			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
@@ -759,3 +847,13 @@
 	sort.Strings(*cfiStaticLibs)
 	ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " "))
 }
+
+func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
+	hwasanStaticLibs := hwasanStaticLibs(ctx.Config())
+	sort.Strings(*hwasanStaticLibs)
+	ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " "))
+
+	hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config())
+	sort.Strings(*hwasanVendorStaticLibs)
+	ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " "))
+}
diff --git a/cc/util.go b/cc/util.go
index 8de4210..93cf536 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -59,29 +59,30 @@
 
 func flagsToBuilderFlags(in Flags) builderFlags {
 	return builderFlags{
-		globalFlags:    strings.Join(in.GlobalFlags, " "),
-		arFlags:        strings.Join(in.ArFlags, " "),
-		asFlags:        strings.Join(in.AsFlags, " "),
-		cFlags:         strings.Join(in.CFlags, " "),
-		toolingCFlags:  strings.Join(in.ToolingCFlags, " "),
-		conlyFlags:     strings.Join(in.ConlyFlags, " "),
-		cppFlags:       strings.Join(in.CppFlags, " "),
-		yaccFlags:      strings.Join(in.YaccFlags, " "),
-		protoFlags:     strings.Join(in.protoFlags, " "),
-		protoOutParams: strings.Join(in.protoOutParams, ","),
-		aidlFlags:      strings.Join(in.aidlFlags, " "),
-		rsFlags:        strings.Join(in.rsFlags, " "),
-		ldFlags:        strings.Join(in.LdFlags, " "),
-		libFlags:       strings.Join(in.libFlags, " "),
-		tidyFlags:      strings.Join(in.TidyFlags, " "),
-		sAbiFlags:      strings.Join(in.SAbiFlags, " "),
-		yasmFlags:      strings.Join(in.YasmFlags, " "),
-		toolchain:      in.Toolchain,
-		clang:          in.Clang,
-		coverage:       in.Coverage,
-		tidy:           in.Tidy,
-		sAbiDump:       in.SAbiDump,
-		protoRoot:      in.ProtoRoot,
+		globalFlags:     strings.Join(in.GlobalFlags, " "),
+		arFlags:         strings.Join(in.ArFlags, " "),
+		asFlags:         strings.Join(in.AsFlags, " "),
+		cFlags:          strings.Join(in.CFlags, " "),
+		toolingCFlags:   strings.Join(in.ToolingCFlags, " "),
+		toolingCppFlags: strings.Join(in.ToolingCppFlags, " "),
+		conlyFlags:      strings.Join(in.ConlyFlags, " "),
+		cppFlags:        strings.Join(in.CppFlags, " "),
+		yaccFlags:       strings.Join(in.YaccFlags, " "),
+		protoFlags:      strings.Join(in.protoFlags, " "),
+		protoOutParams:  strings.Join(in.protoOutParams, ","),
+		aidlFlags:       strings.Join(in.aidlFlags, " "),
+		rsFlags:         strings.Join(in.rsFlags, " "),
+		ldFlags:         strings.Join(in.LdFlags, " "),
+		libFlags:        strings.Join(in.libFlags, " "),
+		tidyFlags:       strings.Join(in.TidyFlags, " "),
+		sAbiFlags:       strings.Join(in.SAbiFlags, " "),
+		yasmFlags:       strings.Join(in.YasmFlags, " "),
+		toolchain:       in.Toolchain,
+		clang:           in.Clang,
+		coverage:        in.Coverage,
+		tidy:            in.Tidy,
+		sAbiDump:        in.SAbiDump,
+		protoRoot:       in.ProtoRoot,
 
 		systemIncludeFlags: strings.Join(in.SystemIncludeFlags, " "),
 
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index 9ce6b50..a39642f 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -104,6 +104,24 @@
 
 var excludes = make(Exclude)
 
+type HostModuleNames map[string]bool
+
+func (n HostModuleNames) IsHostModule(groupId string, artifactId string) bool {
+	_, found := n[groupId + ":" + artifactId]
+	return found
+}
+
+func (n HostModuleNames) String() string {
+	return ""
+}
+
+func (n HostModuleNames) Set(v string) error {
+	n[v] = true
+	return nil
+}
+
+var hostModuleNames = HostModuleNames{}
+
 var sdkVersion string
 var useVersion string
 
@@ -160,6 +178,14 @@
 	return p.Packaging == "jar"
 }
 
+func (p Pom) IsHostModule() bool {
+	return hostModuleNames.IsHostModule(p.GroupId, p.ArtifactId)
+}
+
+func (p Pom) IsDeviceModule() bool {
+	return !p.IsHostModule()
+}
+
 func (p Pom) BpName() string {
 	if p.BpTarget == "" {
 		p.BpTarget = rewriteNames.MavenToBp(p.GroupId, p.ArtifactId)
@@ -278,11 +304,11 @@
     ],{{end}}
 }
 
-{{if .IsAar}}android_library{{else}}java_library_static{{end}} {
-    name: "{{.BpName}}",
+{{if .IsAar}}android_library{{else}}{{if .IsDeviceModule}}java_library_static{{else}}java_library_host{{end}}{{end}} {
+    name: "{{.BpName}}",{{if .IsDeviceModule}}
     sdk_version: "{{.SdkVersion}}",{{if .IsAar}}
     min_sdk_version: "{{.MinSdkVersion}}",
-    manifest: "manifests/{{.BpName}}/AndroidManifest.xml",{{end}}
+    manifest: "manifests/{{.BpName}}/AndroidManifest.xml",{{end}}{{end}}
     static_libs: [
         "{{.BpName}}-nodeps",{{range .BpJarDeps}}
         "{{.}}",{{end}}{{range .BpAarDeps}}
@@ -422,6 +448,7 @@
 	flag.Var(&excludes, "exclude", "Exclude module")
 	flag.Var(&extraDeps, "extra-deps", "Extra dependencies needed when depending on a module")
 	flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
+	flag.Var(&hostModuleNames, "host", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is a host module")
 	flag.StringVar(&sdkVersion, "sdk-version", "", "What to write to LOCAL_SDK_VERSION")
 	flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
 	flag.Bool("static-deps", false, "Ignored")
diff --git a/java/androidmk.go b/java/androidmk.go
index aebbcc8..877d840 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -379,6 +379,9 @@
 				if ddoc.exactApiFile != nil {
 					fmt.Fprintln(w, apiFilePrefix+"EXACT_API_FILE := ", ddoc.exactApiFile.String())
 				}
+				if ddoc.proguardFile != nil {
+					fmt.Fprintln(w, apiFilePrefix+"PROGUARD_FILE := ", ddoc.proguardFile.String())
+				}
 			},
 		},
 	}
diff --git a/java/dex.go b/java/dex.go
index 77a3644..054a176 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -39,10 +39,12 @@
 var r8 = pctx.AndroidStaticRule("r8",
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+			`rm -f "$outDict" && ` +
 			`${config.R8Cmd} -injars $in --output $outDir ` +
 			`--force-proguard-compatibility ` +
 			`-printmapping $outDict ` +
 			`$dxFlags $r8Flags && ` +
+			`touch "$outDict" && ` +
 			`${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
 			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
 		CommandDeps: []string{
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 104e46d..52db705 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -88,6 +88,24 @@
 		},
 		"outDir", "srcJarDir", "stubsDir", "docStubsDir", "srcJars", "javaVersion", "bootclasspathArgs",
 		"classpathArgs", "sourcepath", "opts", "docZip")
+
+	metalavaApiCheck = pctx.AndroidStaticRule("metalavaApiCheck",
+		blueprint.RuleParams{
+			Command: `( rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` +
+				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+				`${config.JavaCmd} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` +
+				`$bootclasspathArgs $classpathArgs -sourcepath $sourcepath --no-banner --color --quiet ` +
+				`$opts && touch $out ) || ` +
+				`( echo -e "$msg" ; exit 38 )`,
+			CommandDeps: []string{
+				"${config.ZipSyncCmd}",
+				"${config.JavaCmd}",
+				"${config.MetalavaJar}",
+			},
+			Rspfile:        "$out.rsp",
+			RspfileContent: "$in",
+		},
+		"srcJarDir", "srcJars", "javaVersion", "bootclasspathArgs", "classpathArgs", "sourcepath", "opts", "msg")
 )
 
 func init() {
@@ -244,6 +262,9 @@
 	// the generated exact API filename by Doclava.
 	Exact_api_filename *string
 
+	// the generated proguard filename by Doclava.
+	Proguard_filename *string
+
 	// if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
 	Create_stubs *bool
 
@@ -606,6 +627,7 @@
 	removedDexApiFile android.WritablePath
 	exactApiFile      android.WritablePath
 	apiMappingFile    android.WritablePath
+	proguardFile      android.WritablePath
 
 	checkCurrentApiTimestamp      android.WritablePath
 	updateCurrentApiTimestamp     android.WritablePath
@@ -712,7 +734,8 @@
 	}
 }
 
-func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, deps deps) (droiddocBuilderFlags, error) {
+func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths,
+	deps deps) (droiddocBuilderFlags, error) {
 	var flags droiddocBuilderFlags
 
 	*implicits = append(*implicits, deps.bootClasspath...)
@@ -767,7 +790,7 @@
 }
 
 func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths,
-	javaVersion string, jsilver, doclava android.Path) string {
+	jsilver, doclava android.Path) string {
 
 	*implicits = append(*implicits, jsilver)
 	*implicits = append(*implicits, doclava)
@@ -779,7 +802,10 @@
 		date = `date -d`
 	}
 
-	args := " -source " + javaVersion + " -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
+	// Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources.  For modules with 1.9
+	// sources, droiddoc will get sources produced by metalava which will have already stripped out the
+	// 1.9 language features.
+	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")" `
@@ -909,6 +935,13 @@
 		*implicitOutputs = append(*implicitOutputs, d.apiMappingFile)
 	}
 
+	if String(d.properties.Proguard_filename) != "" {
+		d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename))
+		doclavaFlags += " -proguard " + d.proguardFile.String()
+		// Omitted: metalava support
+		*implicitOutputs = append(*implicitOutputs, d.proguardFile)
+	}
+
 	if BoolDefault(d.properties.Create_stubs, true) {
 		doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String()
 	}
@@ -1052,7 +1085,7 @@
 	checkApiClasspath classpath, msg, opts string, output android.WritablePath) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        apiCheck,
-		Description: "Check API",
+		Description: "Doclava Check API",
 		Output:      output,
 		Inputs:      nil,
 		Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
@@ -1069,6 +1102,29 @@
 	})
 }
 
+func (d *Droiddoc) transformMetalavaCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
+	implicits android.Paths, javaVersion, bootclasspathArgs, classpathArgs, opts, msg string,
+	output android.WritablePath) {
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        metalavaApiCheck,
+		Description: "Metalava Check API",
+		Output:      output,
+		Inputs:      d.Javadoc.srcFiles,
+		Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
+			implicits...),
+		Args: map[string]string{
+			"srcJarDir":         android.PathForModuleOut(ctx, "srcjars").String(),
+			"srcJars":           strings.Join(d.Javadoc.srcJars.Strings(), " "),
+			"javaVersion":       javaVersion,
+			"bootclasspathArgs": bootclasspathArgs,
+			"classpathArgs":     classpathArgs,
+			"sourcepath":        strings.Join(d.Javadoc.sourcepaths.Strings(), ":"),
+			"opts":              opts,
+			"msg":               msg,
+		},
+	})
+}
+
 func (d *Droiddoc) transformUpdateApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path,
 	output android.WritablePath) {
 	ctx.Build(pctx, android.BuildParams{
@@ -1089,13 +1145,6 @@
 	deps := d.Javadoc.collectDeps(ctx)
 
 	javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
-	// Doclava has problem with "-source 1.9", so override javaVersion when Doclava
-	// is running with EXPERIMENTAL_USE_OPENJDK9=true. And eventually Doclava will be
-	// replaced by Metalava.
-	if !Bool(d.properties.Metalava_enabled) {
-		javaVersion = "1.8"
-	}
-
 	jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
 	doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
 	java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
@@ -1111,6 +1160,7 @@
 	}
 
 	flags, err := d.initBuilderFlags(ctx, &implicits, deps)
+	metalavaCheckApiImplicits := implicits
 	if err != nil {
 		return
 	}
@@ -1127,25 +1177,27 @@
 					flags.dokkaClasspathArgs, outDir, docStubsDir)
 				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
-						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaAnnotationsFlags+" "+
+						strings.Split(flags.args, "--generate-documentation")[0]+
 						flags.metalavaDokkaFlags+" "+strings.Split(flags.args, "--generate-documentation")[1])
 			} else {
 				flags.metalavaJavadocFlags = d.collectMetalavaJavadocFlags(
 					ctx, flags.bootClasspathArgs, flags.classpathArgs, outDir, docStubsDir)
-				flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
+				flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
 				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
-						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaAnnotationsFlags+" "+
+						strings.Split(flags.args, "--generate-documentation")[0]+
 						flags.metalavaJavadocFlags+flags.doclavaDocsFlags+
 						" "+strings.Split(flags.args, "--generate-documentation")[1])
 			}
 		} else {
 			d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 				flags.bootClasspathArgs, flags.classpathArgs,
-				flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.args)
+				flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+" "+flags.args)
 		}
 	} else {
-		flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, javaVersion, jsilver, doclava)
+		flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
 		flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits)
 		d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs,
 			flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+flags.args,
@@ -1158,8 +1210,8 @@
 		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
 			"check_api.current_removed_api_file")
 
+		d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
 		if !Bool(d.properties.Metalava_enabled) {
-			d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp")
 			d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
 				fmt.Sprintf(`\n******************************\n`+
 					`You have tried to change the API from what has been previously approved.\n\n`+
@@ -1173,10 +1225,22 @@
 					`******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args),
 				d.checkCurrentApiTimestamp)
 		} else {
-			// TODO(nanzhang): Refactor below when Metalava support API check.
-			if d.apiFile == nil || d.removedApiFile == nil {
-				ctx.ModuleErrorf("api_filename and removed_api_filename properties cannot be empty for API check!")
-			}
+			opts := flags.args + " --check-compatibility:api:current " + apiFile.String() +
+				" --check-compatibility:removed:current " + removedApiFile.String() + " "
+
+			d.transformMetalavaCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits,
+				javaVersion, flags.bootClasspathArgs, flags.classpathArgs, opts,
+				fmt.Sprintf(`\n******************************\n`+
+					`You have tried to change the API from what has been previously approved.\n\n`+
+					`To make these errors go away, you have two choices:\n`+
+					`   1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+
+					`      errors above.\n\n`+
+					`   2. You can update current.txt by executing the following command:\n`+
+					`         make %s-update-current-api\n\n`+
+					`      To submit the revised current.txt to the main Android repository,\n`+
+					`      you will need approval.\n`+
+					`******************************\n`, ctx.ModuleName()),
+				d.checkCurrentApiTimestamp)
 		}
 
 		d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
@@ -1184,19 +1248,31 @@
 	}
 
 	if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
-		d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
-
 		apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
 			"check_api.last_released.api_file")
 		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
 			"check_api.last_released.removed_api_file")
 
-		d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
-			`\n******************************\n`+
-				`You have tried to change the API from what has been previously released in\n`+
-				`an SDK.  Please fix the errors listed above.\n`+
-				`******************************\n`, String(d.properties.Check_api.Last_released.Args),
-			d.checkLastReleasedApiTimestamp)
+		d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
+		if !Bool(d.properties.Metalava_enabled) {
+			d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
+				`\n******************************\n`+
+					`You have tried to change the API from what has been previously released in\n`+
+					`an SDK.  Please fix the errors listed above.\n`+
+					`******************************\n`, String(d.properties.Check_api.Last_released.Args),
+				d.checkLastReleasedApiTimestamp)
+		} else {
+			opts := flags.args + " --check-compatibility:api:released " + apiFile.String() +
+				" --check-compatibility:removed:released " + removedApiFile.String() + " "
+
+			d.transformMetalavaCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits,
+				javaVersion, flags.bootClasspathArgs, flags.classpathArgs, opts,
+				`\n******************************\n`+
+					`You have tried to change the API from what has been previously released in\n`+
+					`an SDK.  Please fix the errors listed above.\n`+
+					`******************************\n`,
+				d.checkLastReleasedApiTimestamp)
+		}
 	}
 }
 
diff --git a/scripts/clang-tidy.sh b/scripts/clang-tidy.sh
new file mode 100755
index 0000000..04d0bdd
--- /dev/null
+++ b/scripts/clang-tidy.sh
@@ -0,0 +1,37 @@
+#!/bin/bash -e
+
+# Copyright 2018 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.
+
+# Wrapper script to remove clang compiler flags rejected by clang-tidy.
+# Inputs:
+#  Environment:
+#   CLANG_TIDY: path to the real clang-tidy program
+
+# clang-tidy doesn't recognize every flag that clang compiler does.
+# It gives clang-diagnostic-unused-command-line-argument warnings
+# to -Wa,* flags.
+# The -flto flags caused clang-tidy to ignore the -I flags,
+# see https://bugs.llvm.org/show_bug.cgi?id=38332.
+# -fsanitize and -fwhole-program-vtables need -flto.
+args=("${@}")
+n=${#args[@]}
+for ((i=0; i<$n; ++i)); do
+  case ${args[i]} in
+    -Wa,*|-flto|-flto=*|-fsanitize=*|-fsanitize-*|-fwhole-program-vtables)
+      unset args[i]
+      ;;
+  esac
+done
+${CLANG_TIDY} "${args[@]}"
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 57f9595..a076b66 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -108,7 +108,7 @@
 		productOut("system_other"),
 		productOut("vendor"),
 		productOut("product"),
-		productOut("product-services"),
+		productOut("product_services"),
 		productOut("oem"),
 		productOut("obj/FAKE"),
 		productOut("breakpad"),
diff --git a/ui/build/config.go b/ui/build/config.go
index eefe0ed..c171a67 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -293,6 +293,9 @@
 	// for others)
 	if inList("C.UTF-8", locales) {
 		c.environ.Set("LANG", "C.UTF-8")
+	} else if inList("C.utf8", locales) {
+		// These normalize to the same thing
+		c.environ.Set("LANG", "C.UTF-8")
 	} else if inList("en_US.UTF-8", locales) {
 		c.environ.Set("LANG", "en_US.UTF-8")
 	} else if inList("en_US.utf8", locales) {