Merge "Fix "unknown binary op: string + list" errors"
diff --git a/android/bazel.go b/android/bazel.go
index f4f9a72..970ad0d 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -367,13 +367,21 @@
 		"libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
 		"libcmd",                  // depends on unconverted modules: libbinder
 
+		"libdexfile_support_static",                                                       // Depends on unconverted module: libdexfile_external_headers
+		"libunwindstack_local", "libunwindstack_utils", "libc_malloc_debug", "libfdtrack", // Depends on unconverted module: libunwindstack
+
+		"libdexfile_support",          // TODO(b/210546943): Enabled based on product variables.
+		"libdexfile_external_headers", // TODO(b/210546943): Enabled based on product variables.
+
+		"libunwindstack",                // Depends on unconverted module libdexfile_support.
+		"libnativehelper_compat_libc++", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99
+
 		"chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol
 
 		"libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules
 
 		"gen-kotlin-build-file.py", // module has same name as source
 
-		"libbinder",               // TODO(b/188503688): Disabled for some archs,
 		"libactivitymanager_aidl", // TODO(b/207426160): Depends on activity_manager_procstate_aidl, which is an aidl filegroup.
 
 		"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libgmock_ndk
@@ -434,8 +442,7 @@
 		"linkerconfig", // http://b/202876379 has arch-variant static_executable
 		"mdnsd",        // http://b/202876379 has arch-variant static_executable
 
-		"acvp_modulewrapper", // disabled for android x86/x86_64
-		"CarHTMLViewer",      // depends on unconverted modules android.car-stubs, car-ui-lib
+		"CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
 
 		"libdexfile",  // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
 		"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
@@ -443,9 +450,7 @@
 
 	// Per-module denylist of cc_library modules to only generate the static
 	// variant if their shared variant isn't ready or buildable by Bazel.
-	bp2buildCcLibraryStaticOnlyList = []string{
-		"libjemalloc5", // http://b/188503688, cc_library, `target: { android: { enabled: false } }` for android targets.
-	}
+	bp2buildCcLibraryStaticOnlyList = []string{}
 
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
@@ -513,6 +518,9 @@
 		// Windows toolchains are not currently supported.
 		return false
 	}
+	if !ctx.Module().Enabled() {
+		return false
+	}
 	if !ctx.Config().BazelContext.BazelEnabled() {
 		return false
 	}
diff --git a/android/config.go b/android/config.go
index 5c0e5ae..0187a8a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1245,6 +1245,10 @@
 	return coverage
 }
 
+func (c *deviceConfig) AfdoAdditionalProfileDirs() []string {
+	return c.config.productVariables.AfdoAdditionalProfileDirs
+}
+
 func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
 	return c.config.productVariables.PgoAdditionalProfileDirs
 }
diff --git a/android/module.go b/android/module.go
index 6de4165..2750131 100644
--- a/android/module.go
+++ b/android/module.go
@@ -869,6 +869,13 @@
 	Data bazel.LabelListAttribute
 }
 
+// constraintAttributes represents Bazel attributes pertaining to build constraints,
+// which make restrict building a Bazel target for some set of platforms.
+type constraintAttributes struct {
+	// Constraint values this target can be built for.
+	Target_compatible_with bazel.LabelListAttribute
+}
+
 type distProperties struct {
 	// configuration to distribute output files from this module to the distribution
 	// directory (default: $OUT/dist, configurable with $DIST_DIR)
@@ -1089,7 +1096,8 @@
 	m.base().commonProperties.CreateCommonOSVariant = true
 }
 
