Merge "Allow platform modules to link to vendor public libraries" into pi-dev
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 0a18fc6..f315b1d 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -174,6 +174,7 @@
 }
 
 func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.TestContext {
+	t.Helper()
 	ctx := createTestContext(t, config, bp)
 
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
@@ -185,6 +186,7 @@
 }
 
 func testCc(t *testing.T, bp string) *android.TestContext {
+	t.Helper()
 	config := android.TestArchConfig(buildDir, nil)
 	config.ProductVariables.DeviceVndkVersion = StringPtr("current")
 	config.ProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -193,6 +195,7 @@
 }
 
 func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
+	t.Helper()
 	config := android.TestArchConfig(buildDir, nil)
 	config.ProductVariables.Platform_vndk_version = StringPtr("VER")
 
@@ -200,6 +203,7 @@
 }
 
 func testCcError(t *testing.T, pattern string, bp string) {
+	t.Helper()
 	config := android.TestArchConfig(buildDir, nil)
 	config.ProductVariables.DeviceVndkVersion = StringPtr("current")
 	config.ProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -256,6 +260,8 @@
 func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
 	isVndkSp bool, extends string) {
 
+	t.Helper()
+
 	mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
 	if !mod.hasVendorVariant() {
 		t.Error("%q must have vendor variant", name)
@@ -339,6 +345,107 @@
 	checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
 }
 
+func TestVndkDepError(t *testing.T) {
+	// Check whether an error is emitted when a VNDK lib depends on a system lib.
+	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			shared_libs: ["libfwk"],  // Cause error
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libfwk",
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK lib depends on a vendor lib.
+	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			shared_libs: ["libvendor"],  // Cause error
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-SP lib depends on a system lib.
+	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			shared_libs: ["libfwk"],  // Cause error
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libfwk",
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-SP lib depends on a vendor lib.
+	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			shared_libs: ["libvendor"],  // Cause error
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+			nocrt: true,
+		}
+	`)
+
+	// Check whether an error is emitted when a VNDK-SP lib depends on a VNDK lib.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			shared_libs: ["libvndk"],  // Cause error
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+	`)
+}
+
 func TestVndkExt(t *testing.T) {
 	// This test checks the VNDK-Ext properties.
 	ctx := testCc(t, `
@@ -365,7 +472,7 @@
 	checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
 }
 
-func TestVndkExtNoVndk(t *testing.T) {
+func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
 	// This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
 	ctx := testCcNoVndk(t, `
 		cc_library {
@@ -486,7 +593,7 @@
 }
 
 func TestVndkExtVendorAvailableFalseError(t *testing.T) {
-	// This test ensures an error is emitted when a vndk-ext library extends a vndk library
+	// This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
 	// with `vendor_available: false`.
 	testCcError(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
 		cc_library {
@@ -510,8 +617,8 @@
 	`)
 }
 
-func TestVendorModuleUsesVndkExt(t *testing.T) {
-	// This test ensures a vendor module can depend on a vndk-ext library.
+func TestVendorModuleUseVndkExt(t *testing.T) {
+	// This test ensures a vendor module can depend on a VNDK-Ext library.
 	testCc(t, `
 		cc_library {
 			name: "libvndk",
@@ -563,8 +670,8 @@
 	`)
 }
 
-func TestVndkExtUsesVendorLib(t *testing.T) {
-	// This test ensures a vndk-ext library can depend on a vendor library.
+func TestVndkExtUseVendorLib(t *testing.T) {
+	// This test ensures a VNDK-Ext library can depend on a vendor library.
 	testCc(t, `
 		cc_library {
 			name: "libvndk",
@@ -592,12 +699,9 @@
 			nocrt: true,
 		}
 	`)
-}
 
-func TestVndkSpExtUsesVendorLibError(t *testing.T) {
-	// This test ensures an error is emitted if a vndk-sp-ext library depends on a vendor
-	// library.
-	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+	// This test ensures a VNDK-SP-Ext library can depend on a vendor library.
+	testCc(t, `
 		cc_library {
 			name: "libvndk_sp",
 			vendor_available: true,
@@ -628,9 +732,91 @@
 	`)
 }
 
-func TestVndkUsesVndkExtError(t *testing.T) {
-	// This test ensures an error is emitted if a vndk/vndk-sp library depends on a
-	// vndk-ext/vndk-sp-ext library.
+func TestVndkSpExtUseVndkError(t *testing.T) {
+	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
+	// library.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp_ext",
+			vendor: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk_sp",
+				support_system_process: true,
+			},
+			shared_libs: ["libvndk"],  // Cause an error
+			nocrt: true,
+		}
+	`)
+
+	// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK-Ext
+	// library.
+	testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
+		cc_library {
+			name: "libvndk",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_ext",
+			vendor: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk",
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp",
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+			nocrt: true,
+		}
+
+		cc_library {
+			name: "libvndk_sp_ext",
+			vendor: true,
+			vndk: {
+				enabled: true,
+				extends: "libvndk_sp",
+				support_system_process: true,
+			},
+			shared_libs: ["libvndk_ext"],  // Cause an error
+			nocrt: true,
+		}
+	`)
+}
+
+func TestVndkUseVndkExtError(t *testing.T) {
+	// This test ensures an error is emitted if a VNDK/VNDK-SP library depends on a
+	// VNDK-Ext/VNDK-SP-Ext library.
 	testCcError(t, "dependency \".*\" of \".*\" missing variant", `
 		cc_library {
 			name: "libvndk",
diff --git a/cc/vndk.go b/cc/vndk.go
index a0d338b..5a24a98 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -150,22 +150,39 @@
 		return
 	}
 
-	// VNDK-core and VNDK-SP must not depend on VNDK extensions.
-	if (vndk.isVndk() || vndk.isVndkSp()) && !vndk.isVndkExt() && to.vndkdep.isVndkExt() {
+	// Check the dependencies of VNDK shared libraries.
+	if !vndkIsVndkDepAllowed(vndk, to.vndkdep) {
 		ctx.ModuleErrorf("(%s) should not link to %q (%s)",
 			vndk.typeName(), to.Name(), to.vndkdep.typeName())
 		return
 	}
+}
 
-	// VNDK-core must be only depend on VNDK-SP or LL-NDK. VNDK-SP must only depend on
-	// LL-NDK, regardless the extension status. VNDK-Ext may depend on vendor libraries, but
-	// VNDK-SP-Ext must remain self-contained.
-	if (vndk.isVndk() && !to.vndkdep.isVndk() && !vndk.isVndkExt()) ||
-		(vndk.isVndkSp() && !to.vndkdep.isVndkSp()) {
-		ctx.ModuleErrorf("(%s) should not link to %q (%s)",
-			vndk.typeName(), to.Name(), to.vndkdep.typeName())
-		return
+func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) bool {
+	// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
+	if from.isVndkExt() {
+		if from.isVndkSp() {
+			// VNDK-SP-Ext may depend on VNDK-SP, VNDK-SP-Ext, or vendor libs (excluding
+			// VNDK and VNDK-Ext).
+			return to.isVndkSp() || !to.isVndk()
+		}
+		// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
+		return true
 	}
+	if from.isVndk() {
+		if to.isVndkExt() {
+			// VNDK-core and VNDK-SP must not depend on VNDK extensions.
+			return false
+		}
+		if from.isVndkSp() {
+			// VNDK-SP must only depend on VNDK-SP.
+			return to.isVndkSp()
+		}
+		// VNDK-core may depend on VNDK-core or VNDK-SP.
+		return to.isVndk()
+	}
+	// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
+	return true
 }
 
 var (