convert .aidl srcs for java_library

Test: go test ./bp2build
Test: b build //frameworks/base/services/tests/servicestests/aidl:servicestests-aidl
Test: enable //packages/modules/NetworkStack/common/networkstackclient
    && disable restriction on Android SDK in javaLibraryBp2Build
    && b build //packages/modules/NetworkStack/common/networkstackclient:ipmemorystore-aidl-interfaces-V10-java
Change-Id: Ifb817daf09a3983ea1c84948ed9f02a79f95784b
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 5c79fa2..0bc7462 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -157,6 +157,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,
@@ -408,6 +409,7 @@
 		"linker_config",
 		"java_import",
 		"java_import_host",
+		"aidl_interface_headers",
 	}
 
 	Bp2buildModuleDoNotConvertList = []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/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/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/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.")
 	}