Make GetTargetProperties() aware of more complex targets, like 'android_arm', instead of just 'android'.

Test: Added new unit test and updated existing tests.

Test: bazel build //bionic/... //external/... //frameworks/... //system/...

Test: ./build/bazel/scripts/run_presubmits.sh

Change-Id: I250d1964f5cf42b92ddb929379d35d8c844423f7
diff --git a/bazel/properties.go b/bazel/properties.go
index 6ecf6ca..8adc9d0 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -160,7 +160,12 @@
 	}
 
 	for os := range PlatformOsMap {
-		result.SetValueForOS(os, FilterLabelList(haystack.GetValueForOS(os), needleFn))
+		result.SetOsValueForTarget(os, FilterLabelList(haystack.GetOsValueForTarget(os), needleFn))
+
+		// TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
+		for _, arch := range AllArches {
+			result.SetOsArchValueForTarget(os, arch, FilterLabelList(haystack.GetOsArchValueForTarget(os, arch), needleFn))
+		}
 	}
 
 	return result
@@ -176,8 +181,12 @@
 	}
 
 	for os := range PlatformOsMap {
-		result.SetValueForOS(os,
-			SubtractBazelLabelList(haystack.GetValueForOS(os), needle.GetValueForOS(os)))
+		result.SetOsValueForTarget(os, SubtractBazelLabelList(haystack.GetOsValueForTarget(os), needle.GetOsValueForTarget(os)))
+
+		// TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
+		for _, arch := range AllArches {
+			result.SetOsArchValueForTarget(os, arch, SubtractBazelLabelList(haystack.GetOsArchValueForTarget(os, arch), needle.GetOsArchValueForTarget(os, arch)))
+		}
 	}
 
 	result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
@@ -241,6 +250,21 @@
 	OS_LINUX_BIONIC = "linux_bionic"
 	OS_WINDOWS      = "windows"
 
+	// Targets in arch.go
+	TARGET_ANDROID_ARM         = "android_arm"
+	TARGET_ANDROID_ARM64       = "android_arm64"
+	TARGET_ANDROID_X86         = "android_x86"
+	TARGET_ANDROID_X86_64      = "android_x86_64"
+	TARGET_DARWIN_X86_64       = "darwin_x86_64"
+	TARGET_FUCHSIA_ARM64       = "fuchsia_arm64"
+	TARGET_FUCHSIA_X86_64      = "fuchsia_x86_64"
+	TARGET_LINUX_X86           = "linux_glibc_x86"
+	TARGET_LINUX_x86_64        = "linux_glibc_x86_64"
+	TARGET_LINUX_BIONIC_ARM64  = "linux_bionic_arm64"
+	TARGET_LINUX_BIONIC_X86_64 = "linux_bionic_x86_64"
+	TARGET_WINDOWS_X86         = "windows_x86"
+	TARGET_WINDOWS_X86_64      = "windows_x86_64"
+
 	// This is the string representation of the default condition wherever a
 	// configurable attribute is used in a select statement, i.e.
 	// //conditions:default for Bazel.
@@ -282,6 +306,26 @@
 		OS_WINDOWS:         "//build/bazel/platforms/os:windows",
 		CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
 	}
+
+	PlatformTargetMap = map[string]string{
+		TARGET_ANDROID_ARM:         "//build/bazel/platforms:android_arm",
+		TARGET_ANDROID_ARM64:       "//build/bazel/platforms:android_arm64",
+		TARGET_ANDROID_X86:         "//build/bazel/platforms:android_x86",
+		TARGET_ANDROID_X86_64:      "//build/bazel/platforms:android_x86_64",
+		TARGET_DARWIN_X86_64:       "//build/bazel/platforms:darwin_x86_64",
+		TARGET_FUCHSIA_ARM64:       "//build/bazel/platforms:fuchsia_arm64",
+		TARGET_FUCHSIA_X86_64:      "//build/bazel/platforms:fuchsia_x86_64",
+		TARGET_LINUX_X86:           "//build/bazel/platforms:linux_glibc_x86",
+		TARGET_LINUX_x86_64:        "//build/bazel/platforms:linux_glibc_x86_64",
+		TARGET_LINUX_BIONIC_ARM64:  "//build/bazel/platforms:linux_bionic_arm64",
+		TARGET_LINUX_BIONIC_X86_64: "//build/bazel/platforms:linux_bionic_x86_64",
+		TARGET_WINDOWS_X86:         "//build/bazel/platforms:windows_x86",
+		TARGET_WINDOWS_X86_64:      "//build/bazel/platforms:windows_x86_64",
+		CONDITIONS_DEFAULT:         ConditionsDefaultSelectKey, // The default condition of an os select map.
+	}
+
+	// TODO(b/187530594): Should we add CONDITIONS_DEFAULT here?
+	AllArches = []string{ARCH_ARM, ARCH_ARM64, ARCH_X86, ARCH_X86_64}
 )
 
 type Attribute interface {
@@ -345,15 +389,32 @@
 	ConditionsDefault LabelList
 }
 
