Merge "Add --bazel-mode and --bazel-mode-dev"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 60b3503..fc01703 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -46,6 +46,7 @@
 		"bionic":                                Bp2BuildDefaultTrueRecursively,
 		"bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
 
+		"build/bazel/examples/aidl":                   Bp2BuildDefaultTrueRecursively,
 		"build/bazel/examples/apex/minimal":           Bp2BuildDefaultTrueRecursively,
 		"build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
 		"build/bazel/examples/python":                 Bp2BuildDefaultTrueRecursively,
@@ -137,6 +138,7 @@
 		"external/libjpeg-turbo":                 Bp2BuildDefaultTrueRecursively,
 		"external/libmpeg2":                      Bp2BuildDefaultTrueRecursively,
 		"external/libpng":                        Bp2BuildDefaultTrueRecursively,
+		"external/libyuv":                        Bp2BuildDefaultTrueRecursively,
 		"external/lz4/lib":                       Bp2BuildDefaultTrue,
 		"external/lzma/C":                        Bp2BuildDefaultTrueRecursively,
 		"external/mdnsresponder":                 Bp2BuildDefaultTrueRecursively,
@@ -148,6 +150,7 @@
 		"external/scudo":                         Bp2BuildDefaultTrueRecursively,
 		"external/selinux/libselinux":            Bp2BuildDefaultTrueRecursively,
 		"external/selinux/libsepol":              Bp2BuildDefaultTrueRecursively,
+		"external/speex":                         Bp2BuildDefaultTrueRecursively,
 		"external/toybox":                        Bp2BuildDefaultTrueRecursively,
 		"external/zlib":                          Bp2BuildDefaultTrueRecursively,
 		"external/zopfli":                        Bp2BuildDefaultTrueRecursively,
@@ -157,6 +160,7 @@
 		"frameworks/av/media/liberror":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
 		"frameworks/base/media/tests/MediaDump":              Bp2BuildDefaultTrue,
+		"frameworks/base/services/tests/servicestests/aidl":  Bp2BuildDefaultTrue,
 		"frameworks/base/startop/apps/test":                  Bp2BuildDefaultTrue,
 		"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
@@ -225,6 +229,7 @@
 		"system/libziparchive":                                   Bp2BuildDefaultTrueRecursively,
 		"system/logging/liblog":                                  Bp2BuildDefaultTrueRecursively,
 		"system/media/audio":                                     Bp2BuildDefaultTrueRecursively,
+		"system/media/audio_utils":                               Bp2BuildDefaultTrueRecursively,
 		"system/memory/libion":                                   Bp2BuildDefaultTrueRecursively,
 		"system/memory/libmemunreachable":                        Bp2BuildDefaultTrueRecursively,
 		"system/sepolicy/apex":                                   Bp2BuildDefaultTrueRecursively,
@@ -248,6 +253,7 @@
 		"build/bazel":/* recursive = */ false,
 		"build/bazel/ci/dist":/* recursive = */ false,
 		"build/bazel/examples/android_app":/* recursive = */ true,
+		"build/bazel/examples/cc":/* recursive = */ true,
 		"build/bazel/examples/java":/* recursive = */ true,
 		"build/bazel/examples/partitions":/* recursive = */ true,
 		"build/bazel/bazel_skylib":/* recursive = */ true,
@@ -306,7 +312,8 @@
 		"libandroid_runtime_lazy",
 		"libandroid_runtime_vm_headers",
 		"libaudioclient_aidl_conversion_util",
-		"libaudioutils_fixedfft",
+		"libbinder",
+		"libbinder_device_interface_sources",
 		"libbinder_aidl",
 		"libbinder_headers",
 		"libbinder_headers_platform_shared",
@@ -408,6 +415,7 @@
 		"linker_config",
 		"java_import",
 		"java_import_host",
+		"aidl_interface_headers",
 	}
 
 	Bp2buildModuleDoNotConvertList = []string{
@@ -419,7 +427,6 @@
 		"linker",                 // TODO(b/228316882): cc_binary uses link_crt
 		"libdebuggerd",           // TODO(b/228314770): support product variable-specific header_libs
 		"versioner",              // TODO(b/228313961):  depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
-		"libspeexresampler",      // TODO(b/231995978): Filter out unknown cflags
 		"libvpx",                 // TODO(b/240756936): Arm neon variant not supported
 		"art_libartbase_headers", // TODO(b/236268577): Header libraries do not support export_shared_libs_headers
 		"apexer_test",            // Requires aapt2
@@ -524,6 +531,24 @@
 
 		// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
 		"toybox-static",
+
+		// Do not convert the following modules because of duplicate labels checking in Bazel.
+		// See b/241283350. They should be removed from this list once the bug is fixed.
+		"libartpalette",
+		"libartbase",
+		"libdexfile",
+		"libartbased",
+		"libdexfile_static",
+		"libartbase-testing",
+		"libartbased-testing",
+		"libdexfile_support",
+		"libunwindstack",
+		"libunwindstack_local",
+		"libfdtrack",
+		"libc_malloc_debug",
+		"libutilscallstack",
+		"libunwindstack_utils",
+		"unwind_for_offline",
 	}
 
 	Bp2buildCcLibraryStaticOnlyList = []string{}
diff --git a/android/filegroup.go b/android/filegroup.go
index 7d39238..e609f63 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"regexp"
 	"strings"
 
 	"android/soong/bazel"
@@ -37,6 +38,34 @@
 	return ctx.OtherModuleType(m) == "filegroup"
 }
 
+var (
+	// ignoring case, checks for proto or protos as an independent word in the name, whether at the
+	// beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match
+	filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)")
+	filegroupLikelyAidlPattern  = regexp.MustCompile("(?i)(^|[^a-z])aidl([^a-z]|$)")
+
+	ProtoSrcLabelPartition = bazel.LabelPartition{
+		Extensions:  []string{".proto"},
+		LabelMapper: isFilegroupWithPattern(filegroupLikelyProtoPattern),
+	}
+	AidlSrcLabelPartition = bazel.LabelPartition{
+		Extensions:  []string{".aidl"},
+		LabelMapper: isFilegroupWithPattern(filegroupLikelyAidlPattern),
+	}
+)
+
+func isFilegroupWithPattern(pattern *regexp.Regexp) bazel.LabelMapper {
+	return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+		m, exists := ctx.ModuleFromName(label.OriginalModuleName)
+		labelStr := label.Label
+		if !exists || !IsFilegroup(ctx, m) {
+			return labelStr, false
+		}
+		likelyMatched := pattern.MatchString(label.OriginalModuleName)
+		return labelStr, likelyMatched
+	}
+}
+
 // https://docs.bazel.build/versions/master/be/general.html#filegroup
 type bazelFilegroupAttributes struct {
 	Srcs bazel.LabelListAttribute
@@ -232,3 +261,16 @@
 		return fg.GetBazelLabel(ctx, fg)
 	}
 }
+
+// Given a name in srcs prop, check to see if the name references a filegroup
+// and the filegroup is converted to aidl_library
+func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool {
+	if module, ok := ctx.ModuleFromName(name); ok {
+		if IsFilegroup(ctx, module) {
+			if fg, ok := module.(Bp2buildAidlLibrary); ok {
+				return fg.ShouldConvertToAidlLibrary(ctx)
+			}
+		}
+	}
+	return false
+}
diff --git a/android/fixture.go b/android/fixture.go
index f718935..f33e718 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -642,6 +642,20 @@
 	NinjaDeps []string
 }
 
+type TestPathContext struct {
+	*TestResult
+}
+
+var _ PathContext = &TestPathContext{}
+
+func (t *TestPathContext) Config() Config {
+	return t.TestResult.Config
+}
+
+func (t *TestPathContext) AddNinjaFileDeps(deps ...string) {
+	panic("unimplemented")
+}
+
 func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
 	config := TestConfig(buildDir, nil, "", nil)
 	ctx := NewTestContext(config)
diff --git a/android/paths.go b/android/paths.go
index 74d9f13..1f69125 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1978,6 +1978,18 @@
 	return testPath{basePath{path: p, rel: p}}
 }
 
+func PathForTestingWithRel(path, rel string) Path {
+	p, err := validateSafePath(path, rel)
+	if err != nil {
+		panic(err)
+	}
+	r, err := validatePath(rel)
+	if err != nil {
+		panic(err)
+	}
+	return testPath{basePath{path: p, rel: r}}
+}
+
 // PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests.
 func PathsForTesting(strs ...string) Paths {
 	p := make(Paths, len(strs))
diff --git a/android/proto.go b/android/proto.go
index c3759f8..8ad16a6 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -16,7 +16,6 @@
 
 import (
 	"android/soong/bazel"
-	"regexp"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -27,14 +26,6 @@
 	canonicalPathFromRootDefault = true
 )
 
-var (
-	// ignoring case, checks for proto or protos as an independent word in the name, whether at the
-	// beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match
-	filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)")
-
-	ProtoSrcLabelPartition = bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup}
-)
-
 // TODO(ccross): protos are often used to communicate between multiple modules.  If the only
 // way to convert a proto to source is to reference it as a source file, and external modules cannot
 // reference source files in other modules, then every module that owns a proto file will need to