-func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext) {
+func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext,
+	enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes {
 	// Assert passed-in attributes include Name
 	name := attrs.Name
 	if len(name) == 0 {
@@ -1107,14 +1115,45 @@
 
 	required := depsToLabelList(props.Required)
 	archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
+
+	var enabledProperty bazel.BoolAttribute
+	if props.Enabled != nil {
+		enabledProperty.Value = props.Enabled
+	}
+
 	for axis, configToProps := range archVariantProps {
 		for config, _props := range configToProps {
 			if archProps, ok := _props.(*commonProperties); ok {
 				required.SetSelectValue(axis, config, depsToLabelList(archProps.Required).Value)
+				if archProps.Enabled != nil {
+					enabledProperty.SetSelectValue(axis, config, archProps.Enabled)
+				}
 			}
 		}
 	}
+
+	if enabledPropertyOverrides.Value != nil {
+		enabledProperty.Value = enabledPropertyOverrides.Value
+	}
+	for _, axis := range enabledPropertyOverrides.SortedConfigurationAxes() {
+		configToBools := enabledPropertyOverrides.ConfigurableValues[axis]
+		for cfg, val := range configToBools {
+			enabledProperty.SetSelectValue(axis, cfg, &val)
+		}
+	}
+
 	data.Append(required)
+
+	var err error
+	constraints := constraintAttributes{}
+	constraints.Target_compatible_with, err = enabledProperty.ToLabelListAttribute(
+		bazel.LabelList{[]bazel.Label{bazel.Label{Label: "@platforms//:incompatible"}}, nil},
+		bazel.LabelList{[]bazel.Label{}, nil})
+
+	if err != nil {
+		ctx.ModuleErrorf("Error processing enabled attribute: %s", err)
+	}
+	return constraints
 }
 
 // A ModuleBase object contains the properties that are common to all Android
@@ -1233,10 +1272,11 @@
 
 // A struct containing all relevant information about a Bazel target converted via bp2build.
 type bp2buildInfo struct {
-	Dir         string
-	BazelProps  bazel.BazelTargetModuleProperties
-	CommonAttrs CommonAttributes
-	Attrs       interface{}
+	Dir             string
+	BazelProps      bazel.BazelTargetModuleProperties
+	CommonAttrs     CommonAttributes
+	ConstraintAttrs constraintAttributes
+	Attrs           interface{}
 }
 
 // TargetName returns the Bazel target name of a bp2build converted target.
@@ -1262,7 +1302,7 @@
 
 // BazelAttributes returns the Bazel attributes of a bp2build converted target.
 func (b bp2buildInfo) BazelAttributes() []interface{} {
-	return []interface{}{&b.CommonAttrs, b.Attrs}
+	return []interface{}{&b.CommonAttrs, &b.ConstraintAttrs, b.Attrs}
 }
 
 func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
diff --git a/android/mutator.go b/android/mutator.go
index dbd8c04..fa6f2be 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -254,6 +254,14 @@
 	// BazelTargetModuleProperties containing additional metadata for the
 	// bp2build codegenerator.
 	CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
+
+	// CreateBazelTargetModuleWithRestrictions creates a BazelTargetModule by calling the
+	// factory method, just like in CreateModule, but also requires
+	// BazelTargetModuleProperties containing additional metadata for the
+	// bp2build codegenerator. The generated target is restricted to only be buildable for certain
+	// platforms, as dictated by a given bool attribute: the target will not be buildable in
+	// any platform for which this bool attribute is false.
+	CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
 }
 
 type topDownMutatorContext struct {
@@ -502,13 +510,30 @@
 	bazelProps bazel.BazelTargetModuleProperties,
 	commonAttrs CommonAttributes,
 	attrs interface{}) {
-	commonAttrs.fillCommonBp2BuildModuleAttrs(t)
+	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{})
+}
+
+func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions(
+	bazelProps bazel.BazelTargetModuleProperties,
+	commonAttrs CommonAttributes,
+	attrs interface{},
+	enabledProperty bazel.BoolAttribute) {
+	t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
+}
+
+func (t *topDownMutatorContext) createBazelTargetModule(
+	bazelProps bazel.BazelTargetModuleProperties,
+	commonAttrs CommonAttributes,
+	attrs interface{},
+	enabledProperty bazel.BoolAttribute) {
+	constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
 	mod := t.Module()
 	info := bp2buildInfo{
-		Dir:         t.OtherModuleDir(mod),
-		BazelProps:  bazelProps,
-		CommonAttrs: commonAttrs,
-		Attrs:       attrs,
+		Dir:             t.OtherModuleDir(mod),
+		BazelProps:      bazelProps,
+		CommonAttrs:     commonAttrs,
+		ConstraintAttrs: constraintAttributes,
+		Attrs:           attrs,
 	}
 	mod.base().addBp2buildInfo(info)
 }
diff --git a/android/variable.go b/android/variable.go
index bc93835..a6156b1 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -124,6 +124,8 @@
 			Shared_libs       []string
 
 			Cmdline []string
+			Srcs         []string
+			Exclude_srcs []string
 		}
 
 		// eng is true for -eng builds, and can be used to turn on additionaly heavyweight debugging
@@ -327,7 +329,8 @@
 
 	NamespacesToExport []string `json:",omitempty"`
 
-	PgoAdditionalProfileDirs []string `json:",omitempty"`
+	AfdoAdditionalProfileDirs []string `json:",omitempty"`
+	PgoAdditionalProfileDirs  []string `json:",omitempty"`
 
 	VndkUseCoreVariant         *bool `json:",omitempty"`
 	VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 1993f76..7355ac7 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -109,6 +109,21 @@
 		osArchWindowsX86_64:        "//build/bazel/platforms/os_arch:windows_x86_64",
 		ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
 	}
+
+	// Map where keys are OsType names, and values are slices containing the archs
+	// that that OS supports.
+	// These definitions copied from arch.go.
+	// TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
+	// in a cyclic dependency.
+	osToArchMap = map[string][]string{
+		osAndroid:     {archArm, archArm64, archX86, archX86_64},
+		osLinux:       {archX86, archX86_64},
+		osLinuxMusl:   {archX86, archX86_64},
+		osDarwin:      {archArm64, archX86_64},
+		osLinuxBionic: {archArm64, archX86_64},
+		// TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
+		osWindows: {archX86, archX86_64},
+	}
 )
 
 // basic configuration types
@@ -122,6 +137,10 @@
 	productVariables
 )
 
+func osArchString(os string, arch string) string {
+	return fmt.Sprintf("%s_%s", os, arch)
+}
+
 func (ct configurationType) String() string {
 	return map[configurationType]string{
 		noConfig:         "no_config",
diff --git a/bazel/properties.go b/bazel/properties.go
index 76be058..d8b3a3a 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -244,9 +244,69 @@
 	ConfigurableValues configurableLabels
 }
 
+func (la *LabelAttribute) axisTypes() map[configurationType]bool {
+	types := map[configurationType]bool{}
+	for k := range la.ConfigurableValues {
+		if len(la.ConfigurableValues[k]) > 0 {
+			types[k.configurationType] = true
+		}
+	}
+	return types
+}
+
+// Collapse reduces the configurable axes of the label attribute to a single axis.
+// This is necessary for final writing to bp2build, as a configurable label
+// attribute can only be comprised by a single select.
+func (la *LabelAttribute) Collapse() error {
+	axisTypes := la.axisTypes()
+	_, containsOs := axisTypes[os]
+	_, containsArch := axisTypes[arch]
+	_, containsOsArch := axisTypes[osArch]
+	_, containsProductVariables := axisTypes[productVariables]
+	if containsProductVariables {
+		if containsOs || containsArch || containsOsArch {
+			return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
+		}
+	}
+	if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
+		// If a bool attribute has both os and arch configuration axes, the only
+		// way to successfully union their values is to increase the granularity
+		// of the configuration criteria to os_arch.
+		for osType, supportedArchs := range osToArchMap {
+			for _, supportedArch := range supportedArchs {
+				osArch := osArchString(osType, supportedArch)
+				if archOsVal := la.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
+					// Do nothing, as the arch_os is explicitly defined already.
+				} else {
+					archVal := la.SelectValue(ArchConfigurationAxis, supportedArch)
+					osVal := la.SelectValue(OsConfigurationAxis, osType)
+					if osVal != nil && archVal != nil {
+						// In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
+						// runs after os mutator.
+						la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
+					} else if osVal != nil && archVal == nil {
+						la.SetSelectValue(OsArchConfigurationAxis, osArch, *osVal)
+					} else if osVal == nil && archVal != nil {
+						la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
+					}
+				}
+			}
+		}
+		// All os_arch values are now set. Clear os and arch axes.
+		delete(la.ConfigurableValues, ArchConfigurationAxis)
+		delete(la.ConfigurableValues, OsConfigurationAxis)
+	}
+	return nil
+}
+
 // HasConfigurableValues returns whether there are configurable values set for this label.
 func (la LabelAttribute) HasConfigurableValues() bool {
-	return len(la.ConfigurableValues) > 0
+	for _, selectValues := range la.ConfigurableValues {
+		if len(selectValues) > 0 {
+			return true
+		}
+	}
+	return false
 }
 
 // SetValue sets the base, non-configured value for the Label