-type labelListOsValues struct {
-	Android     LabelList
-	Darwin      LabelList
-	Fuchsia     LabelList
-	Linux       LabelList
-	LinuxBionic LabelList
-	Windows     LabelList
+type labelListTargetValue struct {
+	// E.g. for android
+	OsValue LabelList
 
-	ConditionsDefault LabelList
+	// E.g. for android_arm, android_arm64, ...
+	ArchValues labelListArchValues
+}
+
+func (target *labelListTargetValue) Append(other labelListTargetValue) {
+	target.OsValue.Append(other.OsValue)
+	target.ArchValues.X86.Append(other.ArchValues.X86)
+	target.ArchValues.X86_64.Append(other.ArchValues.X86_64)
+	target.ArchValues.Arm.Append(other.ArchValues.Arm)
+	target.ArchValues.Arm64.Append(other.ArchValues.Arm64)
+	target.ArchValues.ConditionsDefault.Append(other.ArchValues.ConditionsDefault)
+}
+
+type labelListTargetValues struct {
+	Android     labelListTargetValue
+	Darwin      labelListTargetValue
+	Fuchsia     labelListTargetValue
+	Linux       labelListTargetValue
+	LinuxBionic labelListTargetValue
+	Windows     labelListTargetValue
+
+	ConditionsDefault labelListTargetValue
 }
 
 // LabelListAttribute is used to represent a list of Bazel labels as an
@@ -370,7 +431,7 @@
 	// The os-specific attribute label list values. Optional. If used, these
 	// are generated in a select statement and appended to the non-os specific
 	// label list Value.
-	OsValues labelListOsValues
+	TargetValues labelListTargetValues
 }
 
 // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
@@ -389,10 +450,10 @@
 	}
 
 	for os := range PlatformOsMap {
-		this := attrs.GetValueForOS(os)
-		that := other.GetValueForOS(os)
+		this := attrs.getValueForTarget(os)
+		that := other.getValueForTarget(os)
 		this.Append(that)
-		attrs.SetValueForOS(os, this)
+		attrs.setValueForTarget(os, this)
 	}
 
 	attrs.Value.Append(other.Value)
@@ -408,9 +469,15 @@
 	}
 
 	for os := range PlatformOsMap {
-		if len(attrs.GetValueForOS(os).Includes) > 0 {
+		if len(attrs.GetOsValueForTarget(os).Includes) > 0 {
 			return true
 		}
+		// TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT (not in AllArches)
+		for _, arch := range AllArches {
+			if len(attrs.GetOsArchValueForTarget(os, arch).Includes) > 0 {
+				return true
+			}
+		}
 	}
 	return false
 }
@@ -443,36 +510,92 @@
 	*v = value
 }
 