@@ -213,13 +204,3 @@
 
 	return info, true
 }
-
-func isProtoFilegroup(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
-	m, exists := ctx.ModuleFromName(label.OriginalModuleName)
-	labelStr := label.Label
-	if !exists || !IsFilegroup(ctx, m) {
-		return labelStr, false
-	}
-	likelyProtos := filegroupLikelyProtoPattern.MatchString(label.OriginalModuleName)
-	return labelStr, likelyProtos
-}
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 0ab49eb..d9b0a12 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -27,7 +27,7 @@
 	archX86_64 = "x86_64"
 
 	// OsType names in arch.go
-	osAndroid     = "android"
+	OsAndroid     = "android"
 	osDarwin      = "darwin"
 	osLinux       = "linux_glibc"
 	osLinuxMusl   = "linux_musl"
@@ -64,6 +64,9 @@
 	ConditionsDefaultSelectKey = "//conditions:default"
 
 	productVariableBazelPackage = "//build/bazel/product_variables"
+
+	AndroidAndInApex  = "android-in_apex"
+	AndroidAndNonApex = "android-non_apex"
 )
 
 var (
@@ -85,7 +88,7 @@
 	// A map of target operating systems to the Bazel label of the
 	// constraint_value for the @platforms//os:os constraint_setting
 	platformOsMap = map[string]string{
-		osAndroid:                  "//build/bazel/platforms/os:android",
+		OsAndroid:                  "//build/bazel/platforms/os:android",
 		osDarwin:                   "//build/bazel/platforms/os:darwin",
 		osLinux:                    "//build/bazel/platforms/os:linux",
 		osLinuxMusl:                "//build/bazel/platforms/os:linux_musl",
@@ -120,7 +123,7 @@
 	// 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},
+		OsAndroid:     {archArm, archArm64, archX86, archX86_64},
 		osLinux:       {archX86, archX86_64},
 		osLinuxMusl:   {archX86, archX86_64},
 		osDarwin:      {archArm64, archX86_64},
@@ -128,6 +131,12 @@
 		// TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
 		osWindows: {archX86, archX86_64},
 	}
+
+	osAndInApexMap = map[string]string{
+		AndroidAndInApex:           "//build/bazel/rules/apex:android-in_apex",
+		AndroidAndNonApex:          "//build/bazel/rules/apex:android-non_apex",
+		ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
+	}
 )
 
 // basic configuration types
@@ -139,6 +148,7 @@
 	os
 	osArch
 	productVariables
+	osAndInApex
 )
 
 func osArchString(os string, arch string) string {
@@ -152,6 +162,7 @@
 		os:               "os",
 		osArch:           "arch_os",
 		productVariables: "product_variables",
+		osAndInApex:      "os_in_apex",
 	}[ct]
 }
 
@@ -175,6 +186,10 @@
 		}
 	case productVariables:
 		// do nothing
+	case osAndInApex:
+		if _, ok := osAndInApexMap[config]; !ok {
+			panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
+		}
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
 	}
@@ -198,6 +213,8 @@
 			return ConditionsDefaultSelectKey
 		}
 		return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
+	case osAndInApex:
+		return osAndInApexMap[config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
 	}
@@ -212,6 +229,8 @@
 	OsConfigurationAxis = ConfigurationAxis{configurationType: os}
 	// An axis for arch+os-specific configurations
 	OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
+	// An axis for os+in_apex-specific configurations
+	OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
 )
 
 // ProductVariableConfigurationAxis returns an axis for the given product variable
diff --git a/bazel/properties.go b/bazel/properties.go
index 963e27b..13e36b5 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -119,7 +119,7 @@
 	return dirs
 }
 
-// Add inserts the label Label at the end of the LabelList.
+// Add inserts the label Label at the end of the LabelList.Includes.
 func (ll *LabelList) Add(label *Label) {
 	if label == nil {
 		return
@@ -127,6 +127,14 @@
 	ll.Includes = append(ll.Includes, *label)
 }
 
+// AddExclude inserts the label Label at the end of the LabelList.Excludes.
+func (ll *LabelList) AddExclude(label *Label) {
+	if label == nil {
+		return
+	}
+	ll.Excludes = append(ll.Excludes, *label)
+}
+
 // Append appends the fields of other labelList to the corresponding fields of ll.
 func (ll *LabelList) Append(other LabelList) {
 	if len(ll.Includes) > 0 || len(other.Includes) > 0 {
@@ -137,6 +145,30 @@
 	}
 }
 
+// Partition splits a LabelList into two LabelLists depending on the return value
+// of the predicate.
+// This function preserves the Includes and Excludes, but it does not provide
+// that information to the partition function.
+func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) {
+	predicated := LabelList{}
+	unpredicated := LabelList{}
+	for _, include := range ll.Includes {
+		if predicate(include) {
+			predicated.Add(&include)
+		} else {
+			unpredicated.Add(&include)
+		}
+	}
+	for _, exclude := range ll.Excludes {
+		if predicate(exclude) {
+			predicated.AddExclude(&exclude)
+		} else {
+			unpredicated.AddExclude(&exclude)
+		}
+	}
+	return predicated, unpredicated
+}
+
 // UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
 // the slice in a sorted order.
 func UniqueSortedBazelLabels(originalLabels []Label) []Label {
@@ -332,7 +364,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		la.Value = &value
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		if la.ConfigurableValues == nil {
 			la.ConfigurableValues = make(configurableLabels)
 		}
@@ -348,7 +380,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		return la.Value
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		return la.ConfigurableValues[axis][config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
@@ -424,7 +456,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		ba.Value = value
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		if ba.ConfigurableValues == nil {
 			ba.ConfigurableValues = make(configurableBools)
 		}
@@ -540,7 +572,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		return ba.Value
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		if v, ok := ba.ConfigurableValues[axis][config]; ok {
 			return &v
 		} else {
@@ -676,7 +708,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		lla.Value = list
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		if lla.ConfigurableValues == nil {
 			lla.ConfigurableValues = make(configurableLabelLists)
 		}
@@ -692,8 +724,8 @@
 	switch axis.configurationType {
 	case noConfig:
 		return lla.Value
-	case arch, os, osArch, productVariables:
-		return lla.ConfigurableValues[axis][config]
+	case arch, os, osArch, productVariables, osAndInApex:
+		return (lla.ConfigurableValues[axis][config])
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
 	}
@@ -822,6 +854,29 @@
 	}
 }
 
+// Partition splits a LabelListAttribute into two LabelListAttributes depending
+// on the return value of the predicate.
+// This function preserves the Includes and Excludes, but it does not provide
+// that information to the partition function.
+func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) {
+	predicated := LabelListAttribute{}
+	unpredicated := LabelListAttribute{}
+
+	valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate)
+	predicated.SetValue(valuePartitionTrue)
+	unpredicated.SetValue(valuePartitionFalse)
+
+	for axis, selectValueLabelLists := range lla.ConfigurableValues {
+		for config, labelList := range selectValueLabelLists {
+			configPredicated, configUnpredicated := labelList.Partition(predicate)
+			predicated.SetSelectValue(axis, config, configPredicated)
+			unpredicated.SetSelectValue(axis, config, configUnpredicated)
+		}
+	}
+
+	return predicated, unpredicated
+}
+
 // OtherModuleContext is a limited context that has methods with information about other modules.
 type OtherModuleContext interface {
 	ModuleFromName(name string) (blueprint.Module, bool)
@@ -1189,7 +1244,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		sla.Value = list
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		if sla.ConfigurableValues == nil {
 			sla.ConfigurableValues = make(configurableStringLists)
 		}
@@ -1205,7 +1260,7 @@
 	switch axis.configurationType {
 	case noConfig:
 		return sla.Value
-	case arch, os, osArch, productVariables:
+	case arch, os, osArch, productVariables, osAndInApex:
 		return sla.ConfigurableValues[axis][config]
 	default:
 		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index 7b76b74..dc4d5b0 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -310,6 +310,134 @@
 	}
 }
 
