Merge "Remove unused Common field."
diff --git a/android/apex.go b/android/apex.go
index 4b74436..4618fe9 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -117,19 +117,6 @@
 	return false
 }
 
-// InApexByBaseName tells whether this apex variant of the module is part of the given apexVariant
-// or not, where the APEX is specified by its canonical base name, i.e. typically beginning with
-// "com.android.". In particular this function doesn't differentiate between source and prebuilt
-// APEXes, where the latter may have "prebuilt_" prefixes.
-func (i ApexInfo) InApexVariantByBaseName(apexVariant string) bool {
-	for _, a := range i.InApexVariants {
-		if RemoveOptionalPrebuiltPrefix(a) == apexVariant {
-			return true
-		}
-	}
-	return false
-}
-
 func (i ApexInfo) InApexModule(apexModuleName string) bool {
 	for _, a := range i.InApexModules {
 		if a == apexModuleName {
@@ -669,8 +656,8 @@
 	mctx.VisitDirectDeps(func(dep Module) {
 		if _, ok := mctx.OtherModuleDependencyTag(dep).(CopyDirectlyInAnyApexTag); ok {
 			depBase := dep.(ApexModule).apexModuleBase()
-			base.ApexProperties.DirectlyInAnyApex = depBase.ApexProperties.DirectlyInAnyApex
-			base.ApexProperties.InAnyApex = depBase.ApexProperties.InAnyApex
+			depBase.ApexProperties.DirectlyInAnyApex = base.ApexProperties.DirectlyInAnyApex
+			depBase.ApexProperties.InAnyApex = base.ApexProperties.InAnyApex
 		}
 	})
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 364013f..4d00944 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7611,6 +7611,80 @@
 		}))
 }
 
+func TestApexJavaCoverage(t *testing.T) {
+	bp := `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["mylib"],
+			bootclasspath_fragments: ["mybootclasspathfragment"],
+			systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_library {
+			name: "mylib",
+			srcs: ["mylib.java"],
+			apex_available: ["myapex"],
+			compile_dex: true,
+		}
+
+		bootclasspath_fragment {
+			name: "mybootclasspathfragment",
+			contents: ["mybootclasspathlib"],
+			apex_available: ["myapex"],
+		}
+
+		java_library {
+			name: "mybootclasspathlib",
+			srcs: ["mybootclasspathlib.java"],
+			apex_available: ["myapex"],
+			compile_dex: true,
+		}
+
+		systemserverclasspath_fragment {
+			name: "mysystemserverclasspathfragment",
+			contents: ["mysystemserverclasspathlib"],
+			apex_available: ["myapex"],
+		}
+
+		java_library {
+			name: "mysystemserverclasspathlib",
+			srcs: ["mysystemserverclasspathlib.java"],
+			apex_available: ["myapex"],
+			compile_dex: true,
+		}
+	`
+
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithApexBuildComponents,
+		prepareForTestWithMyapex,
+		java.PrepareForTestWithJavaDefaultModules,
+		android.PrepareForTestWithAndroidBuildComponents,
+		android.FixtureWithRootAndroidBp(bp),
+		android.FixtureMergeEnv(map[string]string{
+			"EMMA_INSTRUMENT": "true",
+		}),
+	).RunTest(t)
+
+	// Make sure jacoco ran on both mylib and mybootclasspathlib
+	if result.ModuleForTests("mylib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+		t.Errorf("Failed to find jacoco rule for mylib")
+	}
+	if result.ModuleForTests("mybootclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+		t.Errorf("Failed to find jacoco rule for mybootclasspathlib")
+	}
+	if result.ModuleForTests("mysystemserverclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+		t.Errorf("Failed to find jacoco rule for mysystemserverclasspathlib")
+	}
+}
+
 func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 }
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 6125ef5..81bfc86 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -228,10 +228,11 @@
 	})
 
 	// Create an ApexInfo for the prebuilt_apex.
+	apexVariationName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
 	apexInfo := android.ApexInfo{
-		ApexVariationName: android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName()),
-		InApexVariants:    []string{mctx.ModuleName()},
-		InApexModules:     []string{mctx.ModuleName()},
+		ApexVariationName: apexVariationName,
+		InApexVariants:    []string{apexVariationName},
+		InApexModules:     []string{apexVariationName},
 		ApexContents:      []*android.ApexContents{apexContents},
 		ForPrebuiltApex:   true,
 	}