@@ -271,13 +331,13 @@
 }
 
 // SelectValue gets a value for a bazel select for the given axis and config.
-func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) Label {
+func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *Label {
 	axis.validateConfig(config)
 	switch axis.configurationType {
 	case noConfig:
-		return *la.Value
+		return la.Value
 	case arch, os, osArch, productVariables:
-		return *la.ConfigurableValues[axis][config]
+		return la.ConfigurableValues[axis][config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
 	}
@@ -324,7 +384,12 @@
 
 // HasConfigurableValues returns whether there are configurable values for this attribute.
 func (ba BoolAttribute) HasConfigurableValues() bool {
-	return len(ba.ConfigurableValues) > 0
+	for _, cfgToBools := range ba.ConfigurableValues {
+		if len(cfgToBools) > 0 {
+			return true
+		}
+	}
+	return false
 }
 
 // SetSelectValue sets value for the given axis/config.
@@ -343,6 +408,106 @@
 	}
 }
 
+// ToLabelListAttribute creates and returns a LabelListAttribute from this
+// bool attribute, where each bool in this attribute corresponds to a
+// label list value in the resultant attribute.
+func (ba *BoolAttribute) ToLabelListAttribute(falseVal LabelList, trueVal LabelList) (LabelListAttribute, error) {
+	getLabelList := func(boolPtr *bool) LabelList {
+		if boolPtr == nil {
+			return LabelList{nil, nil}
+		} else if *boolPtr {
+			return trueVal
+		} else {
+			return falseVal
+		}
+	}
+
+	mainVal := getLabelList(ba.Value)
+	if !ba.HasConfigurableValues() {
+		return MakeLabelListAttribute(mainVal), nil
+	}
+
+	result := LabelListAttribute{}
+	if err := ba.Collapse(); err != nil {
+		return result, err
+	}
+
+	for axis, configToBools := range ba.ConfigurableValues {
+		if len(configToBools) < 1 {
+			continue
+		}
+		for config, boolPtr := range configToBools {
+			val := getLabelList(&boolPtr)
+			if !val.Equals(mainVal) {
+				result.SetSelectValue(axis, config, val)
+			}
+		}
+		result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
+	}
+
+	return result, nil
+}
+
+// Collapse reduces the configurable axes of the boolean attribute to a single axis.
+// This is necessary for final writing to bp2build, as a configurable boolean
+// attribute can only be comprised by a single select.
+func (ba *BoolAttribute) Collapse() error {
+	axisTypes := ba.axisTypes()
+	_, containsOs := axisTypes[os]
+	_, containsArch := axisTypes[arch]
+	_, containsOsArch := axisTypes[osArch]
+	_, containsProductVariables := axisTypes[productVariables]
+	if containsProductVariables {
+		if containsOs || containsArch || containsOsArch {
+			return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
+		}
+	}
+	if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
+		// If a bool attribute has both os and arch configuration axes, the only
+		// way to successfully union their values is to increase the granularity
+		// of the configuration criteria to os_arch.
+		for osType, supportedArchs := range osToArchMap {
+			for _, supportedArch := range supportedArchs {
+				osArch := osArchString(osType, supportedArch)
+				if archOsVal := ba.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
+					// Do nothing, as the arch_os is explicitly defined already.
+				} else {
+					archVal := ba.SelectValue(ArchConfigurationAxis, supportedArch)
+					osVal := ba.SelectValue(OsConfigurationAxis, osType)
+					if osVal != nil && archVal != nil {
+						// In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
+						// runs after os mutator.
+						ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
+					} else if osVal != nil && archVal == nil {
+						ba.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
+					} else if osVal == nil && archVal != nil {
+						ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
+					}
+				}
+			}
+		}
+		// All os_arch values are now set. Clear os and arch axes.
+		delete(ba.ConfigurableValues, ArchConfigurationAxis)
+		delete(ba.ConfigurableValues, OsConfigurationAxis)
+		// Verify post-condition; this should never fail, provided no additional
+		// axes are introduced.
+		if len(ba.ConfigurableValues) > 1 {
+			panic(fmt.Errorf("error in collapsing attribute: %s", ba))
+		}
+	}
+	return nil
+}
+
+func (ba *BoolAttribute) axisTypes() map[configurationType]bool {
+	types := map[configurationType]bool{}
+	for k := range ba.ConfigurableValues {
+		if len(ba.ConfigurableValues[k]) > 0 {
+			types[k.configurationType] = true
+		}
+	}
+	return types
+}
+
 // SelectValue gets the value for the given axis/config.
 func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
 	axis.validateConfig(config)
@@ -550,7 +715,12 @@
 
 // HasConfigurableValues returns true if the attribute contains axis-specific label list values.
 func (lla LabelListAttribute) HasConfigurableValues() bool {
-	return len(lla.ConfigurableValues) > 0
+	for _, selectValues := range lla.ConfigurableValues {
+		if len(selectValues) > 0 {
+			return true
+		}
+	}
+	return false
 }
 
 // IsEmpty returns true if the attribute has no values under any configuration.