+func TestLabelListAttributePartition(t *testing.T) {
+	testCases := []struct {
+		name         string
+		input        LabelListAttribute
+		predicated   LabelListAttribute
+		unpredicated LabelListAttribute
+		predicate    func(label Label) bool
+	}{
+		{
+			name: "move all to predicated partition",
+			input: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			predicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			unpredicated: LabelListAttribute{},
+			predicate: func(label Label) bool {
+				return true
+			},
+		},
+		{
+			name: "move all to unpredicated partition",
+			input: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			predicated: LabelListAttribute{},
+			unpredicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			predicate: func(label Label) bool {
+				return false
+			},
+		},
+		{
+			name: "partition includes and excludes",
+			input: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			predicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "keep2"},
+				[]string{"keep1", "keep2"},
+			)),
+			unpredicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"throw1", "throw2"},
+				[]string{"throw1", "throw2"},
+			)),
+			predicate: func(label Label) bool {
+				return strings.HasPrefix(label.Label, "keep")
+			},
+		},
+		{
+			name: "partition excludes only",
+			input: MakeLabelListAttribute(makeLabelList(
+				[]string{},
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+			)),
+			predicated: MakeLabelListAttribute(makeLabelList(
+				[]string{},
+				[]string{"keep1", "keep2"},
+			)),
+			unpredicated: MakeLabelListAttribute(makeLabelList(
+				[]string{},
+				[]string{"throw1", "throw2"},
+			)),
+			predicate: func(label Label) bool {
+				return strings.HasPrefix(label.Label, "keep")
+			},
+		},
+		{
+			name: "partition includes only",
+			input: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "throw1", "keep2", "throw2"},
+				[]string{},
+			)),
+			predicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"keep1", "keep2"},
+				[]string{},
+			)),
+			unpredicated: MakeLabelListAttribute(makeLabelList(
+				[]string{"throw1", "throw2"},
+				[]string{},
+			)),
+			predicate: func(label Label) bool {
+				return strings.HasPrefix(label.Label, "keep")
+			},
+		},
+		{
+			name:         "empty partition",
+			input:        MakeLabelListAttribute(makeLabelList([]string{}, []string{})),
+			predicated:   LabelListAttribute{},
+			unpredicated: LabelListAttribute{},
+			predicate: func(label Label) bool {
+				return true
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			predicated, unpredicated := tc.input.Partition(tc.predicate)
+			if !predicated.Value.Equals(tc.predicated.Value) {
+				t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
+			}
+			for axis, configs := range predicated.ConfigurableValues {
+				tcConfigs, ok := tc.predicated.ConfigurableValues[axis]
+				if !ok || !reflect.DeepEqual(configs, tcConfigs) {
+					t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
+				}
+			}
+			if !unpredicated.Value.Equals(tc.unpredicated.Value) {
+				t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
+			}
+			for axis, configs := range unpredicated.ConfigurableValues {
+				tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis]
+				if !ok || !reflect.DeepEqual(configs, tcConfigs) {
+					t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
+				}
+			}
+		})
+	}
+}
+
 // labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
 // typ
 func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index cb25627..d327157 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -18,6 +18,7 @@
         "testing.go",
     ],
     deps: [
+        "aidl-soong-rules",
         "soong-android",
         "soong-android-allowlists",
         "soong-android-soongconfig",
@@ -36,6 +37,7 @@
     ],
     testSrcs: [
         "aar_conversion_test.go",
+        "aidl_interface_conversion_test.go",
         "android_app_certificate_conversion_test.go",
         "android_app_conversion_test.go",
         "apex_conversion_test.go",
diff --git a/bp2build/aidl_interface_conversion_test.go b/bp2build/aidl_interface_conversion_test.go
new file mode 100644
index 0000000..38d902d
--- /dev/null
+++ b/bp2build/aidl_interface_conversion_test.go
@@ -0,0 +1,249 @@
+package bp2build
+
+import (
+	"android/soong/aidl"
+	"android/soong/android"
+	"testing"
+)
+
+func runAidlInterfaceTestCase(t *testing.T, tc Bp2buildTestCase) {
+	t.Helper()
+	RunBp2BuildTestCase(
+		t,
+		func(ctx android.RegistrationContext) {
+			ctx.RegisterModuleType("aidl_interface", aidl.AidlInterfaceFactory)
+			ctx.RegisterModuleType("aidl_interface_headers", aidl.AidlInterfaceHeadersFactory)
+		},
+		tc,
+	)
+}
+
+func TestAidlInterfaceHeaders(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface_headers`,
+		Blueprint: `
+aidl_interface_headers {
+    name: "aidl-interface-headers",
+	include_dir: "src",
+	srcs: [
+		"src/A.aidl",
+	],
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{
+				"strip_import_prefix": `"src"`,
+				"hdrs":                `["src/A.aidl"]`,
+			}),
+		},
+	})
+}
+
+func TestAidlInterface(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface with single "latest" aidl_interface import`,
+		Blueprint: `
+aidl_interface_headers {
+    name: "aidl-interface-headers",
+}
+aidl_interface {
+    name: "aidl-interface-import",
+    versions: [
+        "1",
+        "2",
+    ],
+}
+aidl_interface {
+    name: "aidl-interface1",
+    flags: ["--flag1"],
+    imports: [
+        "aidl-interface-import-V1",
+    ],
+    headers: [
+        "aidl-interface-headers",
+    ],
+    versions: [
+        "1",
+        "2",
+        "3",
+    ],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{}),
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"versions": `[
+        "1",
+        "2",
+    ]`,
+			}),
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"deps": `[
+        ":aidl-interface-import-V1",
+        ":aidl-interface-headers",
+    ]`,
+				"flags": `["--flag1"]`,
+				"versions": `[
+        "1",
+        "2",
+        "3",
+    ]`,
+			}),
+		},
+	})
+}
+
+func TestAidlInterfaceWithNoProperties(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface no properties set`,
+		Blueprint: `
+aidl_interface {
+    name: "aidl-interface1",
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+			}),
+		},
+	})
+}
+
+func TestAidlInterfaceWithDisabledBackends(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface with some backends disabled`,
+		Blueprint: `
+aidl_interface {
+    name: "aidl-interface1",
+    backend: {
+        ndk: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
+				"backends": `["java"]`,
+			}),
+		},
+	})
+}
+
+func TestAidlInterfaceWithLatestImport(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface with single "latest" aidl_interface import`,
+		Blueprint: `
+aidl_interface {
+    name: "aidl-interface-import",
+    versions: [
+        "1",
+        "2",
+    ],
+}
+aidl_interface {
+    name: "aidl-interface1",
+    imports: [
+        "aidl-interface-import",
+    ],
+    versions: [
+        "1",
+        "2",
+        "3",
+    ],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"versions": `[
+        "1",
+        "2",
+    ]`,
+			}),
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"deps": `[":aidl-interface-import-latest"]`,
+				"versions": `[
+        "1",
+        "2",
+        "3",
+    ]`,
+			}),
+		},
+	})
+}
+
+func TestAidlInterfaceWithVersionedImport(t *testing.T) {
+	runAidlInterfaceTestCase(t, Bp2buildTestCase{
+		Description: `aidl_interface with single versioned aidl_interface import`,
+		Blueprint: `
+aidl_interface {
+    name: "aidl-interface-import",
+    versions: [
+        "1",
+        "2",
+    ],
+}
+aidl_interface {
+    name: "aidl-interface1",
+    imports: [
+        "aidl-interface-import-V2",
+    ],
+    versions: [
+        "1",
+        "2",
+        "3",
+    ],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"versions": `[
+        "1",
+        "2",
+    ]`,
+			}),
+			MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{
+				"backends": `[
+        "cpp",
+        "java",
+        "ndk",
+    ]`,
+				"deps": `[":aidl-interface-import-V2"]`,
+				"versions": `[
+        "1",
+        "2",
+        "3",
+    ]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 1f69b5a..9e449eb 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -581,3 +581,32 @@
 		},
 	})
 }
