Merge "Add recovery_available to prebuilt_etc."
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/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/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..072821c 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -300,6 +300,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/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/java/app.go b/java/app.go
index 78d526d..3f72ec9 100644
--- a/java/app.go
+++ b/java/app.go
@@ -208,7 +208,7 @@
 		&module.aaptProperties,
 		&module.appProperties)
 
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+	InitJavaModule(module, android.DeviceSupported)
 	return module
 }
 
@@ -261,7 +261,6 @@
 		&module.appTestProperties,
 		&module.testProperties)
 
-	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
-
+	InitJavaModule(module, android.DeviceSupported)
 	return module
 }
diff --git a/java/droiddoc.go b/java/droiddoc.go
index f90c548..104e46d 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -950,9 +950,8 @@
 		previousApi := ctx.ExpandSource(String(d.properties.Metalava_previous_api),
 			"metalava_previous_api")
 		*implicits = append(*implicits, previousApi)
-		flags += " --previous-api " + previousApi.String()
 
-		flags += " --include-annotations --migrate-nullness"
+		flags += " --include-annotations --migrate-nullness " + previousApi.String()
 
 		d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
 		*implicitOutputs = append(*implicitOutputs, d.annotationsZip)
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index dd2e355..264e422 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -78,7 +78,7 @@
 func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, prop *string) android.Path {
 	path, autogenPath := testConfigPath(ctx, prop)
 	if autogenPath != nil {
-		autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}")
+		autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}")
 	}
 	return path
 }
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"),