Link type check for Android.bp defined Java modules

Link-type is also checked among Java modules defined in Soong. Until
now, the check has been done in between Soong/Make and Make/Make.

With this, a Java module can't depend on another Java module built with
larger API surface. For example, a java library built with Android SDK
(sdk_version: "current") can't link to a library built without SDK.

Bug: 73829976
Test: m -j

Change-Id: I64277be6e65e8535aad951b4f08f8d10b67abe66
Merged-In: I64277be6e65e8535aad951b4f08f8d10b67abe66
(cherry picked from commit f3586661e8525125f529082fee14edec32d73e04)
diff --git a/java/java.go b/java/java.go
index 06dce05..5785681 100644
--- a/java/java.go
+++ b/java/java.go
@@ -591,12 +591,56 @@
 	}
 }
 
+type linkType int
+
+const (
+	javaCore linkType = iota
+	javaSdk
+	javaSystem
+	javaPlatform
+)
+
+func getLinkType(m *Module) linkType {
+	ver := String(m.deviceProperties.Sdk_version)
+	if strings.HasPrefix(ver, "core_") {
+		return javaCore
+	} else if strings.HasPrefix(ver, "system_") {
+		return javaSystem
+	} else if _, err := strconv.Atoi(ver); err == nil || ver == "current" {
+		return javaSdk
+	} else {
+		// test_current falls back here as well
+		return javaPlatform
+	}
+}
+
 func checkLinkType(ctx android.ModuleContext, from *Module, to *Library, tag dependencyTag) {
-	if strings.HasPrefix(String(from.deviceProperties.Sdk_version), "core_") {
-		if !strings.HasPrefix(String(to.deviceProperties.Sdk_version), "core_") {
-			ctx.ModuleErrorf("depends on other library %q using non-core Java APIs",
+	myLinkType := getLinkType(from)
+	otherLinkType := getLinkType(&to.Module)
+	commonMessage := "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source."
+
+	switch myLinkType {
+	case javaCore:
+		if otherLinkType != javaCore {
+			ctx.ModuleErrorf("compiles against core Java API, but dependency %q is compiling against non-core Java APIs."+commonMessage,
 				ctx.OtherModuleName(to))
 		}
+		break
+	case javaSdk:
+		if otherLinkType != javaCore && otherLinkType != javaSdk {
+			ctx.ModuleErrorf("compiles against Android API, but dependency %q is compiling against non-public Android API."+commonMessage,
+				ctx.OtherModuleName(to))
+		}
+		break
+	case javaSystem:
+		if otherLinkType == javaPlatform {
+			ctx.ModuleErrorf("compiles against system API, but dependency %q is compiling against private API."+commonMessage,
+				ctx.OtherModuleName(to))
+		}
+		break
+	case javaPlatform:
+		// no restriction on link-type
+		break
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 6e3ada4..6b730da 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -818,12 +818,14 @@
 		java_library {
 			name: "foo",
 			srcs: ["a.java"],
+			sdk_version: "14",
 		}
 
 		java_library {
 			name: "bar",
 			srcs: ["b.java"],
 			static_libs: ["foo"],
+			sdk_version: "14",
 		}
 
 		java_library {