+
+func TestCcBinaryWithInstructionSet(t *testing.T) {
+	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+		description: "instruction set",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    arch: {
+      arm: {
+        instruction_set: "arm",
+      }
+    }
+}
+`,
+		targets: []testBazelTarget{
+			{"cc_binary", "foo", AttrNameToString{
+				"features": `select({
+        "//build/bazel/platforms/arch:arm": [
+            "arm_isa_arm",
+            "-arm_isa_thumb",
+        ],
+        "//conditions:default": [],
+    })`,
+				"local_includes": `["."]`,
+			},
+			},
+		},
+	})
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index f6d5067..024d4e0 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1301,10 +1301,10 @@
 		"additional_linker_inputs": true,
 		"linkopts":                 true,
 		"strip":                    true,
-		"stubs_symbol_file":        true,
-		"stubs_versions":           true,
 		"inject_bssl_hash":         true,
+		"has_stubs":                true,
 	}
+
 	sharedAttrs := AttrNameToString{}
 	staticAttrs := AttrNameToString{}
 	for key, val := range attrs {
@@ -1321,6 +1321,26 @@
 	return []string{staticTarget, sharedTarget}
 }
 
+func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
+	if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
+		return ""
+	}
+	STUB_SUITE_ATTRS := map[string]string{
+		"stubs_symbol_file": "symbol_file",
+		"stubs_versions":    "versions",
+		"soname":            "soname",
+		"source_library":    "source_library",
+	}
+
+	stubSuiteAttrs := AttrNameToString{}
+	for key, _ := range attrs {
+		if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
+			stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
+		}
+	}
+	return makeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
+}
+
 func TestCCLibraryNoLibCrtFalse(t *testing.T) {
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library",
@@ -2424,6 +2444,19 @@
 }
 
 func TestCcLibraryStubs(t *testing.T) {
+	expectedBazelTargets := makeCcLibraryTargets("a", AttrNameToString{
+		"has_stubs": `True`,
+	})
+	expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{
+		"soname":            `"a.so"`,
+		"source_library":    `":a"`,
+		"stubs_symbol_file": `"a.map.txt"`,
+		"stubs_versions": `[
+        "28",
+        "29",
+        "current",
+    ]`,
+	}))
 	runCcLibraryTestCase(t, Bp2buildTestCase{
 		Description:                "cc_library stubs",
 		ModuleTypeUnderTest:        "cc_library",
@@ -2439,15 +2472,8 @@
 }
 `,
 		},
-		Blueprint: soongCcLibraryPreamble,
-		ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
-			"stubs_symbol_file": `"a.map.txt"`,
-			"stubs_versions": `[
-        "28",
-        "29",
-        "current",
-    ]`,
-		}),
+		Blueprint:            soongCcLibraryPreamble,
+		ExpectedBazelTargets: expectedBazelTargets,
 	},
 	)
 }
@@ -2540,3 +2566,109 @@
 		},
 	})
 }
+
+func TestCcLibraryWithInstructionSet(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `cc_library {
+    name: "foo",
+    arch: {
+      arm: {
+        instruction_set: "arm",
+      }
+    }
+}
+`,
+		ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
+			"features": `select({
+        "//build/bazel/platforms/arch:arm": [
+            "arm_isa_arm",
+            "-arm_isa_thumb",
+        ],
+        "//conditions:default": [],
+    })`,
+			"local_includes": `["."]`,
+		}),
+	})
+}
+
+func TestCcLibraryWithAidlSrcs(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with aidl srcs",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Blueprint: `
+filegroup {
+    name: "A_aidl",
+    srcs: ["aidl/A.aidl"],
+	path: "aidl",
+}
+cc_library {
+	name: "foo",
+	srcs: [
+		":A_aidl",
+		"B.aidl",
+	],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
+				"srcs":                `["aidl/A.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+			}),
+			makeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+				"srcs": `["B.aidl"]`,
+			}),
+			makeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+				"deps": `[
+        ":A_aidl",
+        ":foo_aidl_library",
+    ]`,
+			}),
+			makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":     `["."]`,
+			}),
+			makeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":     `["."]`,
+			}),
+		},
+	})
+}
+
+func TestCcLibraryWithNonAdjacentAidlFilegroup(t *testing.T) {
+	runCcLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library with non aidl filegroup",
+		ModuleTypeUnderTest:        "cc_library",
+		ModuleTypeUnderTestFactory: cc.LibraryFactory,
+		Filesystem: map[string]string{
+			"path/to/A/Android.bp": `
+filegroup {
+	name: "A_aidl",
+	srcs: ["aidl/A.aidl"],
+	path: "aidl",
+}`,
+		},
+		Blueprint: `
+cc_library {
+	name: "foo",
+	srcs: [
+		":A_aidl",
+	],
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+				"deps": `["//path/to/A:A_aidl"]`,
+			}),
+			makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":     `["."]`,
+			}),
+			makeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"whole_archive_deps": `[":foo_cc_aidl_library"]`,
+				"local_includes":     `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index de57e5a..7a44f69 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -485,12 +485,7 @@
 		},
 		Blueprint: soongCcLibraryPreamble,
 		ExpectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "a", AttrNameToString{
-			"stubs_symbol_file": `"a.map.txt"`,
-			"stubs_versions": `[
-        "28",
-        "29",
-        "current",
-    ]`,
+			"has_stubs": `True`,
 		}),
 		},
 	},
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 7fa19d9..f5a5938 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -372,3 +372,132 @@
 		ExpectedBazelTargets: []string{},
 	})
 }
+
+func TestJavaLibraryAidl(t *testing.T) {
+	runJavaLibraryTestCase(t, Bp2buildTestCase{
+		Description:                "Java library - aidl creates separate dependency",
+		ModuleTypeUnderTest:        "java_library",
+		ModuleTypeUnderTestFactory: java.LibraryFactory,
+		Blueprint: `java_library {
+        name: "example_lib",
+        srcs: [
+			"a.java",
+			"b.java",
+			"a.aidl",
+			"b.aidl",
+		],
+        bazel_module: { bp2build_available: true },
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
+				"srcs": `[
+        "a.aidl",
+        "b.aidl",
+    ]`,
+			}),
+			makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
+				"deps": `[":example_lib_aidl_library"]`,
+			}),
+			makeBazelTarget("java_library", "example_lib", AttrNameToString{
+				"deps":    `[":example_lib_java_aidl_library"]`,
+				"exports": `[":example_lib_java_aidl_library"]`,
+				"srcs": `[
+        "a.java",
+        "b.java",
+    ]`,
+			}),
+		}})
+}
+
+func TestJavaLibraryAidlSrcsNoFileGroup(t *testing.T) {
+	runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
+		Description:                "Java library - aidl filegroup is parsed",
+		ModuleTypeUnderTest:        "java_library",
+		ModuleTypeUnderTestFactory: java.LibraryFactory,
+		Blueprint: `
+java_library {
+        name: "example_lib",
+        srcs: [
+			"a.java",
+			"b.aidl",
+		],
+        bazel_module: { bp2build_available: true },
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
+				"srcs": `["b.aidl"]`,
+			}),
+			makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
+				"deps": `[":example_lib_aidl_library"]`,
+			}),
+			makeBazelTarget("java_library", "example_lib", AttrNameToString{
+				"deps":    `[":example_lib_java_aidl_library"]`,
+				"exports": `[":example_lib_java_aidl_library"]`,
+				"srcs":    `["a.java"]`,
+			}),
+		},
+	}, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	})
+}
+
+func TestJavaLibraryAidlFilegroup(t *testing.T) {
+	runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
+		Description:                "Java library - aidl filegroup is parsed",
+		ModuleTypeUnderTest:        "java_library",
+		ModuleTypeUnderTestFactory: java.LibraryFactory,
+		Blueprint: `
+filegroup {
+	name: "random_other_files",
+	srcs: [
+		"a.java",
+		"b.java",
+	],
+}
+filegroup {
+	name: "aidl_files",
+	srcs: [
+		"a.aidl",
+		"b.aidl",
+	],
+}
+java_library {
+        name: "example_lib",
+        srcs: [
+			"a.java",
+			"b.java",
+			":aidl_files",
+			":random_other_files",
+		],
+        bazel_module: { bp2build_available: true },
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "aidl_files", AttrNameToString{
+				"srcs": `[
+        "a.aidl",
+        "b.aidl",
+    ]`,
+			}),
+			makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
+				"deps": `[":aidl_files"]`,
+			}),
+			makeBazelTarget("java_library", "example_lib", AttrNameToString{
+				"deps":    `[":example_lib_java_aidl_library"]`,
+				"exports": `[":example_lib_java_aidl_library"]`,
+				"srcs": `[
+        "a.java",
+        "b.java",
+        ":random_other_files",
+    ]`,
+			}),
+			MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{
+				"srcs": `[
+        "a.java",
+        "b.java",
+    ]`,
+			}),
+		},
+	}, func(ctx android.RegistrationContext) {
+		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	})
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 5954098..625e7ce 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -35,16 +35,18 @@
 	llSrcPartition    = "ll"
 	cppSrcPartition   = "cpp"
 	protoSrcPartition = "proto"