@@ -800,7 +970,12 @@
 
 // HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
 func (sla StringListAttribute) HasConfigurableValues() bool {
-	return len(sla.ConfigurableValues) > 0
+	for _, selectValues := range sla.ConfigurableValues {
+		if len(selectValues) > 0 {
+			return true
+		}
+	}
+	return false
 }
 
 // Append appends all values, including os and arch specific ones, from another
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index eaceea9..59a2389 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1369,6 +1369,94 @@
 	})
 }
 
+func TestCCLibraryNoLibCrtArchAndTargetVariant(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		filesystem: map[string]string{
+			"impl.cpp": "",
+		},
+		blueprint: soongCcLibraryPreamble + `
+cc_library {
+    name: "foo-lib",
+    srcs: ["impl.cpp"],
+    arch: {
+        arm: {
+            no_libcrt: true,
+        },
+        x86: {
+            no_libcrt: true,
+        },
+    },
+    target: {
+        darwin: {
+            no_libcrt: true,
+        }
+    },
+    include_build_directory: false,
+}
+`,
+		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+			"srcs": `["impl.cpp"]`,
+			"use_libcrt": `select({
+        "//build/bazel/platforms/os_arch:android_arm": False,
+        "//build/bazel/platforms/os_arch:android_x86": False,
+        "//build/bazel/platforms/os_arch:darwin_arm64": False,
+        "//build/bazel/platforms/os_arch:darwin_x86_64": False,
+        "//build/bazel/platforms/os_arch:linux_glibc_x86": False,
+        "//build/bazel/platforms/os_arch:linux_musl_x86": False,
+        "//build/bazel/platforms/os_arch:windows_x86": False,
+        "//conditions:default": None,
+    })`,
+		}),
+	})
+}
+
+func TestCCLibraryNoLibCrtArchAndTargetVariantConflict(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		filesystem: map[string]string{
+			"impl.cpp": "",
+		},
+		blueprint: soongCcLibraryPreamble + `
+cc_library {
+    name: "foo-lib",
+    srcs: ["impl.cpp"],
+    arch: {
+        arm: {
+            no_libcrt: true,
+        },
+        // This is expected to override the value for darwin_x86_64.
+        x86_64: {
+            no_libcrt: true,
+        },
+    },
+    target: {
+        darwin: {
+            no_libcrt: false,
+        }
+    },
+    include_build_directory: false,
+}
+`,
+		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+			"srcs": `["impl.cpp"]`,
+			"use_libcrt": `select({
+        "//build/bazel/platforms/os_arch:android_arm": False,
+        "//build/bazel/platforms/os_arch:android_x86_64": False,
+        "//build/bazel/platforms/os_arch:darwin_arm64": True,
+        "//build/bazel/platforms/os_arch:darwin_x86_64": False,
+        "//build/bazel/platforms/os_arch:linux_bionic_x86_64": False,
+        "//build/bazel/platforms/os_arch:linux_glibc_x86_64": False,
+        "//build/bazel/platforms/os_arch:linux_musl_x86_64": False,
+        "//build/bazel/platforms/os_arch:windows_x86_64": False,
+        "//conditions:default": None,
+    })`,
+		}),
+	})
+}
+
 func TestCcLibraryStrip(t *testing.T) {
 	expectedTargets := []string{}
 	expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{
@@ -2159,3 +2247,146 @@
 		},
 	})
 }
