Support asan/hwasan versions of prebuilts.

In apex_set and cc_prebuilt_library_*, provide a way to specify an
alternative source to use when build with sanitizers.

Test: prebuilt_test, apex_test
Change-Id: I1ab8091bf696d94da3547cf5248853df489bdee6
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 9f6c8ad..ce16d73 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -50,6 +50,10 @@
 	properties prebuiltCommonProperties
 }
 
+type sanitizedPrebuilt interface {
+	hasSanitizedSource(sanitizer string) bool
+}
+
 type prebuiltCommonProperties struct {
 	ForceDisable bool `blueprint:"mutated"`
 }
@@ -75,9 +79,10 @@
 	forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
 	forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
 
-	// 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())
+	// b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source
+	sanitized := ctx.Module().(sanitizedPrebuilt)
+	forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address"))
+	forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress"))
 
 	if forceDisable && p.prebuilt.SourceExists() {
 		p.properties.ForceDisable = true
@@ -135,6 +140,10 @@
 	Overrides []string
 }
 
+func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
+	return false
+}
+
 func (p *Prebuilt) installable() bool {
 	return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
 }
@@ -266,6 +275,18 @@
 	// the .apks file path that contains prebuilt apex files to be extracted.
 	Set *string
 
+	Sanitized struct {
+		None struct {
+			Set *string
+		}
+		Address struct {
+			Set *string
+		}
+		Hwaddress struct {
+			Set *string
+		}
+	}
+
 	// whether the extracted apex file installable.
 	Installable *bool
 
@@ -284,6 +305,41 @@
 	Prerelease *bool
 }
 
+func (a *ApexSet) prebuiltSrcs(ctx android.BaseModuleContext) []string {
+	var srcs []string
+	if a.properties.Set != nil {
+		srcs = append(srcs, *a.properties.Set)
+	}
+
+	var sanitizers []string
+	if ctx.Host() {
+		sanitizers = ctx.Config().SanitizeHost()
+	} else {
+		sanitizers = ctx.Config().SanitizeDevice()
+	}
+
+	if android.InList("address", sanitizers) && a.properties.Sanitized.Address.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.Address.Set)
+	} else if android.InList("hwaddress", sanitizers) && a.properties.Sanitized.Hwaddress.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.Hwaddress.Set)
+	} else if a.properties.Sanitized.None.Set != nil {
+		srcs = append(srcs, *a.properties.Sanitized.None.Set)
+	}
+
+	return srcs
+}
+
+func (a *ApexSet) hasSanitizedSource(sanitizer string) bool {
+	if sanitizer == "address" {
+		return a.properties.Sanitized.Address.Set != nil
+	}
+	if sanitizer == "hwaddress" {
+		return a.properties.Sanitized.Hwaddress.Set != nil
+	}
+
+	return false
+}
+
 func (a *ApexSet) installable() bool {
 	return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
 }
@@ -304,7 +360,12 @@
 func apexSetFactory() android.Module {
 	module := &ApexSet{}
 	module.AddProperties(&module.properties)
-	android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
+
+	srcsSupplier := func(ctx android.BaseModuleContext) []string {
+		return module.prebuiltSrcs(ctx)
+	}
+
+	android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "set")
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	return module
 }