-func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
-	return map[string]*LabelList{
-		OS_ANDROID:         &attrs.OsValues.Android,
-		OS_DARWIN:          &attrs.OsValues.Darwin,
-		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
-		OS_LINUX:           &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:         &attrs.OsValues.Windows,
-		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
+func (attrs *LabelListAttribute) targetValuePtrs() map[string]*labelListTargetValue {
+	return map[string]*labelListTargetValue{
+		OS_ANDROID:         &attrs.TargetValues.Android,
+		OS_DARWIN:          &attrs.TargetValues.Darwin,
+		OS_FUCHSIA:         &attrs.TargetValues.Fuchsia,
+		OS_LINUX:           &attrs.TargetValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.TargetValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.TargetValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
 	}
 }
 
-// GetValueForOS returns the label_list attribute value for an OS target.
-func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList {
-	var v *LabelList
-	if v = attrs.osValuePtrs()[os]; v == nil {
+func (attrs *LabelListAttribute) getValueForTarget(os string) labelListTargetValue {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
 		panic(fmt.Errorf("Unknown os: %s", os))
 	}
 	return *v
 }
 
-// SetValueForArch sets the label_list attribute value for an OS target.
-func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) {
-	var v *LabelList
-	if v = attrs.osValuePtrs()[os]; v == nil {
+func (attrs *LabelListAttribute) GetOsValueForTarget(os string) LabelList {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	return v.OsValue
+}
+
+func (attrs *LabelListAttribute) GetOsArchValueForTarget(os string, arch string) LabelList {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	switch arch {
+	case ARCH_X86:
+		return v.ArchValues.X86
+	case ARCH_X86_64:
+		return v.ArchValues.X86_64
+	case ARCH_ARM:
+		return v.ArchValues.Arm
+	case ARCH_ARM64:
+		return v.ArchValues.Arm64
+	case CONDITIONS_DEFAULT:
+		return v.ArchValues.ConditionsDefault
+	default:
+		panic(fmt.Errorf("Unknown arch: %s\n", arch))
+	}
+}
+
+func (attrs *LabelListAttribute) setValueForTarget(os string, value labelListTargetValue) {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
 		panic(fmt.Errorf("Unknown os: %s", os))
 	}
 	*v = value
 }
 
+func (attrs *LabelListAttribute) SetOsValueForTarget(os string, value LabelList) {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	v.OsValue = value
+}
+
+func (attrs *LabelListAttribute) SetOsArchValueForTarget(os string, arch string, value LabelList) {
+	var v *labelListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	switch arch {
+	case ARCH_X86:
+		v.ArchValues.X86 = value
+	case ARCH_X86_64:
+		v.ArchValues.X86_64 = value
+	case ARCH_ARM:
+		v.ArchValues.Arm = value
+	case ARCH_ARM64:
+		v.ArchValues.Arm64 = value
+	case CONDITIONS_DEFAULT:
+		v.ArchValues.ConditionsDefault = value
+	default:
+		panic(fmt.Errorf("Unknown arch: %s\n", arch))
+	}
+}
+
 // StringListAttribute corresponds to the string_list Bazel attribute type with
 // support for additional metadata, like configurations.
 type StringListAttribute struct {
@@ -487,7 +610,7 @@
 	// The os-specific attribute string list values. Optional. If used, these
 	// are generated in a select statement and appended to the non-os specific
 	// label list Value.
-	OsValues stringListOsValues
+	TargetValues stringListTargetValues
 
 	// list of product-variable string list values. Optional. if used, each will generate a select
 	// statement appended to the label list Value.
@@ -512,15 +635,32 @@
 	ConditionsDefault []string
 }
 
-type stringListOsValues struct {
-	Android     []string
-	Darwin      []string
-	Fuchsia     []string
-	Linux       []string
-	LinuxBionic []string
-	Windows     []string
+type stringListTargetValue struct {
+	// E.g. for android
+	OsValue []string
 
-	ConditionsDefault []string
+	// E.g. for android_arm, android_arm64, ...
+	ArchValues stringListArchValues
+}
+
+func (target *stringListTargetValue) Append(other stringListTargetValue) {
+	target.OsValue = append(target.OsValue, other.OsValue...)
+	target.ArchValues.X86 = append(target.ArchValues.X86, other.ArchValues.X86...)
+	target.ArchValues.X86_64 = append(target.ArchValues.X86_64, other.ArchValues.X86_64...)
+	target.ArchValues.Arm = append(target.ArchValues.Arm, other.ArchValues.Arm...)
+	target.ArchValues.Arm64 = append(target.ArchValues.Arm64, other.ArchValues.Arm64...)
+	target.ArchValues.ConditionsDefault = append(target.ArchValues.ConditionsDefault, other.ArchValues.ConditionsDefault...)
+}
+
+type stringListTargetValues struct {
+	Android     stringListTargetValue
+	Darwin      stringListTargetValue
+	Fuchsia     stringListTargetValue
+	Linux       stringListTargetValue
+	LinuxBionic stringListTargetValue
+	Windows     stringListTargetValue
+
+	ConditionsDefault stringListTargetValue
 }
 
 // Product Variable values for StringListAttribute
@@ -545,9 +685,16 @@
 	}
 
 	for os := range PlatformOsMap {
-		if len(attrs.GetValueForOS(os)) > 0 {
+		if len(attrs.GetOsValueForTarget(os)) > 0 {
 			return true
 		}
+		// TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (Not in AllArches)
+		for _, arch := range AllArches {
+			if len(attrs.GetOsArchValueForTarget(os, arch)) > 0 {
+				return true
+			}
+
+		}
 	}
 
 	return len(attrs.ProductValues) > 0
@@ -581,31 +728,58 @@
 	*v = value
 }
 
-func (attrs *StringListAttribute) osValuePtrs() map[string]*[]string {
-	return map[string]*[]string{
-		OS_ANDROID:         &attrs.OsValues.Android,
-		OS_DARWIN:          &attrs.OsValues.Darwin,
-		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
-		OS_LINUX:           &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:         &attrs.OsValues.Windows,
-		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
+func (attrs *StringListAttribute) targetValuePtrs() map[string]*stringListTargetValue {
+	return map[string]*stringListTargetValue{
+		OS_ANDROID:         &attrs.TargetValues.Android,
+		OS_DARWIN:          &attrs.TargetValues.Darwin,
+		OS_FUCHSIA:         &attrs.TargetValues.Fuchsia,
+		OS_LINUX:           &attrs.TargetValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.TargetValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.TargetValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
 	}
 }
 
-// GetValueForOS returns the string_list attribute value for an OS target.
-func (attrs *StringListAttribute) GetValueForOS(os string) []string {
-	var v *[]string
-	if v = attrs.osValuePtrs()[os]; v == nil {
+func (attrs *StringListAttribute) getValueForTarget(os string) stringListTargetValue {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
 		panic(fmt.Errorf("Unknown os: %s", os))
 	}
 	return *v
 }
 
-// SetValueForArch sets the string_list attribute value for an OS target.
-func (attrs *StringListAttribute) SetValueForOS(os string, value []string) {
-	var v *[]string
-	if v = attrs.osValuePtrs()[os]; v == nil {
+func (attrs *StringListAttribute) GetOsValueForTarget(os string) []string {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	return v.OsValue
+}
+
+func (attrs *StringListAttribute) GetOsArchValueForTarget(os string, arch string) []string {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	switch arch {
+	case ARCH_X86:
+		return v.ArchValues.X86
+	case ARCH_X86_64:
+		return v.ArchValues.X86_64
+	case ARCH_ARM:
+		return v.ArchValues.Arm
+	case ARCH_ARM64:
+		return v.ArchValues.Arm64
+	case CONDITIONS_DEFAULT:
+		return v.ArchValues.ConditionsDefault
+	default:
+		panic(fmt.Errorf("Unknown arch: %s\n", arch))
+	}
+}
+
+func (attrs *StringListAttribute) setValueForTarget(os string, value stringListTargetValue) {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
 		panic(fmt.Errorf("Unknown os: %s", os))
 	}
 	*v = value
@@ -617,6 +791,35 @@
 	return vals
 }
 
+func (attrs *StringListAttribute) SetOsValueForTarget(os string, value []string) {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	v.OsValue = value
+}
+
+func (attrs *StringListAttribute) SetOsArchValueForTarget(os string, arch string, value []string) {
+	var v *stringListTargetValue
+	if v = attrs.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	switch arch {
+	case ARCH_X86:
+		v.ArchValues.X86 = value
+	case ARCH_X86_64:
+		v.ArchValues.X86_64 = value
+	case ARCH_ARM:
+		v.ArchValues.Arm = value
+	case ARCH_ARM64:
+		v.ArchValues.Arm64 = value
+	case CONDITIONS_DEFAULT:
+		v.ArchValues.ConditionsDefault = value
+	default:
+		panic(fmt.Errorf("Unknown arch: %s\n", arch))
+	}
+}
+
 // Append appends all values, including os and arch specific ones, from another
 // StringListAttribute to this StringListAttribute
 func (attrs *StringListAttribute) Append(other StringListAttribute) {
@@ -628,10 +831,10 @@
 	}
 
 	for os := range PlatformOsMap {
-		this := attrs.GetValueForOS(os)
-		that := other.GetValueForOS(os)
-		this = append(this, that...)
-		attrs.SetValueForOS(os, this)
+		this := attrs.getValueForTarget(os)
+		that := other.getValueForTarget(os)
+		this.Append(that)
+		attrs.setValueForTarget(os, this)
 	}
 
 	productValues := make(map[string][]string, 0)