+
+func TestCcLibraryDisabledArchAndTarget(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		blueprint: soongCcProtoPreamble + `cc_library {
+	name: "foo",
+	srcs: ["foo.cpp"],
+	target: {
+		darwin: {
+			enabled: false,
+		},
+		windows: {
+			enabled: false,
+		},
+		linux_glibc_x86: {
+			enabled: false,
+		},
+	},
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
+			"srcs": `["foo.cpp"]`,
+			"target_compatible_with": `select({
+        "//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/os_arch:linux_glibc_x86": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/os_arch:windows_x86": ["@platforms//:incompatible"],
+        "//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+		}),
+	})
+}
+
+func TestCcLibraryDisabledArchAndTargetWithDefault(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		blueprint: soongCcProtoPreamble + `cc_library {
+	name: "foo",
+	srcs: ["foo.cpp"],
+  enabled: false,
+	target: {
+		darwin: {
+			enabled: true,
+		},
+		windows: {
+			enabled: false,
+		},
+		linux_glibc_x86: {
+			enabled: false,
+		},
+	},
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
+			"srcs": `["foo.cpp"]`,
+			"target_compatible_with": `select({
+        "//build/bazel/platforms/os_arch:darwin_arm64": [],
+        "//build/bazel/platforms/os_arch:darwin_x86_64": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    })`,
+		}),
+	})
+}
+
+func TestCcLibrarySharedDisabled(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		blueprint: soongCcProtoPreamble + `cc_library {
+	name: "foo",
+	srcs: ["foo.cpp"],
+	enabled: false,
+	shared: {
+		enabled: true,
+	},
+	target: {
+		android: {
+			shared: {
+				enabled: false,
+			},
+		}
+  },
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+			"srcs":                   `["foo.cpp"]`,
+			"target_compatible_with": `["@platforms//:incompatible"]`,
+		}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+			"srcs": `["foo.cpp"]`,
+			"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+		}),
+		},
+	})
+}
+
+func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:        "cc_library",
+		moduleTypeUnderTestFactory: cc.LibraryFactory,
+		blueprint: soongCcProtoPreamble + `cc_library {
+	name: "foo",
+	srcs: ["foo.cpp"],
+	shared: {
+		enabled: false
+	},
+	target: {
+		darwin: {
+			enabled: true,
+		},
+		windows: {
+			enabled: false,
+		},
+		linux_glibc_x86: {
+			shared: {
+				enabled: true,
+			},
+		},
+	},
+	include_build_directory: false,
+}`,
+		expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+			"srcs": `["foo.cpp"]`,
+			"target_compatible_with": `select({
+        "//build/bazel/platforms/os:windows": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+		}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+			"srcs": `["foo.cpp"]`,
+			"target_compatible_with": `select({
+        "//build/bazel/platforms/os_arch:darwin_arm64": [],
+        "//build/bazel/platforms/os_arch:darwin_x86_64": [],
+        "//build/bazel/platforms/os_arch:linux_glibc_x86": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    })`,
+		}),
+		}})
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index c953259..dfbb265 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -1,10 +1,11 @@
 package bp2build
 
 import (
-	"android/soong/android"
-	"android/soong/bazel"
 	"fmt"
 	"reflect"
+
+	"android/soong/android"
+	"android/soong/bazel"
 )
 
 // Configurability support for bp2build.
@@ -89,13 +90,15 @@
 		}
 		archSelects := map[string]reflect.Value{}
 		defaultVal := configToLabels[bazel.ConditionsDefaultConfigKey]
+		// Skip empty list values unless ether EmitEmptyList is true, or these values differ from the default.
+		emitEmptyList := list.EmitEmptyList || len(defaultVal.Includes) > 0
 		for config, labels := range configToLabels {
 			// Omit any entries in the map which match the default value, for brevity.
 			if config != bazel.ConditionsDefaultConfigKey && labels.Equals(defaultVal) {
 				continue
 			}
 			selectKey := axis.SelectKey(config)
-			if use, value := labelListSelectValue(selectKey, labels, list.EmitEmptyList); use {
+			if use, value := labelListSelectValue(selectKey, labels, emitEmptyList); use {
 				archSelects[selectKey] = value
 			}
 		}
@@ -144,9 +147,15 @@
 			shouldPrintDefault = true
 		}
 	case bazel.LabelAttribute:
+		if err := list.Collapse(); err != nil {
+			return "", err
+		}
 		value, configurableAttrs = getLabelValue(list)
 		defaultSelectValue = &bazelNone
 	case bazel.BoolAttribute:
+		if err := list.Collapse(); err != nil {
+			return "", err
+		}
 		value, configurableAttrs = getBoolValue(list)
 		defaultSelectValue = &bazelNone
 	default:
@@ -204,11 +213,12 @@
 			continue
 		}
 		value := selectMap[selectKey]
-		if isZero(value) && !emitZeroValues {
-			// Ignore zero values to not generate empty lists.
+		if isZero(value) && !emitZeroValues && isZero(selectMap[bazel.ConditionsDefaultSelectKey]) {
+			// Ignore zero values to not generate empty lists. However, always note zero values if
+			// the default value is non-zero.
 			continue
 		}
-		s, err := prettyPrintSelectEntry(value, selectKey, indent, emitZeroValues)
+		s, err := prettyPrintSelectEntry(value, selectKey, indent, true)
 		if err != nil {
 			return "", err
 		}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 5065893..3a5d5bb 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -86,3 +86,45 @@
 				"sub_dir": `"tz"`,
 			})}})
 }
+
+func TestPrebuiltEtcArchAndTargetVariant(t *testing.T) {
+	runPrebuiltEtcTestCase(t, bp2buildTestCase{
+		description: "prebuilt_etc - arch variant",
+		filesystem:  map[string]string{},
+		blueprint: `
+prebuilt_etc {
+    name: "apex_tz_version",
+    src: "version/tz_version",
+    filename: "tz_version",
+    sub_dir: "tz",
+    installable: false,
+    arch: {
+      arm: {
+        src: "arm",
+      },
+      arm64: {
+        src: "darwin_or_arm64",
+      },
+    },
+    target: {
+      darwin: {
+        src: "darwin_or_arm64",
+      }
+    },
+}
+`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+				"filename":    `"tz_version"`,
+				"installable": `False`,
+				"src": `select({
+        "//build/bazel/platforms/os_arch:android_arm": "arm",
+        "//build/bazel/platforms/os_arch:android_arm64": "darwin_or_arm64",
+        "//build/bazel/platforms/os_arch:darwin_arm64": "darwin_or_arm64",
+        "//build/bazel/platforms/os_arch:darwin_x86_64": "darwin_or_arm64",
+        "//build/bazel/platforms/os_arch:linux_bionic_arm64": "darwin_or_arm64",
+        "//conditions:default": "version/tz_version",
+    })`,
+				"sub_dir": `"tz"`,
+			})}})
+}
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index f6d2a20..ac89087 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -73,3 +73,20 @@
 			})},
 	})
 }
+
+func TestShBinaryDefaults(t *testing.T) {
+	runShBinaryTestCase(t, bp2buildTestCase{
+		description:                "sh_binary test",
+		moduleTypeUnderTest:        "sh_binary",
+		moduleTypeUnderTestFactory: sh.ShBinaryFactory,
+		blueprint: `sh_binary {
+    name: "foo",
+    src: "foo.sh",
+    bazel_module: { bp2build_available: true },
+}`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("sh_binary", "foo", attrNameToString{
+				"srcs": `["foo.sh"]`,
+			})},
+	})
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index fa1a84d..9f0c86c 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -83,9 +83,9 @@
 		// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
 		"-isystem bionic/libc/kernel/uapi/asm-arm64",
 		"-isystem bionic/libc/kernel/android/uapi",
+		"-I       frameworks/libs/net/common/native/bpf_headers/include/bpf",
 		// TODO(b/149785767): only give access to specific file with AID_* constants
 		"-I       system/core/libcutils/include",
-		"-I       system/bpf/progs/include",
 		"-I " + ctx.ModuleDir(),
 	}
 
diff --git a/cc/Android.bp b/cc/Android.bp
index 07aa7cb..0bf0045 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -19,10 +19,11 @@
         "soong-tradefed",
     ],
     srcs: [
+        "afdo.go",
         "androidmk.go",
         "api_level.go",
-        "builder.go",
         "bp2build.go",
+        "builder.go",
         "cc.go",
         "ccdeps.go",
         "check.go",
diff --git a/cc/afdo.go b/cc/afdo.go
new file mode 100644
index 0000000..022f283
--- /dev/null
+++ b/cc/afdo.go
@@ -0,0 +1,194 @@
+// Copyright 2021 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 cc
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+var (
+	globalAfdoProfileProjects = []string{
+		"vendor/google_data/pgo_profile/sampling/",
+		"toolchain/pgo-profiles/sampling/",
+	}
+)
+
+var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
+
+const afdoCFlagsFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
+
+func getAfdoProfileProjects(config android.DeviceConfig) []string {
+	return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
+		return append(globalAfdoProfileProjects, config.AfdoAdditionalProfileDirs()...)
+	})
+}
+
+func recordMissingAfdoProfileFile(ctx BaseModuleContext, missing string) {
+	getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
+}
+
+type AfdoProperties struct {
+	Afdo bool
+
+	AfdoTarget *string  `blueprint:"mutated"`
+	AfdoDeps   []string `blueprint:"mutated"`
+}
+
+type afdo struct {
+	Properties AfdoProperties
+}
+
+func (afdo *afdo) props() []interface{} {
+	return []interface{}{&afdo.Properties}
+}
+
+func (afdo *afdo) AfdoEnabled() bool {
+	return afdo != nil && afdo.Properties.Afdo && afdo.Properties.AfdoTarget != nil
+}
+
+// Get list of profile file names, ordered by level of specialisation. For example:
+//   1. libfoo_arm64.afdo
+//   2. libfoo.afdo
+// Add more specialisation as needed.
+func getProfileFiles(ctx BaseModuleContext, moduleName string) []string {
+	var files []string
+	files = append(files, moduleName+"_"+ctx.Arch().ArchType.String()+".afdo")
+	files = append(files, moduleName+".afdo")
+	return files
+}
+
+func (props *AfdoProperties) getAfdoProfileFile(ctx BaseModuleContext, module string) android.OptionalPath {
+	// Test if the profile_file is present in any of the Afdo profile projects
+	for _, profileFile := range getProfileFiles(ctx, module) {
+		for _, profileProject := range getAfdoProfileProjects(ctx.DeviceConfig()) {
+			path := android.ExistentPathForSource(ctx, profileProject, profileFile)
+			if path.Valid() {
+				return path
+			}
+		}
+	}
+
+	// Record that this module's profile file is absent
+	missing := ctx.ModuleDir() + ":" + module
+	recordMissingAfdoProfileFile(ctx, missing)
+
+	return android.OptionalPathForPath(nil)
+}
+
+func (afdo *afdo) begin(ctx BaseModuleContext) {
+	if afdo.Properties.Afdo && !ctx.static() && !ctx.Host() {
+		module := ctx.ModuleName()
+		if afdo.Properties.getAfdoProfileFile(ctx, module).Valid() {
+			afdo.Properties.AfdoTarget = proptools.StringPtr(module)
+		}
+	}
+}
+
+func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
+	if profile := afdo.Properties.AfdoTarget; profile != nil {
+		if profileFile := afdo.Properties.getAfdoProfileFile(ctx, *profile); profileFile.Valid() {
+			profileFilePath := profileFile.Path()
+
+			profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, profileFile)
+			flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlag)
+			flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlag)
+			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-no-warn-sample-unused=true")
+
+			// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+			// if profileFile gets updated
+			flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
+			flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
+		}
+	}
+
+	return flags
+}
+
+// Propagate afdo requirements down from binaries
+func afdoDepsMutator(mctx android.TopDownMutatorContext) {
+	if m, ok := mctx.Module().(*Module); ok && m.afdo.AfdoEnabled() {
+		afdoTarget := *m.afdo.Properties.AfdoTarget
+		mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+			tag := mctx.OtherModuleDependencyTag(dep)
+			libTag, isLibTag := tag.(libraryDependencyTag)
+
+			// Do not recurse down non-static dependencies
+			if isLibTag {
+				if !libTag.static() {
+					return false
+				}
+			} else {
+				if tag != objDepTag && tag != reuseObjTag {
+					return false
+				}
+			}
+
+			if dep, ok := dep.(*Module); ok {
+				dep.afdo.Properties.AfdoDeps = append(dep.afdo.Properties.AfdoDeps, afdoTarget)
+			}
+
+			return true
+		})
+	}
+}
+
+// Create afdo variants for modules that need them
+func afdoMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
+		if m.afdo.AfdoEnabled() && !m.static() {
+			afdoTarget := *m.afdo.Properties.AfdoTarget
+			mctx.SetDependencyVariation(encodeTarget(afdoTarget))
+		}
+
+		variationNames := []string{""}
+		afdoDeps := android.FirstUniqueStrings(m.afdo.Properties.AfdoDeps)
+		for _, dep := range afdoDeps {
+			variationNames = append(variationNames, encodeTarget(dep))
+		}
+		if len(variationNames) > 1 {
+			modules := mctx.CreateVariations(variationNames...)
+			for i, name := range variationNames {
+				if name == "" {
+					continue
+				}
+				variation := modules[i].(*Module)
+				variation.Properties.PreventInstall = true
+				variation.Properties.HideFromMake = true
+				variation.afdo.Properties.AfdoTarget = proptools.StringPtr(decodeTarget(name))
+			}
+		}
+	}
+}
+
+// Encode target name to variation name.
+func encodeTarget(target string) string {
+	if target == "" {
+		return ""
+	}
+	return "afdo-" + target
+}
+
+// Decode target name from variation name.
+func decodeTarget(variation string) string {
+	if variation == "" {
+		return ""
+	}
+	return strings.TrimPrefix(variation, "afdo-")
+}
diff --git a/cc/binary.go b/cc/binary.go
index 50175d9..b59e762 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -558,13 +558,6 @@
 }
 
 func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
-	var compatibleWith bazel.StringListAttribute
-	if typ == "cc_binary_host" {
-		//incompatible with android OS
-		compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, []string{"@platforms//:incompatible"})
-		compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, bazel.ConditionsDefaultConfigKey, []string{})
-	}
-
 	baseAttrs := bp2BuildParseBaseProps(ctx, m)
 	binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
 
@@ -610,16 +603,22 @@
 			None:                         baseAttrs.stripNone,
 		},
 
-		Target_compatible_with: compatibleWith,
-		Features:               baseAttrs.features,
+		Features: baseAttrs.features,
 	}
 
-	ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
+	var enabledProperty bazel.BoolAttribute
+	if typ == "cc_binary_host" {
+		falseVal := false
+		enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, &falseVal)
+	}
+
+	ctx.CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties{
 		Rule_class:        "cc_binary",
 		Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
 	},
 		android.CommonAttributes{Name: m.Name()},
-		attrs)
+		attrs,
+		enabledProperty)
 }
 
 // binaryAttributes contains Bazel attributes corresponding to a cc binary
@@ -655,6 +654,4 @@
 	Strip stripAttributes
 
 	Features bazel.StringListAttribute
-
-	Target_compatible_with bazel.StringListAttribute
 }
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 2119ee4..e4762a0 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -57,6 +57,8 @@
 	Implementation_whole_archive_deps bazel.LabelListAttribute
 
 	System_dynamic_deps bazel.LabelListAttribute
+
+	Enabled bazel.BoolAttribute
 }
 
 func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
@@ -175,6 +177,7 @@
 		attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
 
 		attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
+		attrs.Enabled.SetSelectValue(axis, config, props.Enabled)
 	}
 	// system_dynamic_deps distinguishes between nil/empty list behavior:
 	//    nil -> use default values
diff --git a/cc/cc.go b/cc/cc.go
index 22baf30..a4b7c9c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -64,6 +64,9 @@
 
 		ctx.BottomUp("coverage", coverageMutator).Parallel()
 
+		ctx.TopDown("afdo_deps", afdoDepsMutator)
+		ctx.BottomUp("afdo", afdoMutator).Parallel()
+
 		ctx.TopDown("lto_deps", ltoDepsMutator)
 		ctx.BottomUp("lto", ltoMutator).Parallel()
 
@@ -810,6 +813,7 @@
 	sabi     *sabi
 	vndkdep  *vndkdep
 	lto      *lto
+	afdo     *afdo
 	pgo      *pgo
 
 	library libraryInterface
@@ -1143,6 +1147,9 @@
 	if c.lto != nil {
 		c.AddProperties(c.lto.props()...)
 	}
+	if c.afdo != nil {
+		c.AddProperties(c.afdo.props()...)
+	}
 	if c.pgo != nil {
 		c.AddProperties(c.pgo.props()...)
 	}
@@ -1620,6 +1627,7 @@
 	module.sabi = &sabi{}
 	module.vndkdep = &vndkdep{}
 	module.lto = &lto{}
+	module.afdo = &afdo{}
 	module.pgo = &pgo{}
 	return module
 }
@@ -1815,6 +1823,9 @@
 	if c.lto != nil {
 		flags = c.lto.flags(ctx, flags)
 	}
+	if c.afdo != nil {
+		flags = c.afdo.flags(ctx, flags)
+	}
 	if c.pgo != nil {
 		flags = c.pgo.flags(ctx, flags)
 	}
@@ -1942,6 +1953,9 @@
 	if c.lto != nil {
 		c.lto.begin(ctx)
 	}
+	if c.afdo != nil {
+		c.afdo.begin(ctx)
+	}
 	if c.pgo != nil {
 		c.pgo.begin(ctx)
 	}
@@ -3461,8 +3475,15 @@
 			objectBp2Build(ctx, c)
 		}
 	} else if c.CcLibrary() {
-		static := c.BuildStaticVariant()
-		shared := c.BuildSharedVariant()
+		static := false
+		shared := false
+		if library, ok := c.linker.(*libraryDecorator); ok {
+			static = library.MutatedProperties.BuildStatic
+			shared = library.MutatedProperties.BuildShared
+		} else if library, ok := c.linker.(*prebuiltLibraryLinker); ok {
+			static = library.MutatedProperties.BuildStatic
+			shared = library.MutatedProperties.BuildShared
+		}
 
 		if static && shared {
 			if !prebuilt {
@@ -3534,6 +3555,7 @@
 		&SAbiProperties{},
 		&VndkProperties{},
 		&LTOProperties{},
+		&AfdoProperties{},
 		&PgoProperties{},
 		&android.ProtoProperties{},
 		// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
diff --git a/cc/cc_test.go b/cc/cc_test.go
index bcc6fcd..31d91b6 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3980,9 +3980,9 @@
 	conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"}
 	cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
 
-	cflags := []string{"-Wall", "-Werror"}
-	cstd := []string{"-std=gnu99"}
-	cppstd := []string{"-std=gnu++17", "-fno-rtti"}
+	cflags := []string{"-Wall", "-Werror", "-std=candcpp"}
+	cstd := []string{"-std=gnu99", "-std=conly"}
+	cppstd := []string{"-std=gnu++17", "-std=cpp", "-fno-rtti"}
 
 	lastIncludes := []string{
 		"out/soong/ndk/sysroot/usr/include",
@@ -4025,6 +4025,9 @@
 		cc_library {
 			name: "libfoo",
 			srcs: ["%s"],
+			cflags: ["-std=candcpp"],
+			conlyflags: ["-std=conly"],
+			cppflags: ["-std=cpp"],
 			local_include_dirs: ["local_include_dirs"],
 			export_include_dirs: ["export_include_dirs"],
 			export_system_include_dirs: ["export_system_include_dirs"],
diff --git a/cc/library.go b/cc/library.go
index 216c124..5720944 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -392,8 +392,12 @@
 		Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl",
 	}
 
-	ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs)
-	ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs)
+	ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
+		android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"},
+		staticTargetAttrs, staticAttrs.Enabled)
+	ctx.CreateBazelTargetModuleWithRestrictions(sharedProps,
+		android.CommonAttributes{Name: m.Name()},
+		sharedTargetAttrs, sharedAttrs.Enabled)
 }
 
 // cc_library creates both static and/or shared libraries for a device and/or
diff --git a/cc/object.go b/cc/object.go
index bd43e36..24f6ed4 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -155,7 +155,8 @@
 		for config, props := range configToProps {
 			if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
 				if objectLinkerProps.Linker_script != nil {
-					linkerScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script))
+					label := android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script)
+					linkerScript.SetSelectValue(axis, config, label)
 				}
 				deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs))
 				systemSharedLibs := objectLinkerProps.System_shared_libs
diff --git a/cc/sanitize.go b/cc/sanitize.go
index d7b1ade..6c68822 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -539,11 +539,6 @@
 	if Bool(s.Hwaddress) {
 		s.Address = nil
 		s.Thread = nil
-		// Disable ubsan diagnosic as a workaround for a compiler bug.
-		// TODO(b/191808836): re-enable.
-		s.Diag.Undefined = nil
-		s.Diag.Integer_overflow = nil
-		s.Diag.Misc_undefined = nil
 	}
 
 	// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index c2866ab..83de65f 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -681,7 +681,8 @@
 				continue
 			}
 			if props.Src != nil {
-				srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *props.Src))
+				label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src)
+				srcLabelAttribute.SetSelectValue(axis, config, label)
 			}
 		}
 	}
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
index 149cbb7..83c088c 100644
--- a/java/dexpreopt_check.go
+++ b/java/dexpreopt_check.go
@@ -72,8 +72,7 @@
 		return
 	}
 
-	// TODO(b/203198541): Check all system server jars.
-	systemServerJars := global.AllSystemServerClasspathJars(ctx)
+	systemServerJars := global.AllSystemServerJars(ctx)
 	for _, jar := range systemServerJars.CopyOfJars() {
 		dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, jar)
 		odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType)
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 024311e..2a80e56 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1629,6 +1629,13 @@
 		return
 	}
 	if p, ok := maybeTrim(annotation, "include_top"); ok {
+		// Don't allow duplicate include tops, because then we will generate
+		// invalid starlark code. (duplicate keys in the _entry dictionary)
+		for _, top := range ctx.includeTops {
+			if top == p {
+				return
+			}
+		}
 		ctx.includeTops = append(ctx.includeTops, p)
 		return
 	}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index b06ae88..1ba273b 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1049,7 +1049,7 @@
   }.get("vendor/%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
-    rblf.mkerror("cannot")
+    rblf.mkerror("product.mk", "Cannot find %s" % ("vendor/%s/cfg.mk" % g["MY_PATH"]))
   rblf.inherit(handle, _varmod, _varmod_init)
 `,
 	},