+	aidlSrcPartition  = "aidl"
 )
 
 // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
 // properties which apply to either the shared or static version of a cc_library module.
 type staticOrSharedAttributes struct {
-	Srcs    bazel.LabelListAttribute
-	Srcs_c  bazel.LabelListAttribute
-	Srcs_as bazel.LabelListAttribute
-	Hdrs    bazel.LabelListAttribute
-	Copts   bazel.StringListAttribute
+	Srcs      bazel.LabelListAttribute
+	Srcs_c    bazel.LabelListAttribute
+	Srcs_as   bazel.LabelListAttribute
+	Srcs_aidl bazel.LabelListAttribute
+	Hdrs      bazel.LabelListAttribute
+	Copts     bazel.StringListAttribute
 
 	Deps                              bazel.LabelListAttribute
 	Implementation_deps               bazel.LabelListAttribute
@@ -68,10 +70,17 @@
 	// Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
 	// macro.
 	addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
-		return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
-			m, exists := ctx.ModuleFromName(label.OriginalModuleName)
+		return func(otherModuleCtx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+
+			m, exists := otherModuleCtx.ModuleFromName(label.OriginalModuleName)
 			labelStr := label.Label
-			if !exists || !android.IsFilegroup(ctx, m) {
+			if !exists || !android.IsFilegroup(otherModuleCtx, m) {
+				return labelStr, false
+			}
+			// If the filegroup is already converted to aidl_library, skip creating
+			// _c_srcs, _as_srcs, _cpp_srcs filegroups
+			fg, _ := m.(android.Bp2buildAidlLibrary)
+			if fg.ShouldConvertToAidlLibrary(ctx) {
 				return labelStr, false
 			}
 			return labelStr + suffix, true
@@ -84,6 +93,7 @@
 		cSrcPartition:     bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
 		asSrcPartition:    bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
 		asmSrcPartition:   bazel.LabelPartition{Extensions: []string{".asm"}},
+		aidlSrcPartition:  android.AidlSrcLabelPartition,
 		// TODO(http://b/231968910): If there is ever a filegroup target that
 		// 		contains .l or .ll files we will need to find a way to add a
 		// 		LabelMapper for these that identifies these filegroups and
@@ -282,7 +292,10 @@
 	compilerAttributes
 	linkerAttributes
 
+	// A combination of compilerAttributes.features and linkerAttributes.features
+	features        bazel.StringListAttribute
 	protoDependency *bazel.LabelAttribute
+	aidlDependency  *bazel.LabelAttribute
 }
 
 // Convenience struct to hold all attributes parsed from compiler properties.
@@ -320,9 +333,12 @@
 	includes BazelIncludes
 
 	protoSrcs bazel.LabelListAttribute
+	aidlSrcs  bazel.LabelListAttribute
 
 	stubsSymbolFile *string
 	stubsVersions   bazel.StringListAttribute
+
+	features bazel.StringListAttribute
 }
 
 type filterOutFn func(string) bool
@@ -386,6 +402,13 @@
 	ca.absoluteIncludes.SetSelectValue(axis, config, props.Include_dirs)
 	ca.localIncludes.SetSelectValue(axis, config, localIncludeDirs)
 
+	instructionSet := proptools.StringDefault(props.Instruction_set, "")
+	if instructionSet == "arm" {
+		ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm", "-arm_isa_thumb"})
+	} else if instructionSet != "" && instructionSet != "thumb" {
+		ctx.ModuleErrorf("Unknown value for instruction_set: %s", instructionSet)
+	}
+
 	// In Soong, cflags occur on the command line before -std=<val> flag, resulting in the value being
 	// overridden. In Bazel we always allow overriding, via flags; however, this can cause
 	// incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
@@ -438,6 +461,7 @@
 	partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
 
 	ca.protoSrcs = partitionedSrcs[protoSrcPartition]
+	ca.aidlSrcs = partitionedSrcs[aidlSrcPartition]
 
 	for p, lla := range partitionedSrcs {
 		// if there are no sources, there is no need for headers
@@ -470,12 +494,27 @@
 	}
 
 	allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
+
 	if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 {
 		anySrcs = true
 	}
+
 	return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
 }
 
+// Given a name in srcs prop, check to see if the name references a filegroup
+// and the filegroup is converted to aidl_library
+func isConvertedToAidlLibrary(ctx android.BazelConversionPathContext, name string) bool {
+	if module, ok := ctx.ModuleFromName(name); ok {
+		if android.IsFilegroup(ctx, module) {
+			if fg, ok := module.(android.Bp2buildAidlLibrary); ok {
+				return fg.ShouldConvertToAidlLibrary(ctx)
+			}
+		}
+	}
+	return false
+}
+
 func bp2buildStdVal(std *string, prefix string, useGnu bool) *string {
 	defaultVal := prefix + "_std_default"
 	// If c{,pp}std properties are not specified, don't generate them in the BUILD file.
@@ -642,9 +681,12 @@
 			includes, absoluteIncludes := includesFromLabelList(headers.implementation)
 			currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, config)
 			currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...))
+
 			compilerAttrs.absoluteIncludes.SetSelectValue(axis, config, currAbsoluteIncludes)
+
 			currIncludes := compilerAttrs.localIncludes.SelectValue(axis, config)
 			currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...))
+
 			compilerAttrs.localIncludes.SetSelectValue(axis, config, currIncludes)
 
 			if libraryProps, ok := archVariantLibraryProperties[axis][config].(*LibraryProperties); ok {
@@ -655,6 +697,7 @@
 			}
 		}
 	}
+
 	compilerAttrs.convertStlProps(ctx, module)
 	(&linkerAttrs).convertStripProps(ctx, module)
 
@@ -675,24 +718,106 @@
 	(&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
 
 	protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
+	aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs)
 
 	// bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
 	// which. This will add the newly generated proto library to the appropriate attribute and nothing
 	// to the other
 	(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
 	(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
+	// TODO(b/243023967) Add aidlDep to implementationWholeArchiveDeps if aidl.export_aidl_headers is true
+	(&linkerAttrs).wholeArchiveDeps.Add(aidlDep)
 
 	convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs)
 	(&compilerAttrs).srcs.Add(&convertedLSrcs.srcName)
 	(&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName)
 
+	features := compilerAttrs.features.Clone().Append(linkerAttrs.features)
+	features.DeduplicateAxesFromBase()
+
 	return baseAttributes{
 		compilerAttrs,
 		linkerAttrs,
+		*features,
 		protoDep.protoDep,
+		aidlDep,
 	}
 }
 
+func bp2buildAidlLibraries(
+	ctx android.Bp2buildMutatorContext,
+	m *Module,
+	aidlSrcs bazel.LabelListAttribute,
+) bazel.LabelList {
+	var aidlLibraries bazel.LabelList
+	var directAidlSrcs bazel.LabelList
+
+	// Make a list of labels that correspond to filegroups that are already converted to aidl_library
+	for _, aidlSrc := range aidlSrcs.Value.Includes {
+		src := aidlSrc.OriginalModuleName
+		if isConvertedToAidlLibrary(ctx, src) {
+			module, _ := ctx.ModuleFromName(src)
+			fg, _ := module.(android.Bp2buildAidlLibrary)
+			aidlLibraries.Add(&bazel.Label{
+				Label: fg.GetAidlLibraryLabel(ctx),
+			})
+		} else {
+			directAidlSrcs.Add(&aidlSrc)
+		}
+	}
+
+	if len(directAidlSrcs.Includes) > 0 {
+		aidlLibraryLabel := m.Name() + "_aidl_library"
+		ctx.CreateBazelTargetModule(
+			bazel.BazelTargetModuleProperties{
+				Rule_class:        "aidl_library",
+				Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+			},
+			android.CommonAttributes{Name: aidlLibraryLabel},
+			&aidlLibraryAttributes{
+				Srcs: bazel.MakeLabelListAttribute(directAidlSrcs),
+			},
+		)
+		aidlLibraries.Add(&bazel.Label{
+			Label: ":" + aidlLibraryLabel,
+		})
+	}
+	return aidlLibraries
+}
+
+func bp2buildCcAidlLibrary(
+	ctx android.Bp2buildMutatorContext,
+	m *Module,
+	aidlSrcs bazel.LabelListAttribute,
+) *bazel.LabelAttribute {
+	suffix := "_cc_aidl_library"
+	ccAidlLibrarylabel := m.Name() + suffix
+
+	aidlLibraries := bp2buildAidlLibraries(ctx, m, aidlSrcs)
+
+	if aidlLibraries.IsEmpty() {
+		return nil
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "cc_aidl_library",
+			Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+		},
+		android.CommonAttributes{Name: ccAidlLibrarylabel},
+		&ccAidlLibraryAttributes{
+			Deps: bazel.MakeLabelListAttribute(aidlLibraries),
+		},
+	)
+
+	label := &bazel.LabelAttribute{
+		Value: &bazel.Label{
+			Label: ":" + ccAidlLibrarylabel,
+		},
+	}
+	return label
+}
+
 func bp2BuildParseSdkAttributes(module *Module) sdkAttributes {
 	return sdkAttributes{
 		Sdk_version:     module.Properties.Sdk_version,
@@ -779,6 +904,45 @@
 	sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
 	la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
 	la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
+	if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
+		// If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be
+		// used when the dependency is linked in a APEX. The dependencies in NoConfigAxis and
+		// OsConfigurationAxis/OsAndroid are grouped by having stubs or not, so Bazel select()
+		// statement can be used to choose source/stub variants of them.
+		depsWithStubs := []bazel.Label{}
+		for _, l := range sharedDeps.implementation.Includes {
+			dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
+			if m, ok := dep.(*Module); ok && m.HasStubsVariants() {
+				depsWithStubs = append(depsWithStubs, l)
+			}
+		}
+		if len(depsWithStubs) > 0 {
+			implDynamicDeps := bazel.SubtractBazelLabelList(sharedDeps.implementation, bazel.MakeLabelList(depsWithStubs))
+			la.implementationDynamicDeps.SetSelectValue(axis, config, implDynamicDeps)
+
+			stubLibLabels := []bazel.Label{}
+			for _, l := range depsWithStubs {
+				l.Label = l.Label + "_stub_libs_current"
+				stubLibLabels = append(stubLibLabels, l)
+			}
+			inApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex)
+			nonApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex)
+			defaultSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey)
+			if axis == bazel.NoConfigAxis {
+				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
+				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+				(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, defaultSelectValue)
+			} else if config == bazel.OsAndroid {
+				(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
+				(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
+				la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
+			}
+		}
+	}
 
 	if !BoolDefault(props.Pack_relocations, packRelocationsDefault) {
 		axisFeatures = append(axisFeatures, "disable_pack_relocations")
diff --git a/cc/builder.go b/cc/builder.go
index f3faca8..35ae69b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -282,7 +282,7 @@
 	sAbiDiff = pctx.RuleFunc("sAbiDiff",
 		func(ctx android.PackageRuleContext) blueprint.RuleParams {
 			commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
-			commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'"
+			commandStr += "|| (echo '${errorMessage}'"
 			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
 			commandStr += " && exit 1)"
 			return blueprint.RuleParams{
@@ -290,7 +290,7 @@
 				CommandDeps: []string{"$sAbiDiffer"},
 			}
 		},
-		"extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
+		"extraFlags", "referenceDump", "libName", "arch", "errorMessage")
 
 	// Rule to unzip a reference abi dump.
 	unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
@@ -940,9 +940,21 @@
 			"-allow-unreferenced-elf-symbol-changes")
 	}
 
