Support VNDK extensions

This commit adds `extends: "name"` property and provides basic support
to VNDK extensions.  This is the simplest example:

```
cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}
```

A vndk extension library must extend an existing vndk library which has
`vendor_available: true`.  These two libraries must have the same
`support_system_process` property.

VNDK-ext libraries are installed to `/vendor/lib[64]/vndk` and
VNDK-SP-ext libraries are installed to `/vendor/lib[64]/vndk-sp` by
default.

If there is a matching abi-dumps in `prebuilts/abi-dumps`,
`header-abi-diff` will be invoked to check for ABI breakages.

Bug: 38340960

Test: lunch aosp_walleye-userdebug && make -j8   # runs unit tests

Test: lunch aosp_arm-userdebug && make -j8  # build a target w/o VNDK

Test: Create a lsdump for a vndk lib, add an exported API to vndk lib,
and build fails as expected.

Test: Create a lsdump for a vndk lib, create an vndk extension lib with
extra API, and build succeeds as expected.

Test: Create libutils_ext, add an extra function to libutils_ext, and
call it from a HIDL service.

Change-Id: Iba90e08848ee99814405457f047321e6b52b2df0
diff --git a/cc/vndk.go b/cc/vndk.go
index a61b74c..d417bea 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -42,6 +42,9 @@
 		// the module is VNDK-core and can link to other VNDK-core,
 		// VNDK-SP or LL-NDK modules only.
 		Support_system_process *bool
+
+		// Extending another module
+		Extends *string
 	}
 }
 
@@ -67,17 +70,31 @@
 	return Bool(vndk.Properties.Vndk.Support_system_process)
 }
 
+func (vndk *vndkdep) isVndkExt() bool {
+	return vndk.Properties.Vndk.Extends != nil
+}
+
+func (vndk *vndkdep) getVndkExtendsModuleName() string {
+	return String(vndk.Properties.Vndk.Extends)
+}
+
 func (vndk *vndkdep) typeName() string {
 	if !vndk.isVndk() {
 		return "native:vendor"
 	}
-	if !vndk.isVndkSp() {
-		return "native:vendor:vndk"
+	if !vndk.isVndkExt() {
+		if !vndk.isVndkSp() {
+			return "native:vendor:vndk"
+		}
+		return "native:vendor:vndksp"
 	}
-	return "native:vendor:vndksp"
+	if !vndk.isVndkSp() {
+		return "native:vendor:vndkext"
+	}
+	return "native:vendor:vndkspext"
 }
 
-func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module) {
+func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag dependencyTag) {
 	if to.linker == nil {
 		return
 	}
@@ -109,11 +126,43 @@
 			vndk.typeName(), to.Name())
 		return
 	}
+	if tag == vndkExtDepTag {
+		// Ensure `extends: "name"` property refers a vndk module that has vendor_available
+		// and has identical vndk properties.
+		if to.vndkdep == nil || !to.vndkdep.isVndk() {
+			ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name())
+			return
+		}
+		if vndk.isVndkSp() != to.vndkdep.isVndkSp() {
+			ctx.ModuleErrorf(
+				"`extends` refers a module %q with mismatched support_system_process",
+				to.Name())
+			return
+		}
+		if !Bool(to.VendorProperties.Vendor_available) {
+			ctx.ModuleErrorf(
+				"`extends` refers module %q which does not have `vendor_available: true`",
+				to.Name())
+			return
+		}
+	}
 	if to.vndkdep == nil {
 		return
 	}
-	if (vndk.isVndk() && !to.vndkdep.isVndk()) || (vndk.isVndkSp() && !to.vndkdep.isVndkSp()) {
-		ctx.ModuleErrorf("(%s) should not link to %q(%s)",
+
+	// VNDK-core and VNDK-SP must not depend on VNDK extensions.
+	if (vndk.isVndk() || vndk.isVndkSp()) && !vndk.isVndkExt() && to.vndkdep.isVndkExt() {
+		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
 	}
@@ -149,7 +198,7 @@
 			prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
 			if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
 				name := strings.TrimPrefix(m.Name(), "prebuilt_")
-				if m.vndkdep.isVndk() {
+				if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
 					vndkLibrariesLock.Lock()
 					defer vndkLibrariesLock.Unlock()
 					if m.vndkdep.isVndkSp() {