@@ -1073,7 +1073,41 @@
   }.get("%s/cfg.mk" % g["MY_PATH"])
   (_varmod, _varmod_init) = _entry if _entry else (None, None)
   if not _varmod_init:
-    rblf.mkerror("cannot")
+    rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
+  rblf.inherit(handle, _varmod, _varmod_init)
+`,
+	},
+	{
+		desc:   "Dynamic inherit with duplicated hint",
+		mkname: "product.mk",
+		in: `
+MY_PATH:=foo
+#RBC# include_top vendor/foo1
+$(call inherit-product,$(MY_PATH)/cfg.mk)
+#RBC# include_top vendor/foo1
+$(call inherit-product,$(MY_PATH)/cfg.mk)
+`,
+		expected: `load("//build/make/core:product_config.rbc", "rblf")
+load("//vendor/foo1:cfg.star|init", _cfg_init = "init")
+
+def init(g, handle):
+  cfg = rblf.cfg(handle)
+  g["MY_PATH"] = "foo"
+  #RBC# include_top vendor/foo1
+  _entry = {
+    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+  }.get("%s/cfg.mk" % g["MY_PATH"])
+  (_varmod, _varmod_init) = _entry if _entry else (None, None)
+  if not _varmod_init:
+    rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
+  rblf.inherit(handle, _varmod, _varmod_init)
+  #RBC# include_top vendor/foo1
+  _entry = {
+    "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+  }.get("%s/cfg.mk" % g["MY_PATH"])
+  (_varmod, _varmod_init) = _entry if _entry else (None, None)
+  if not _varmod_init:
+    rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
   rblf.inherit(handle, _varmod, _varmod_init)
 `,
 	},
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index d38299d..ebc57b2 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -110,7 +110,9 @@
 		gctx.writef("if not %s:", i.entryName())
 		gctx.indentLevel++
 		gctx.newLine()
-		gctx.write(`rblf.mkerror("cannot")`)
+		gctx.write(`rblf.mkerror("`, gctx.starScript.mkFile, `", "Cannot find %s" % (`)
+		i.path.emit(gctx)
+		gctx.write("))")
 		gctx.indentLevel--
 	}
 }
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index e1df8ac..b1d1bb2 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -511,8 +511,8 @@
 
 type bazelShBinaryAttributes struct {
 	Srcs     bazel.LabelListAttribute
-	Filename string
-	Sub_dir  string
+	Filename *string
+	Sub_dir  *string
 	// Bazel also supports the attributes below, but (so far) these are not required for Bionic
 	// deps
 	// data
@@ -538,14 +538,14 @@
 	srcs := bazel.MakeLabelListAttribute(
 		android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
 
-	var filename string
+	var filename *string
 	if m.properties.Filename != nil {
-		filename = *m.properties.Filename
+		filename = m.properties.Filename
 	}
 
-	var subDir string
+	var subDir *string
 	if m.properties.Sub_dir != nil {
-		subDir = *m.properties.Sub_dir
+		subDir = m.properties.Sub_dir
 	}
 
 	attrs := &bazelShBinaryAttributes{