diff --git a/bazel/properties.go b/bazel/properties.go
index c8ccfb8..813a701 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -332,49 +332,174 @@
 	HasConfigurableValues() bool
 }
 
-// Represents an attribute whose value is a single label
-type LabelAttribute struct {
-	Value  Label
+type labelArchValues struct {
 	X86    Label
 	X86_64 Label
 	Arm    Label
 	Arm64  Label
+
+	ConditionsDefault Label
+}
+
+type labelTargetValue struct {
+	// E.g. for android
+	OsValue Label
+
+	// E.g. for android_arm, android_arm64, ...
+	ArchValues labelArchValues
+}
+
+type labelTargetValues struct {
+	Android     labelTargetValue
+	Darwin      labelTargetValue
+	Fuchsia     labelTargetValue
+	Linux       labelTargetValue
+	LinuxBionic labelTargetValue
+	Windows     labelTargetValue
+
+	ConditionsDefault labelTargetValue
+}
+
+// Represents an attribute whose value is a single label
+type LabelAttribute struct {
+	Value Label
+
+	ArchValues labelArchValues
+
+	TargetValues labelTargetValues
 }
 
 func (attr *LabelAttribute) GetValueForArch(arch string) Label {
-	switch arch {
-	case ARCH_ARM:
-		return attr.Arm
-	case ARCH_ARM64:
-		return attr.Arm64
-	case ARCH_X86:
-		return attr.X86
-	case ARCH_X86_64:
-		return attr.X86_64
-	case CONDITIONS_DEFAULT:
-		return attr.Value
-	default:
-		panic("Invalid arch type")
+	var v *Label
+	if v = attr.archValuePtrs()[arch]; v == nil {
+		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
+	return *v
 }
 
 func (attr *LabelAttribute) SetValueForArch(arch string, value Label) {
-	switch arch {
-	case ARCH_ARM:
-		attr.Arm = value
-	case ARCH_ARM64:
-		attr.Arm64 = value
-	case ARCH_X86:
-		attr.X86 = value
-	case ARCH_X86_64:
-		attr.X86_64 = value
-	default:
-		panic("Invalid arch type")
+	var v *Label
+	if v = attr.archValuePtrs()[arch]; v == nil {
+		panic(fmt.Errorf("Unknown arch: %s", arch))
+	}
+	*v = value
+}
+
+func (attr *LabelAttribute) archValuePtrs() map[string]*Label {
+	return map[string]*Label{
+		ARCH_X86:           &attr.ArchValues.X86,
+		ARCH_X86_64:        &attr.ArchValues.X86_64,
+		ARCH_ARM:           &attr.ArchValues.Arm,
+		ARCH_ARM64:         &attr.ArchValues.Arm64,
+		CONDITIONS_DEFAULT: &attr.ArchValues.ConditionsDefault,
 	}
 }
 
 func (attr LabelAttribute) HasConfigurableValues() bool {
-	return attr.Arm.Label != "" || attr.Arm64.Label != "" || attr.X86.Label != "" || attr.X86_64.Label != ""
+	for arch := range PlatformArchMap {
+		if attr.GetValueForArch(arch).Label != "" {
+			return true
+		}
+	}
+
+	for os := range PlatformOsMap {
+		if attr.GetOsValueForTarget(os).Label != "" {
+			return true
+		}
+		// TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT (not in AllArches)
+		for _, arch := range AllArches {
+			if attr.GetOsArchValueForTarget(os, arch).Label != "" {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func (attr *LabelAttribute) getValueForTarget(os string) labelTargetValue {
+	var v *labelTargetValue
+	if v = attr.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	return *v
+}
+
+func (attr *LabelAttribute) GetOsValueForTarget(os string) Label {
+	var v *labelTargetValue
+	if v = attr.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	return v.OsValue
+}
+
+func (attr *LabelAttribute) GetOsArchValueForTarget(os string, arch string) Label {
+	var v *labelTargetValue
+	if v = attr.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 (attr *LabelAttribute) setValueForTarget(os string, value labelTargetValue) {
+	var v *labelTargetValue
+	if v = attr.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	*v = value
+}
+
+func (attr *LabelAttribute) SetOsValueForTarget(os string, value Label) {
+	var v *labelTargetValue
+	if v = attr.targetValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	v.OsValue = value
+}
+
+func (attr *LabelAttribute) SetOsArchValueForTarget(os string, arch string, value Label) {
+	var v *labelTargetValue
+	if v = attr.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))
+	}
+}
+
+func (attr *LabelAttribute) targetValuePtrs() map[string]*labelTargetValue {
+	return map[string]*labelTargetValue{
+		OS_ANDROID:         &attr.TargetValues.Android,
+		OS_DARWIN:          &attr.TargetValues.Darwin,
+		OS_FUCHSIA:         &attr.TargetValues.Fuchsia,
+		OS_LINUX:           &attr.TargetValues.Linux,
+		OS_LINUX_BIONIC:    &attr.TargetValues.LinuxBionic,
+		OS_WINDOWS:         &attr.TargetValues.Windows,
+		CONDITIONS_DEFAULT: &attr.TargetValues.ConditionsDefault,
+	}
 }
 
 // Arch-specific label_list typed Bazel attribute values. This should correspond
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 6aa148e..49f1f42 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -808,3 +808,46 @@
 )`},
 	})
 }
+
+func TestCcLibraryLabelAttributeGetTargetProperties(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		description:                        "cc_library GetTargetProperties on a LabelAttribute",
+		moduleTypeUnderTest:                "cc_library",
+		moduleTypeUnderTestFactory:         cc.LibraryFactory,
+		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+		depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+		dir:                                "foo/bar",
+		filesystem: map[string]string{
+			"foo/bar/Android.bp": `
+		cc_library {
+		   name: "a",
+		   srcs: ["a.cpp"],
+		   target: {
+		     android_arm: {
+		       version_script: "android_arm.map",
+		     },
+		     linux_bionic_arm64: {
+		       version_script: "linux_bionic_arm64.map",
+		     },
+		   },
+
+		   bazel_module: { bp2build_available: true },
+		}
+		`,
+		},
+		blueprint: soongCcLibraryPreamble,
+		expectedBazelTargets: []string{`cc_library(
+    name = "a",
+    copts = [
+        "-Ifoo/bar",
+        "-I$(BINDIR)/foo/bar",
+    ],
+    srcs = ["a.cpp"],
+    version_script = select({
+        "//build/bazel/platforms:android_arm": "android_arm.map",
+        "//build/bazel/platforms:linux_bionic_arm64": "linux_bionic_arm64.map",
+        "//conditions:default": None,
+    }),
+)`},
+	})
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index b5070b9..c13e737 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -60,19 +60,67 @@
 }
 
 func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
-	var value reflect.Value
-	var archSelects selects
-
-	if label.HasConfigurableValues() {
-		archSelects = map[string]reflect.Value{}
-		for arch, selectKey := range bazel.PlatformArchMap {
-			archSelects[selectKey] = reflect.ValueOf(label.GetValueForArch(arch))
-		}
-	} else {
-		value = reflect.ValueOf(label.Value)
+	value := reflect.ValueOf(label.Value)
+	if !label.HasConfigurableValues() {
+		return value, []selects{}
 	}
 
-	return value, []selects{archSelects}
+	// Keep track of which arches and oses have been used in case we need to raise a warning
+	usedArches := make(map[string]bool)
+	usedOses := make(map[string]bool)
+
+	archSelects := map[string]reflect.Value{}
+	for arch, selectKey := range bazel.PlatformArchMap {
+		archSelects[selectKey] = reflect.ValueOf(label.GetValueForArch(arch))
+		if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
+			usedArches[arch] = true
+		}
+	}
+
+	osSelects := map[string]reflect.Value{}
+	for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
+		selectKey := bazel.PlatformOsMap[os]
+		osSelects[selectKey] = reflect.ValueOf(label.GetOsValueForTarget(os))
+		if osSelects[selectKey].IsValid() && !isZero(osSelects[selectKey]) {
+			usedOses[os] = true
+		}
+	}
+
+	osArchSelects := make([]selects, 0)
+	for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
+		archSelects := make(map[string]reflect.Value)
+		// TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (not in AllArches)
+		for _, arch := range bazel.AllArches {
+			target := os + "_" + arch
+			selectKey := bazel.PlatformTargetMap[target]
+			archSelects[selectKey] = reflect.ValueOf(label.GetOsArchValueForTarget(os, arch))
+			if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
+				if _, ok := usedArches[arch]; ok {
+					fmt.Printf("WARNING: Same arch used twice in LabelAttribute select: arch '%s'\n", arch)
+				}
+				if _, ok := usedOses[os]; ok {
+					fmt.Printf("WARNING: Same os used twice in LabelAttribute select: os '%s'\n", os)
+				}
+			}
+		}
+		osArchSelects = append(osArchSelects, archSelects)
+	}
+
+	// Because we have to return a single Label, we can only use one select statement
+	combinedSelects := map[string]reflect.Value{}
+	for k, v := range archSelects {
+		combinedSelects[k] = v
+	}
+	for k, v := range osSelects {
+		combinedSelects[k] = v
+	}
+	for _, osArchSelect := range osArchSelects {
+		for k, v := range osArchSelect {
+			combinedSelects[k] = v
+		}
+	}
+
+	return value, []selects{combinedSelects}
 }
 
 func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 339a489..711410c 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -568,6 +568,10 @@
 
 			linkopts.SetOsValueForTarget(os.Name, getBp2BuildLinkerFlags(baseLinkerProps))
 
+			if baseLinkerProps.Version_script != nil {
+				versionScript.SetOsValueForTarget(os.Name, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
+			}
+
 			sharedLibs := baseLinkerProps.Shared_libs
 			dynamicDeps.SetOsValueForTarget(os.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
 		}
@@ -582,6 +586,10 @@
 
 				linkopts.SetOsArchValueForTarget(os.Name, arch.Name, getBp2BuildLinkerFlags(baseLinkerProps))
 
+				if baseLinkerProps.Version_script != nil {
+					versionScript.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
+				}
+
 				sharedLibs := baseLinkerProps.Shared_libs
 				dynamicDeps.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
 			}
diff --git a/cc/cc.go b/cc/cc.go
index 8a34dad..aa218bf 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -729,12 +729,6 @@
 	llndkStubDepTag       = dependencyTag{name: "llndk stub"}
 )
 
-type copyDirectlyInAnyApexDependencyTag dependencyTag
-
-func (copyDirectlyInAnyApexDependencyTag) CopyDirectlyInAnyApex() {}
-
-var _ android.CopyDirectlyInAnyApexTag = copyDirectlyInAnyApexDependencyTag{}
-
 func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
 	ccLibDepTag, ok := depTag.(libraryDependencyTag)
 	return ok && ccLibDepTag.shared()
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 44803a9..792193f 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -22,6 +22,7 @@
 
 	"android/soong/android"
 	"android/soong/dexpreopt"
+
 	"github.com/google/blueprint/proptools"
 
 	"github.com/google/blueprint"
@@ -76,12 +77,17 @@
 	return true
 }
 
+// Contents of bootclasspath fragments in an apex are considered to be directly in the apex, as if
+// they were listed in java_libs.
+func (b bootclasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {}
+
 // The tag used for the dependency between the bootclasspath_fragment module and its contents.
 var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
 
 var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
 var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
 var _ android.SdkMemberTypeDependencyTag = bootclasspathFragmentContentDepTag
+var _ android.CopyDirectlyInAnyApexTag = bootclasspathFragmentContentDepTag
 
 func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
 	return tag == bootclasspathFragmentContentDepTag
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index bdf055a..52934a3 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -171,7 +171,7 @@
 			// A platform variant is required but this is for an apex so ignore it.
 			return false
 		}
-	} else if !apexInfo.InApexVariantByBaseName(requiredApex) {
+	} else if !apexInfo.InApexVariant(requiredApex) {
 		// An apex variant for a specific apex is required but this is the wrong apex.
 		return false
 	}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index f973cf4..7ffb056 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"android/soong/dexpreopt"
+
 	"github.com/google/blueprint"
 )
 
@@ -118,6 +119,12 @@
 	blueprint.BaseDependencyTag
 }
 
+// Contents of system server fragments in an apex are considered to be directly in the apex, as if
+// they were listed in java_libs.
+func (systemServerClasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {}
+
+var _ android.CopyDirectlyInAnyApexTag = systemServerClasspathFragmentContentDepTag
+
 // The tag used for the dependency between the systemserverclasspath_fragment module and its contents.
 var systemServerClasspathFragmentContentDepTag = systemServerClasspathFragmentContentDependencyTag{}