-	// TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved.
+	var errorMessage string
+	// When error occurs in previous version ABI diff, Developers can't just update ABI
+	// reference but need to follow instructions to ensure ABI backward compatibility.
 	if previousVersionDiff {
+		// TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved.
 		extraFlags = append(extraFlags, "-advice-only")
+		errorMessage = "error: Please follow development/vndk/tools/header-checker/README.md to ensure the ABI compatibility between your source code and version " + prevVersion + "."
+		// The prevVersion is expected as a string of int, skip it if not.
+		if prevVersionInt, err := strconv.Atoi(prevVersion); err == nil {
+			sourceVersion := strconv.Itoa(prevVersionInt + 1)
+			extraFlags = append(extraFlags, "-target-version", sourceVersion)
+		}
+	} else {
+		errorMessage = "error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
+		extraFlags = append(extraFlags, "-target-version", "current")
 	}
 
 	if isLlndk || isNdk {
@@ -961,11 +973,11 @@
 		Input:       inputDump,
 		Implicit:    referenceDump,
 		Args: map[string]string{
-			"referenceDump":            referenceDump.String(),
-			"libName":                  libName,
-			"arch":                     ctx.Arch().ArchType.Name,
-			"extraFlags":               strings.Join(extraFlags, " "),
-			"createReferenceDumpFlags": "",
+			"referenceDump": referenceDump.String(),
+			"libName":       libName,
+			"arch":          ctx.Arch().ArchType.Name,
+			"extraFlags":    strings.Join(extraFlags, " "),
+			"errorMessage":  errorMessage,
 		},
 	})
 	return android.OptionalPathForPath(outputFile)
diff --git a/cc/library.go b/cc/library.go
index 41dca01..fc03fa2 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -270,6 +270,15 @@
 	Features bazel.StringListAttribute
 }
 
+type aidlLibraryAttributes struct {
+	Srcs        bazel.LabelListAttribute
+	Include_dir *string
+}
+
+type ccAidlLibraryAttributes struct {
+	Deps bazel.LabelListAttribute
+}
+
 type stripAttributes struct {
 	Keep_symbols                 bazel.BoolAttribute
 	Keep_symbols_and_debug_frame bazel.BoolAttribute
@@ -359,7 +368,7 @@
 		C_std:                    compilerAttrs.cStd,
 		Use_version_lib:          linkerAttrs.useVersionLib,
 
-		Features: linkerAttrs.features,
+		Features: baseAttributes.features,
 	}
 
 	sharedTargetAttrs := &bazelCcLibrarySharedAttributes{
@@ -391,10 +400,12 @@
 			All:                          linkerAttrs.stripAll,
 			None:                         linkerAttrs.stripNone,
 		},
-		Features: linkerAttrs.features,
+		Features: baseAttributes.features,
+	}
 
-		Stubs_symbol_file: compilerAttrs.stubsSymbolFile,
-		Stubs_versions:    compilerAttrs.stubsVersions,
+	if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
+		hasStubs := true
+		sharedTargetAttrs.Has_stubs.SetValue(&hasStubs)
 	}
 
 	for axis, configToProps := range m.GetArchVariantProperties(ctx, &LibraryProperties{}) {
@@ -427,6 +438,25 @@
 	ctx.CreateBazelTargetModuleWithRestrictions(sharedProps,
 		android.CommonAttributes{Name: m.Name()},
 		sharedTargetAttrs, sharedAttrs.Enabled)
+
+	if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
+		stubSuitesProps := bazel.BazelTargetModuleProperties{
+			Rule_class:        "cc_stub_suite",
+			Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl",
+		}
+		soname := m.Name() + ".so"
+		stubSuitesAttrs := &bazelCcStubSuiteAttributes{
+			Symbol_file:     compilerAttrs.stubsSymbolFile,
+			Versions:        compilerAttrs.stubsVersions,
+			Export_includes: exportedIncludes.Includes,
+			Soname:          &soname,
+			Source_library:  *bazel.MakeLabelAttribute(":" + m.Name()),
+			Deps:            baseAttributes.deps,
+		}
+		ctx.CreateBazelTargetModule(stubSuitesProps,
+			android.CommonAttributes{Name: m.Name() + "_stub_libs"},
+			stubSuitesAttrs)
+	}
 }
 
 // cc_library creates both static and/or shared libraries for a device and/or
@@ -2579,12 +2609,12 @@
 			Conlyflags: compilerAttrs.conlyFlags,
 			Asflags:    asFlags,
 
-			Features: linkerAttrs.features,
+			Features: baseAttributes.features,
 		}
 	} else {
 		commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
 
-		attrs = &bazelCcLibrarySharedAttributes{
+		sharedLibAttrs := &bazelCcLibrarySharedAttributes{
 			staticOrSharedAttributes: commonAttrs,
 
 			Cppflags:   compilerAttrs.cppFlags,
@@ -2616,11 +2646,13 @@
 				None:                         linkerAttrs.stripNone,
 			},
 
-			Features: linkerAttrs.features,
-
-			Stubs_symbol_file: compilerAttrs.stubsSymbolFile,
-			Stubs_versions:    compilerAttrs.stubsVersions,
+			Features: baseAttributes.features,
 		}
+		if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
+			hasStubs := true
+			sharedLibAttrs.Has_stubs.SetValue(&hasStubs)
+		}
+		attrs = sharedLibAttrs
 	}
 
 	var modType string
@@ -2694,7 +2726,16 @@
 
 	Features bazel.StringListAttribute
 
-	Stubs_symbol_file *string
-	Stubs_versions    bazel.StringListAttribute
-	Inject_bssl_hash  bazel.BoolAttribute
+	Has_stubs bazel.BoolAttribute
+
+	Inject_bssl_hash bazel.BoolAttribute
+}
+
+type bazelCcStubSuiteAttributes struct {
+	Symbol_file     *string
+	Versions        bazel.StringListAttribute
+	Export_includes bazel.StringListAttribute
+	Source_library  bazel.LabelAttribute
+	Soname          *string
+	Deps            bazel.LabelListAttribute
 }
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 6686c87..7a0dac3 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -26,6 +26,7 @@
 	"strings"
 
 	"android/soong/bazel/cquery"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/proptools"
@@ -468,6 +469,7 @@
 				return "SOONG_ERROR", nil
 			}
 
+			// Apply shell escape to each cases to prevent source file paths containing $ from being evaluated in shell
 			switch name {
 			case "location":
 				if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
@@ -481,15 +483,15 @@
 					return reportError("default label %q has multiple files, use $(locations %s) to reference it",
 						firstLabel, firstLabel)
 				}
