Vulkan semaphore opaque fd support

This CL adds Vulkan semaphore opaque fd support. It associates guest fd
with host fd by creating a guest mem file and write the host fd into it.
However, they are not 1 to 1 especially when dup() is used on guest fd,
which results in fd leaks.

It fixes dEQP VK must-pass opaque_fd tests, though.

BUG: 123905820

+ Patch up on_vkCreateSemaphore to keep extension structs when
on Android.

Change-Id: Id7d2b4e0e66d08db51d4407883ace819ec1c1a32
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 6d7c399..27141a9 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -113,6 +113,29 @@
 #include <stdlib.h>
 #include <sync/sync.h>
 
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+#ifdef HOST_BUILD
+#include "android/utils/tempfile.h"
+#endif
+
+#ifndef HAVE_MEMFD_CREATE
+static inline int
+memfd_create(const char *name, unsigned int flags) {
+#ifdef HOST_BUILD
+    TempFile* tmpFile = tempfile_create();
+    return open(tempfile_path(tmpFile), O_RDWR);
+    // TODO: Windows is not suppose to support VkSemaphoreGetFdInfoKHR
+#else
+    return syscall(SYS_memfd_create, name, flags);
+#endif
+}
+#endif // !HAVE_MEMFD_CREATE
+#endif // !VK_USE_PLATFORM_ANDROID_KHR
+
 #define RESOURCE_TRACKER_DEBUG 0
 
 #if RESOURCE_TRACKER_DEBUG
@@ -660,10 +683,12 @@
         const char*,
         uint32_t* pPropertyCount,
         VkExtensionProperties* pProperties) {
-
         std::vector<const char*> allowedExtensionNames = {
             "VK_KHR_get_physical_device_properties2",
             "VK_KHR_sampler_ycbcr_conversion",
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+            "VK_KHR_external_semaphore_capabilities",
+#endif
             // TODO:
             // VK_KHR_external_memory_capabilities
         };
@@ -735,6 +760,10 @@
             "VK_KHR_dedicated_allocation",
             "VK_KHR_bind_memory2",
             "VK_KHR_sampler_ycbcr_conversion",
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+            "VK_KHR_external_semaphore",
+            "VK_KHR_external_semaphore_fd",
+#endif
             // "VK_KHR_maintenance2",
             // "VK_KHR_maintenance3",
             // TODO:
@@ -792,6 +821,7 @@
             }
         }
 
+
         return VK_SUCCESS;
     }
 
@@ -1770,15 +1800,18 @@
         VkEncoder* enc = (VkEncoder*)context;
 
         VkSemaphoreCreateInfo finalCreateInfo = *pCreateInfo;
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+        // vk_init_struct_chain initializes pNext to nullptr
         vk_struct_common* structChain = vk_init_struct_chain(
             (vk_struct_common*)(&finalCreateInfo));
-        structChain->pNext = nullptr;
 
         VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr =
             (VkExportSemaphoreCreateInfoKHR*)vk_find_struct((vk_struct_common*)pCreateInfo,
                 VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR);
 
         bool exportFence = false;
+
         if (exportSemaphoreInfoPtr) {
             exportFence =
                 exportSemaphoreInfoPtr->handleTypes &
@@ -1786,13 +1819,17 @@
             // TODO: add host side export struct info.
         }
 
+#endif
         input_result = enc->vkCreateSemaphore(
             device, &finalCreateInfo, pAllocator, pSemaphore);
 
         zx_handle_t event_handle = ZX_HANDLE_INVALID;
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
         if (exportFence) {
             zx_event_create(0, &event_handle);
         }
+#endif
 
         AutoLock lock(mLock);
 
@@ -1814,6 +1851,63 @@
         enc->vkDestroySemaphore(device, semaphore, pAllocator);
     }
 
+    // https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#vkGetSemaphoreFdKHR
+    // Each call to vkGetSemaphoreFdKHR must create a new file descriptor and transfer ownership
+    // of it to the application. To avoid leaking resources, the application must release ownership
+    // of the file descriptor when it is no longer needed.
+    VkResult on_vkGetSemaphoreFdKHR(
+        void* context, VkResult,
+        VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
+        int* pFd) {
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkEncoder* enc = (VkEncoder*)context;
+        int hostFd = 0;
+        VkResult result = enc->vkGetSemaphoreFdKHR(device, pGetFdInfo, &hostFd);
+        if (result != VK_SUCCESS) {
+            return result;
+        }
+        *pFd = memfd_create("vk_opaque_fd", 0);
+        write(*pFd, &hostFd, sizeof(hostFd));
+        return VK_SUCCESS;
+#else
+        (void)context;
+        (void)device;
+        (void)pGetFdInfo;
+        (void)pFd;
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+#endif
+    }
+
+    VkResult on_vkImportSemaphoreFdKHR(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo) {
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkEncoder* enc = (VkEncoder*)context;
+        if (input_result != VK_SUCCESS) {
+            return input_result;
+        }
+        int fd = pImportSemaphoreFdInfo->fd;
+        int err = lseek(fd, 0, SEEK_SET);
+        if (err == -1) {
+            ALOGE("lseek fail on import semaphore");
+        }
+        int hostFd = 0;
+        read(fd, &hostFd, sizeof(hostFd));
+        VkImportSemaphoreFdInfoKHR tmpInfo = *pImportSemaphoreFdInfo;
+        tmpInfo.fd = hostFd;
+        VkResult result = enc->vkImportSemaphoreFdKHR(device, &tmpInfo);
+        close(fd);
+        return result;
+#else
+        (void)context;
+        (void)input_result;
+        (void)device;
+        (void)pImportSemaphoreFdInfo;
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+#endif
+    }
+
     VkResult on_vkQueueSubmit(
         void* context, VkResult input_result,
         VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) {
@@ -2427,6 +2521,21 @@
         context, input_result, queue, submitCount, pSubmits, fence);
 }
 
+VkResult ResourceTracker::on_vkGetSemaphoreFdKHR(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
+    int* pFd) {
+    return mImpl->on_vkGetSemaphoreFdKHR(context, input_result, device, pGetFdInfo, pFd);
+}
+
+VkResult ResourceTracker::on_vkImportSemaphoreFdKHR(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo) {
+    return mImpl->on_vkImportSemaphoreFdKHR(context, input_result, device, pImportSemaphoreFdInfo);
+}
+
 void ResourceTracker::unwrap_VkNativeBufferANDROID(
     const VkImageCreateInfo* pCreateInfo,
     VkImageCreateInfo* local_pCreateInfo) {