apex: apex_available with prefix

We now support prefix form (com.foo.*) in apex_available list.

Bug: 360265761
Test: m --no-skip-soong-tests
Change-Id: I50ab884651dd6321950cfd4563b59ef3ed0f07fd
diff --git a/android/apex.go b/android/apex.go
index ef4cf82..028be57 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -280,6 +280,7 @@
 	//
 	// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
 	// "//apex_available:platform" refers to non-APEX partitions like "system.img".
+	// Prefix pattern (com.foo.*) can be used to match with any APEX name with the prefix(com.foo.).
 	// Default is ["//apex_available:platform"].
 	Apex_available []string
 
@@ -491,10 +492,27 @@
 	if len(apex_available) == 0 {
 		return what == AvailableToPlatform
 	}
-	return InList(what, apex_available) ||
-		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
-		(what == "com.google.mainline.primary.libs") || // TODO b/248601389
-		(what == "com.google.mainline.go.primary.libs") // TODO b/248601389
+
+	// TODO b/248601389
+	if what == "com.google.mainline.primary.libs" || what == "com.google.mainline.go.primary.libs" {
+		return true
+	}
+
+	for _, apex_name := range apex_available {
+		// exact match.
+		if apex_name == what {
+			return true
+		}
+		// //apex_available:anyapex matches with any apex name, but not //apex_available:platform
+		if apex_name == AvailableToAnyApex && what != AvailableToPlatform {
+			return true
+		}
+		// prefix match.
+		if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
+			return true
+		}
+	}
+	return false
 }
 
 // Implements ApexModule
@@ -523,6 +541,19 @@
 		if n == AvailableToPlatform || n == AvailableToAnyApex {
 			continue
 		}
+		// Prefix pattern should end with .* and has at least two components.
+		if strings.Contains(n, "*") {
+			if !strings.HasSuffix(n, ".*") {
+				mctx.PropertyErrorf("apex_available", "Wildcard should end with .* like com.foo.*")
+			}
+			if strings.Count(n, ".") < 2 {
+				mctx.PropertyErrorf("apex_available", "Wildcard requires two or more components like com.foo.*")
+			}
+			if strings.Count(n, "*") != 1 {
+				mctx.PropertyErrorf("apex_available", "Wildcard is not allowed in the middle.")
+			}
+			continue
+		}
 		if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
 			mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
 		}