-				return paths[0], nil
+				return proptools.ShellEscape(paths[0]), nil
 			case "in":
-				return strings.Join(cmd.PathsForInputs(srcFiles), " "), nil
+				return strings.Join(proptools.ShellEscapeList(cmd.PathsForInputs(srcFiles)), " "), nil
 			case "out":
 				var sandboxOuts []string
 				for _, out := range task.out {
 					sandboxOuts = append(sandboxOuts, cmd.PathForOutput(out))
 				}
-				return strings.Join(sandboxOuts, " "), nil
+				return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
 			case "depfile":
 				referencedDepfile = true
 				if !Bool(g.properties.Depfile) {
@@ -497,7 +499,7 @@
 				}
 				return "__SBOX_DEPFILE__", nil
 			case "genDir":
-				return cmd.PathForOutput(task.genDir), nil
+				return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
 			default:
 				if strings.HasPrefix(name, "location ") {
 					label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -509,7 +511,7 @@
 							return reportError("label %q has multiple files, use $(locations %s) to reference it",
 								label, label)
 						}
-						return paths[0], nil
+						return proptools.ShellEscape(paths[0]), nil
 					} else {
 						return reportError("unknown location label %q is not in srcs, out, tools or tool_files.", label)
 					}
@@ -520,7 +522,7 @@
 						if len(paths) == 0 {
 							return reportError("label %q has no files", label)
 						}
-						return strings.Join(paths, " "), nil
+						return proptools.ShellEscape(strings.Join(paths, " ")), nil
 					} else {
 						return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label)
 					}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index b9be1f7..cd941cc 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -422,7 +422,7 @@
 
 			allowMissingDependencies: true,
 
-			expect: "cat ***missing srcs :missing*** > __SBOX_SANDBOX_DIR__/out/out",
+			expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
 		},
 		{
 			name: "tool allow missing dependencies",
@@ -434,7 +434,7 @@
 
 			allowMissingDependencies: true,
 
-			expect: "***missing tool :missing*** > __SBOX_SANDBOX_DIR__/out/out",
+			expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
 		},
 	}
 
@@ -878,6 +878,92 @@
 	android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
 }
 
+func TestGenruleWithGlobPaths(t *testing.T) {
+	testcases := []struct {
+		name            string
+		bp              string
+		additionalFiles android.MockFS
+		expectedCmd     string
+	}{
+		{
+			name: "single file in directory with $ sign",
+			bp: `
+				genrule {
+					name: "gen",
+					srcs: ["inn*.txt"],
+					out: ["out.txt"],
+					cmd: "cp $(in) $(out)",
+				}
+				`,
+			additionalFiles: android.MockFS{"inn$1.txt": nil},
+			expectedCmd:     "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+		},
+		{
+			name: "multiple file in directory with $ sign",
+			bp: `
+				genrule {
+					name: "gen",
+					srcs: ["inn*.txt"],
+					out: ["."],
+					cmd: "cp $(in) $(out)",
+				}
+				`,
+			additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
+			expectedCmd:     "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
+		},
+		{
+			name: "file in directory with other shell unsafe character",
+			bp: `
+				genrule {
+					name: "gen",
+					srcs: ["inn*.txt"],
+					out: ["out.txt"],
+					cmd: "cp $(in) $(out)",
+				}
+				`,
+			additionalFiles: android.MockFS{"inn@1.txt": nil},
+			expectedCmd:     "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+		},
+		{
+			name: "glob location param with filepath containing $",
+			bp: `
+				genrule {
+					name: "gen",
+					srcs: ["**/inn*"],
+					out: ["."],
+					cmd: "cp $(in) $(location **/inn*)",
+				}
+				`,
+			additionalFiles: android.MockFS{"a/inn$1.txt": nil},
+			expectedCmd:     "cp 'a/inn$1.txt' 'a/inn$1.txt'",
+		},
+		{
+			name: "glob locations param with filepath containing $",
+			bp: `
+				genrule {
+					name: "gen",
+					tool_files: ["**/inn*"],
+					out: ["out.txt"],
+					cmd: "cp $(locations  **/inn*) $(out)",
+				}
+				`,
+			additionalFiles: android.MockFS{"a/inn$1.txt": nil},
+			expectedCmd:     "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+		},
+	}
+
+	for _, test := range testcases {
+		t.Run(test.name, func(t *testing.T) {
+			result := android.GroupFixturePreparers(
+				prepareForGenRuleTest,
+				android.FixtureMergeMockFs(test.additionalFiles),
+			).RunTestWithBp(t, test.bp)
+			gen := result.Module("gen", "").(*Module)
+			android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
+		})
+	}
+}
+
 type testTool struct {
 	android.ModuleBase
 	outputFile android.Path
diff --git a/go.mod b/go.mod
index 8c1a9f0..2e28ab6 100644
--- a/go.mod
+++ b/go.mod
@@ -1,13 +1,17 @@
 module android/soong
 
-require google.golang.org/protobuf v0.0.0
-
-require github.com/google/blueprint v0.0.0
+require (
+	google.golang.org/protobuf v0.0.0
+	github.com/google/blueprint v0.0.0
+	android/soong/aidl v0.0.0
+)
 
 replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
 
 replace github.com/google/blueprint v0.0.0 => ../blueprint
 
+replace android/soong/aidl v0.0.0 => ../../system/tools/aidl/build
+
 // Indirect deps from golang-protobuf
 exclude github.com/golang/protobuf v1.5.0
 
diff --git a/java/base.go b/java/base.go
index fe92b47..cf3b3d5 100644
--- a/java/base.go
+++ b/java/base.go
@@ -820,7 +820,7 @@
 }
 
 func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
-	aidlIncludeDirs android.Paths) (string, android.Paths) {
+	aidlIncludeDirs android.Paths, aidlSrcs android.Paths) (string, android.Paths) {
 
 	aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
 	aidlIncludes = append(aidlIncludes,
@@ -830,6 +830,7 @@
 
 	var flags []string
 	var deps android.Paths
+	var includeDirs android.Paths
 
 	flags = append(flags, j.deviceProperties.Aidl.Flags...)
 
@@ -837,21 +838,24 @@
 		flags = append(flags, "-p"+aidlPreprocess.String())
 		deps = append(deps, aidlPreprocess.Path())
 	} else if len(aidlIncludeDirs) > 0 {
-		flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
+		includeDirs = append(includeDirs, aidlIncludeDirs...)
 	}
 
 	if len(j.exportAidlIncludeDirs) > 0 {
-		flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
+		includeDirs = append(includeDirs, j.exportAidlIncludeDirs...)
 	}
 
 	if len(aidlIncludes) > 0 {
-		flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
+		includeDirs = append(includeDirs, aidlIncludes...)
 	}
 
-	flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
+	includeDirs = append(includeDirs, android.PathForModuleSrc(ctx))
 	if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
-		flags = append(flags, "-I"+src.String())
+		includeDirs = append(includeDirs, src.Path())
 	}
+	flags = append(flags, android.JoinWithPrefix(includeDirs.Strings(), "-I"))
+	// add flags for dirs containing AIDL srcs that haven't been specified yet
+	flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))
 
 	if Bool(j.deviceProperties.Aidl.Generate_traces) {
 		flags = append(flags, "-t")
@@ -935,9 +939,6 @@
 	// systemModules
 	flags.systemModules = deps.systemModules
 
-	// aidl flags.
-	flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
-
 	return flags
 }
 
@@ -1046,6 +1047,9 @@
 		ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
 	}
 
+	aidlSrcs := srcFiles.FilterByExt(".aidl")
+	flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs, aidlSrcs)
+
 	nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar")
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
@@ -1195,12 +1199,21 @@
 		}
 	}
 	if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
+		hasErrorproneableFiles := false
+		for _, ext := range j.sourceExtensions {
+			if ext != ".proto" && ext != ".aidl" {
+				// Skip running errorprone on pure proto or pure aidl modules. Some modules take a long time to
+				// compile, and it's not useful to have warnings on these generated sources.
+				hasErrorproneableFiles = true
+				break
+			}
+		}
 		var extraJarDeps android.Paths
 		if Bool(j.properties.Errorprone.Enabled) {
 			// If error-prone is enabled, enable errorprone flags on the regular
 			// build.
 			flags = enableErrorproneFlags(flags)
-		} else if ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil {
+		} else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil {
 			// Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
 			// a new jar file just for compiling with the errorprone compiler to.
 			// This is because we don't want to cause the java files to get completely
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 901419c..9b1f43b 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -314,7 +314,7 @@
 	outSrcFiles := make(android.Paths, 0, len(srcFiles))
 	var aidlSrcs android.Paths
 
-	aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
+	aidlIncludeFlags := genAidlIncludeFlags(ctx, srcFiles, android.Paths{})
 
 	for _, srcFile := range srcFiles {
 		switch srcFile.Ext() {
diff --git a/java/gen.go b/java/gen.go
index 1572bf0..638da25 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -15,6 +15,7 @@
 package java
 
 import (
+	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -116,12 +117,31 @@
 	return javaFile
 }
 
-func genAidlIncludeFlags(srcFiles android.Paths) string {
+// genAidlIncludeFlags returns additional include flags based on the relative path
+// of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to
+// the Android checkout root that should not be included in the returned flags.
+func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string {
 	var baseDirs []string
+	excludeDirsStrings := excludeDirs.Strings()
 	for _, srcFile := range srcFiles {
 		if srcFile.Ext() == ".aidl" {
 			baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
-			if baseDir != "" && !android.InList(baseDir, baseDirs) {
+			baseDir = filepath.Clean(baseDir)
+			baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings)
+
+			// For go/bp2build mixed builds, a file may be listed under a
+			// directory in the Bazel output tree that is symlinked to a
+			// directory under the android source tree. We should only
+			// include one copy of this directory so that the AIDL tool
+			// doesn't find multiple definitions of the same AIDL class.
+			// This code comes into effect when filegroups are used in mixed builds.
+			bazelPathPrefix := android.PathForBazelOut(ctx, "").String()
+			bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir)
+			bazelBaseDirSeen := err == nil &&
+				android.InList(bazelBaseDir, baseDirs) ||
+				android.InList(bazelBaseDir, excludeDirsStrings)
+
+			if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen {
 				baseDirs = append(baseDirs, baseDir)
 			}
 		}
@@ -136,8 +156,6 @@
 	var protoSrcs android.Paths
 	var aidlSrcs android.Paths
 
-	aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
-
 	for _, srcFile := range srcFiles {
 		switch srcFile.Ext() {
 		case ".aidl":
@@ -168,7 +186,7 @@
 				individualFlags[aidlSrc.String()] = flags
 			}
 		}
-		srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, individualFlags, flags.aidlDeps)
+		srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps)
 		outSrcFiles = append(outSrcFiles, srcJarFiles...)
 	}
 
diff --git a/java/java.go b/java/java.go
index 210b883..0251b57 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2259,16 +2259,27 @@
 	StaticDeps bazel.LabelListAttribute
 }
 
-// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
-// and also separates dependencies into dynamic dependencies and static dependencies.
-// Each corresponding Bazel target type, can have a different method for handling
-// dynamic vs. static dependencies, and so these are returned to the calling function.
 type eventLogTagsAttributes struct {
 	Srcs bazel.LabelListAttribute
 }
 
+type aidlLibraryAttributes struct {
+	Srcs bazel.LabelListAttribute
+}
+
+type javaAidlLibraryAttributes struct {
+	Deps bazel.LabelListAttribute
+}
+
+// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
+// and also separates dependencies into dynamic dependencies and static dependencies.
+// Each corresponding Bazel target type, can have a different method for handling
+// dynamic vs. static dependencies, and so these are returned to the calling function.
 func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
 	var srcs bazel.LabelListAttribute
+	var deps bazel.LabelList
+	var staticDeps bazel.LabelList
+
 	archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
 	for axis, configToProps := range archVariantProps {
 		for config, _props := range configToProps {
@@ -2282,18 +2293,18 @@
 	javaSrcPartition := "java"
 	protoSrcPartition := "proto"
 	logtagSrcPartition := "logtag"
+	aidlSrcPartition := "aidl"
 	srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
 		javaSrcPartition:   bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
 		logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
 		protoSrcPartition:  android.ProtoSrcLabelPartition,
+		aidlSrcPartition:   android.AidlSrcLabelPartition,
 	})
 
 	javaSrcs := srcPartitions[javaSrcPartition]
 
-	var logtagsSrcs bazel.LabelList
 	if !srcPartitions[logtagSrcPartition].IsEmpty() {
 		logtagsLibName := m.Name() + "_logtags"
-		logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
 		ctx.CreateBazelTargetModule(
 			bazel.BazelTargetModuleProperties{
 				Rule_class:        "event_log_tags",
@@ -2304,8 +2315,45 @@
 				Srcs: srcPartitions[logtagSrcPartition],
 			},
 		)
+
+		logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
+		javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
 	}
-	javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
+
+	if !srcPartitions[aidlSrcPartition].IsEmpty() {
+		aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool {
+			return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
+		})
+
+		if !aidlSrcs.IsEmpty() {
+			aidlLibName := m.Name() + "_aidl_library"
+			ctx.CreateBazelTargetModule(
+				bazel.BazelTargetModuleProperties{
+					Rule_class:        "aidl_library",
+					Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+				},
+				android.CommonAttributes{Name: aidlLibName},
+				&aidlLibraryAttributes{
+					Srcs: aidlSrcs,
+				},
+			)
+			aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
+		}
+
+		javaAidlLibName := m.Name() + "_java_aidl_library"
+		ctx.CreateBazelTargetModule(
+			bazel.BazelTargetModuleProperties{
+				Rule_class:        "java_aidl_library",
+				Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl",
+			},
+			android.CommonAttributes{Name: javaAidlLibName},
+			&javaAidlLibraryAttributes{
+				Deps: aidlLibs,
+			},
+		)
+
+		staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName})
+	}
 
 	var javacopts []string
 	if m.properties.Javacflags != nil {
@@ -2331,14 +2379,10 @@
 		Javacopts: bazel.MakeStringListAttribute(javacopts),
 	}
 
-	depLabels := &javaDependencyLabels{}
-
-	var deps bazel.LabelList
 	if m.properties.Libs != nil {
 		deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
 	}
 
-	var staticDeps bazel.LabelList
 	if m.properties.Static_libs != nil {
 		staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs))))
 	}
@@ -2352,6 +2396,7 @@
 	// and so this should be a static dependency.
 	staticDeps.Add(protoDepLabel)
 
+	depLabels := &javaDependencyLabels{}
 	depLabels.Deps = bazel.MakeLabelListAttribute(deps)
 	depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
 
@@ -2376,7 +2421,7 @@
 			// TODO(b/220869005) remove forced dependency on current public android.jar
 			deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
 		}
-	} else if !depLabels.Deps.IsEmpty() {
+	} else if !deps.IsEmpty() {
 		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
 	}
 
diff --git a/java/java_test.go b/java/java_test.go
index bfd97eb..7f0cea7 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1747,3 +1747,37 @@
 	android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
 	android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
 }
+
+func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) {
+	bazelOutputBaseDir := filepath.Join("out", "bazel")
+	result := android.GroupFixturePreparers(
+		PrepareForIntegrationTestWithJava,
+		android.FixtureModifyConfig(func(config android.Config) {
+			config.BazelContext = android.MockBazelContext{
+				OutputBaseDir: bazelOutputBaseDir,
+			}
+		}),
+	).RunTest(t)
+
+	ctx := &android.TestPathContext{TestResult: result}
+
+	srcDirectory := filepath.Join("frameworks", "base")
+	srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java")
+	bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory)
+	bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded)
+	srcs := android.Paths{
+		android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"),
+		android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"),
+		android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"),
+		android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"),
+	}
+	dirsAlreadyIncluded := android.Paths{
+		android.PathForTesting(srcDirectoryAlreadyIncluded),
+	}
+
+	expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base"
+	flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded)
+	if flags != expectedFlags {
+		t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
+	}
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index 9acbfb3..e676837 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.62.0.p1"
+	RustDefaultVersion = "1.63.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2021"
 	Stdlibs            = []string{
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 4b2f795..ac3c177 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -33,6 +33,10 @@
 SOONG_OUTPUT_DIR="$OUTPUT_DIR/soong"
 BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
 
+function call_bazel() {
+  tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
+}
+
 function cleanup {
   # call bazel clean because some bazel outputs don't have w bits.
   call_bazel clean
@@ -54,9 +58,6 @@
 ######################
 build/soong/soong_ui.bash --make-mode BP2BUILD_VERBOSE=1 --skip-soong-tests bp2build
 
-function call_bazel() {
-  tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
-}
 BAZEL_OUT="$(call_bazel info output_path)"
 
 call_bazel build --config=bp2build --config=ci --config=android_arm \
diff --git a/tests/lib.sh b/tests/lib.sh
index 6210e77..643b46a 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -93,6 +93,7 @@
   symlink_directory external/go-cmp
   symlink_directory external/golang-protobuf
   symlink_directory external/starlark-go
+  symlink_directory system/tools/aidl
 
   touch "$MOCK_TOP/Android.bp"
 }