[vulkan] Fill in missing pieces for AHardwareBuffer and sync fd supporti

bug: 122080810

- Add goldfish_sync_signal ioctl.
This requires a newer guest kernel.
- Add external AHB format, which is really a Vulkan format
(VK_FORMAT_G8B8G8R8_422_UNORM);
this is meant to satisfy the external buffer path of AHB/Vulkan interop.
- Use this external format (which is not really external)
when appropriate VkExternalFormatANDROID structs are passed to either
vkCreateImage or vkCreateSamplerYcbcrConversion.
- Do not allow any kind of buffer/image, external or not,
to use memory types that are not device local nor host visible.
These memory types occur on NVIDIA and guest apps will land on
those memory types if we so much as look at it wrong.
- Do not pass through dedicated allocation info to the host
if we are importing AHardwareBuffer. That's because on the host,
we are not using dedicated allocations for the ColorBuffer,
and according to the spec, if we import allocate a dedicated-image
memory, the memory that we imported must also be a dedicated-image
allocation, and the image must be identical to boot.
- Advertise that dedicated allocation is required and preferred
for external buffers/images, in line with the AHardwareBuffer spec.
- Integrate the sync device; similarly to Fuchsia events,
wait on pre signal semaphores sync fd's and signal post wait sync fd's.
- Finally, treat AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM as
VK_FORMAT_R8G8B8A8_UNORM, not VK_FORMAT_R8G8B8_UNORM.

Change-Id: I995ac11071867ee55adaeb1acdee040bba0a8762
diff --git a/system/egl/goldfish_sync.h b/system/egl/goldfish_sync.h
index ec29bee..18e3083 100644
--- a/system/egl/goldfish_sync.h
+++ b/system/egl/goldfish_sync.h
@@ -15,20 +15,26 @@
 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_SYNC_H
 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_SYNC_H
 
+#define GOLDFISH_SYNC_VULKAN_SEMAPHORE_SYNC 0x00000001
+
 #ifdef HOST_BUILD
 
 static __inline__ int goldfish_sync_open() {
     return 0;
 }
 
-static __inline__ int goldfish_sync_close(int sync_fd) {
+static __inline__ int goldfish_sync_close(int) {
     return 0;
 }
 
-static __inline__ int goldfish_sync_queue_work(int goldfish_sync_fd,
-                                                uint64_t host_glsync,
-                                                uint64_t host_thread,
-                                                int* fd_out) {
+static __inline__ int goldfish_sync_queue_work(int,
+                                               uint64_t,
+                                               uint64_t,
+                                               int*) {
+    return 0;
+}
+
+static __inline__ int goldfish_sync_signal(int goldfish_sync_fd) {
     return 0;
 }
 
@@ -58,6 +64,7 @@
 };
 
 #define GOLDFISH_SYNC_IOC_QUEUE_WORK	_IOWR(GOLDFISH_SYNC_IOC_MAGIC, 0, struct goldfish_sync_ioctl_info)
+#define GOLDFISH_SYNC_IOC_SIGNAL	_IOWR(GOLDFISH_SYNC_IOC_MAGIC, 1, struct goldfish_sync_ioctl_info)
 
 static __inline__ int goldfish_sync_open() {
     return open("/dev/goldfish_sync", O_RDWR);
@@ -99,6 +106,10 @@
     return err;
 }
 
+static __inline__ int goldfish_sync_signal(int goldfish_sync_fd) {
+    return ioctl(goldfish_sync_fd, GOLDFISH_SYNC_IOC_SIGNAL, 0);
+}
+
 #endif // !HOST_BUILD
 
 #endif
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 943ac96..d5ebf2d 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -1712,7 +1712,8 @@
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversion");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateSamplerYcbcrConversion_VkResult_return = (VkResult)0;
-    vkCreateSamplerYcbcrConversion_VkResult_return = vkEnc->vkCreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+    auto resources = ResourceTracker::get();
+    vkCreateSamplerYcbcrConversion_VkResult_return = resources->on_vkCreateSamplerYcbcrConversion(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pYcbcrConversion);
     return vkCreateSamplerYcbcrConversion_VkResult_return;
 }
 static void entry_vkDestroySamplerYcbcrConversion(
@@ -2747,7 +2748,8 @@
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversionKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateSamplerYcbcrConversionKHR_VkResult_return = (VkResult)0;
-    vkCreateSamplerYcbcrConversionKHR_VkResult_return = vkEnc->vkCreateSamplerYcbcrConversionKHR(device, pCreateInfo, pAllocator, pYcbcrConversion);
+    auto resources = ResourceTracker::get();
+    vkCreateSamplerYcbcrConversionKHR_VkResult_return = resources->on_vkCreateSamplerYcbcrConversionKHR(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pYcbcrConversion);
     return vkCreateSamplerYcbcrConversionKHR_VkResult_return;
 }
 static void entry_vkDestroySamplerYcbcrConversionKHR(
diff --git a/system/vulkan_enc/AndroidHardwareBuffer.cpp b/system/vulkan_enc/AndroidHardwareBuffer.cpp
index 9d756a0..620159d 100644
--- a/system/vulkan_enc/AndroidHardwareBuffer.cpp
+++ b/system/vulkan_enc/AndroidHardwareBuffer.cpp
@@ -79,8 +79,7 @@
         ahbFormatProps->format =
             vk_format_from_android(desc.format);
 
-        // Just don't, for now
-        ahbFormatProps->externalFormat = 0;
+        ahbFormatProps->externalFormat = VK_FORMAT_G8B8G8R8_422_UNORM;
 
         // The formatFeatures member must include
         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
@@ -121,13 +120,13 @@
         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
     }
 
-    // Disallow host visible heaps for now
+    // Disallow host visible and noflags heaps for now
     // (hard to make actual dedicated allocs)
     uint32_t memoryTypeBits = 0;
     for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
-        memoryTypeBits |=
-            (!isHostVisibleMemoryTypeIndexForGuest(
-             hostMemVirtInfo, i)) << i;
+        if (isNoFlagsMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
+        if (isHostVisibleMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
+        memoryTypeBits |= (1 << i);
     }
 
     pProperties->memoryTypeBits = memoryTypeBits;
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
index 930cdd4..8e254d0 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
@@ -188,6 +188,28 @@
     return props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
 }
 
+bool isDeviceLocalMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index) {
+
+    const auto& props =
+        info->virtualizationSupported ?
+        info->guestMemoryProperties :
+        info->hostMemoryProperties;
+
+    return props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+}
+
+bool isNoFlagsMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index) {
+    const auto& props =
+        info->virtualizationSupported ?
+        info->guestMemoryProperties :
+        info->hostMemoryProperties;
+    return props.memoryTypes[index].propertyFlags == 0;
+}
+
 VkResult finishHostMemAllocInit(
     VkEncoder*,
     VkDevice device,
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.h b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
index 10afc46..4f8651b 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.h
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
@@ -63,6 +63,14 @@
     const HostVisibleMemoryVirtualizationInfo* info,
     uint32_t index);
 
+bool isDeviceLocalMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index);
+
+bool isNoFlagsMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index);
+
 struct HostMemAlloc {
     bool initialized = false;
     VkResult initResult = VK_SUCCESS;
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index fe1438b..5d39822 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -19,6 +19,8 @@
 
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
 
+#include "../egl/goldfish_sync.h"
+
 typedef uint32_t zx_handle_t;
 #define ZX_HANDLE_INVALID         ((zx_handle_t)0)
 void zx_handle_close(zx_handle_t) { }
@@ -102,6 +104,7 @@
 #include "gralloc_cb.h"
 #include "goldfish_address_space.h"
 #include "goldfish_vk_private_defs.h"
+#include "vk_format_info.h"
 #include "vk_util.h"
 
 #include <string>
@@ -271,6 +274,7 @@
     struct VkSemaphore_Info {
         VkDevice device;
         zx_handle_t eventHandle = ZX_HANDLE_INVALID;
+        int syncFd = -1;
     };
 
 
@@ -792,13 +796,17 @@
         }
 
         bool hostHasWin32ExternalSemaphore =
-            getHostInstanceExtensionIndex(
+            getHostDeviceExtensionIndex(
                 "VK_KHR_external_semaphore_win32") != -1;
 
         bool hostHasPosixExternalSemaphore =
-            getHostInstanceExtensionIndex(
+            getHostDeviceExtensionIndex(
                 "VK_KHR_external_semaphore_fd") != -1;
 
+        ALOGD("%s: host has ext semaphore? win32 %d posix %d\n", __func__,
+                hostHasWin32ExternalSemaphore,
+                hostHasPosixExternalSemaphore);
+
         bool hostSupportsExternalSemaphore =
             hostHasWin32ExternalSemaphore ||
             hostHasPosixExternalSemaphore;
@@ -1207,6 +1215,9 @@
                 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO);
 
         bool shouldPassThroughDedicatedAllocInfo =
+            !exportAllocateInfoPtr &&
+            !importAhbInfoPtr &&
+            !importPhysAddrInfoPtr &&
             !isHostVisibleMemoryTypeIndexForGuest(
                 &mHostVisibleMemoryVirtInfo,
                 pAllocateInfo->memoryTypeIndex);
@@ -1333,6 +1344,7 @@
         }
 
         if (ahw) {
+            ALOGD("%s: AHBIMPORT", __func__);
             const native_handle_t *handle =
                 AHardwareBuffer_getNativeHandle(ahw);
             const cb_handle_t* cb_handle =
@@ -1593,10 +1605,25 @@
         // no-op
     }
 
+    uint32_t transformNonExternalResourceMemoryTypeBitsForGuest(
+        uint32_t hostBits) {
+        uint32_t res = 0;
+        for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
+            if (isNoFlagsMemoryTypeIndexForGuest(
+                    &mHostVisibleMemoryVirtInfo, i)) continue;
+            if (hostBits & (1 << i)) {
+                res |= (1 << i);
+            }
+        }
+        return res;
+    }
+
     uint32_t transformExternalResourceMemoryTypeBitsForGuest(
         uint32_t normalBits) {
         uint32_t res = 0;
         for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
+            if (isNoFlagsMemoryTypeIndexForGuest(
+                    &mHostVisibleMemoryVirtInfo, i)) continue;
             if (normalBits & (1 << i) &&
                 !isHostVisibleMemoryTypeIndexForGuest(
                     &mHostVisibleMemoryVirtInfo, i)) {
@@ -1606,6 +1633,13 @@
         return res;
     }
 
+    void transformNonExternalResourceMemoryRequirementsForGuest(
+        VkMemoryRequirements* reqs) {
+        reqs->memoryTypeBits =
+            transformNonExternalResourceMemoryTypeBitsForGuest(
+                reqs->memoryTypeBits);
+    }
+
     void transformExternalResourceMemoryRequirementsForGuest(
         VkMemoryRequirements* reqs) {
         reqs->memoryTypeBits =
@@ -1613,7 +1647,13 @@
                 reqs->memoryTypeBits);
     }
 
-    void transformExternalImageMemoryRequirementsForGuest(
+    void transformExternalResourceMemoryDedicatedRequirementsForGuest(
+        VkMemoryDedicatedRequirements* dedicatedReqs) {
+        dedicatedReqs->prefersDedicatedAllocation = VK_TRUE;
+        dedicatedReqs->requiresDedicatedAllocation = VK_TRUE;
+    }
+
+    void transformImageMemoryRequirementsForGuest(
         VkImage image,
         VkMemoryRequirements* reqs) {
 
@@ -1623,13 +1663,17 @@
         if (it == info_VkImage.end()) return;
 
         auto& info = it->second;
-        if (!info.external) return;
-        if (!info.externalCreateInfo.handleTypes) return;
+
+        if (!info.external ||
+            !info.externalCreateInfo.handleTypes) {
+            transformNonExternalResourceMemoryRequirementsForGuest(reqs);
+            return;
+        }
 
         transformExternalResourceMemoryRequirementsForGuest(reqs);
     }
 
-    void transformExternalBufferMemoryRequirementsForGuest(
+    void transformBufferMemoryRequirementsForGuest(
         VkBuffer buffer,
         VkMemoryRequirements* reqs) {
 
@@ -1639,12 +1683,80 @@
         if (it == info_VkBuffer.end()) return;
 
         auto& info = it->second;
-        if (!info.external) return;
-        if (!info.externalCreateInfo.handleTypes) return;
+
+        if (!info.external ||
+            !info.externalCreateInfo.handleTypes) {
+            transformNonExternalResourceMemoryRequirementsForGuest(reqs);
+            return;
+        }
 
         transformExternalResourceMemoryRequirementsForGuest(reqs);
     }
 
+    void transformImageMemoryRequirements2ForGuest(
+        VkImage image,
+        VkMemoryRequirements2* reqs2) {
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkImage.find(image);
+        if (it == info_VkImage.end()) return;
+
+        auto& info = it->second;
+
+        if (!info.external ||
+            !info.externalCreateInfo.handleTypes) {
+            transformNonExternalResourceMemoryRequirementsForGuest(
+                &reqs2->memoryRequirements);
+            return;
+        }
+
+        transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements);
+
+        VkMemoryDedicatedRequirements* dedicatedReqs =
+            (VkMemoryDedicatedRequirements*)
+            vk_find_struct(
+                (vk_struct_common*)reqs2,
+                VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS);
+
+        if (!dedicatedReqs) return;
+
+        transformExternalResourceMemoryDedicatedRequirementsForGuest(
+            dedicatedReqs);
+    }
+
+    void transformBufferMemoryRequirements2ForGuest(
+        VkBuffer buffer,
+        VkMemoryRequirements2* reqs2) {
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkBuffer.find(buffer);
+        if (it == info_VkBuffer.end()) return;
+
+        auto& info = it->second;
+
+        if (!info.external ||
+            !info.externalCreateInfo.handleTypes) {
+            transformNonExternalResourceMemoryRequirementsForGuest(
+                &reqs2->memoryRequirements);
+            return;
+        }
+
+        transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements);
+
+        VkMemoryDedicatedRequirements* dedicatedReqs =
+            (VkMemoryDedicatedRequirements*)
+            vk_find_struct(
+                (vk_struct_common*)reqs2,
+                VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS);
+
+        if (!dedicatedReqs) return;
+
+        transformExternalResourceMemoryDedicatedRequirementsForGuest(
+            dedicatedReqs);
+    }
+
     VkResult on_vkCreateImage(
         void* context, VkResult,
         VkDevice device, const VkImageCreateInfo *pCreateInfo,
@@ -1654,6 +1766,72 @@
 
         uint32_t cbHandle = 0;
 
+        VkImageCreateInfo localCreateInfo = *pCreateInfo;
+        VkNativeBufferANDROID localAnb;
+        VkExternalMemoryImageCreateInfo localExtImgCi;
+
+        VkImageCreateInfo* pCreateInfo_mut = &localCreateInfo;
+
+        VkNativeBufferANDROID* anbInfoPtr =
+            (VkNativeBufferANDROID*)
+            vk_find_struct(
+                (vk_struct_common*)pCreateInfo_mut,
+                VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID);
+
+        if (anbInfoPtr) {
+            localAnb = *anbInfoPtr;
+        }
+
+        VkExternalMemoryImageCreateInfo* extImgCiPtr =
+            (VkExternalMemoryImageCreateInfo*)
+            vk_find_struct(
+                (vk_struct_common*)pCreateInfo_mut,
+                VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
+
+        if (extImgCiPtr) {
+            localExtImgCi = *extImgCiPtr;
+        }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkExternalFormatANDROID localExtFormatAndroid;
+        VkExternalFormatANDROID* extFormatAndroidPtr =
+        (VkExternalFormatANDROID*)
+        vk_find_struct(
+            (vk_struct_common*)pCreateInfo_mut,
+            VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+        if (extFormatAndroidPtr) {
+            localExtFormatAndroid = *extFormatAndroidPtr;
+        }
+#endif
+
+        vk_struct_common* structChain =
+            vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut);
+
+        if (extImgCiPtr) {
+            structChain =
+                vk_append_struct(
+                    structChain, (vk_struct_common*)(&localExtImgCi));
+        }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        if (anbInfoPtr) {
+            structChain =
+                vk_append_struct(
+                    structChain, (vk_struct_common*)(&localAnb));
+        }
+
+        if (extFormatAndroidPtr) {
+            // Do not append external format android;
+            // instead, replace the local image pCreateInfo_mut format
+            // with the corresponding Vulkan format
+            if (extFormatAndroidPtr->externalFormat) {
+                pCreateInfo_mut->format =
+                    vk_format_from_android(extFormatAndroidPtr->externalFormat);
+            }
+        }
+#endif
+
+
 #ifdef VK_USE_PLATFORM_FUCHSIA
         VkNativeBufferANDROID native_info = {
             .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
@@ -1661,8 +1839,6 @@
         };
         cb_handle_t native_handle(
             0, 0, 0, 0, 0, 0, 0, 0, 0, FRAMEWORK_FORMAT_GL_COMPATIBLE);
-        VkImageCreateInfo localCreateInfo = *pCreateInfo;
-        pCreateInfo = &localCreateInfo;
 
         if (pCreateInfo->usage &
             (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
@@ -1683,7 +1859,7 @@
         }
 #endif
 
-        VkResult res = enc->vkCreateImage(device, pCreateInfo, pAllocator, pImage);
+        VkResult res = enc->vkCreateImage(device, pCreateInfo_mut, pAllocator, pImage);
 
         if (res != VK_SUCCESS) return res;
 
@@ -1695,22 +1871,94 @@
         auto& info = it->second;
 
         info.device = device;
-        info.createInfo = *pCreateInfo;
+        info.createInfo = *pCreateInfo_mut;
         info.createInfo.pNext = nullptr;
         info.cbHandle = cbHandle;
 
-        VkExternalMemoryImageCreateInfo* extImgCi =
-            (VkExternalMemoryImageCreateInfo*)vk_find_struct((vk_struct_common*)pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
-
-        if (!extImgCi) return res;
+        if (!extImgCiPtr) return res;
 
         info.external = true;
-        info.externalCreateInfo = *extImgCi;
+        info.externalCreateInfo = *extImgCiPtr;
 
         return res;
     }
 
+    VkResult on_vkCreateSamplerYcbcrConversion(
+        void* context, VkResult,
+        VkDevice device,
+        const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkSamplerYcbcrConversion* pYcbcrConversion) {
+
+        VkSamplerYcbcrConversionCreateInfo localCreateInfo = *pCreateInfo;
+        VkSamplerYcbcrConversionCreateInfo* pCreateInfo_mut = &localCreateInfo;
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkExternalFormatANDROID localExtFormatAndroid;
+        VkExternalFormatANDROID* extFormatAndroidPtr =
+        (VkExternalFormatANDROID*)
+        vk_find_struct(
+            (vk_struct_common*)pCreateInfo_mut,
+            VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+        if (extFormatAndroidPtr) {
+            localExtFormatAndroid = *extFormatAndroidPtr;
+        }
+#endif
+
+        vk_struct_common* structChain =
+            vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut);
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        if (extFormatAndroidPtr) {
+            if (extFormatAndroidPtr->externalFormat) {
+                pCreateInfo_mut->format =
+                    vk_format_from_android(extFormatAndroidPtr->externalFormat);
+            }
+        }
+#endif
+
+        VkEncoder* enc = (VkEncoder*)context;
+        return enc->vkCreateSamplerYcbcrConversion(
+            device, pCreateInfo, pAllocator, pYcbcrConversion);
+    }
+
+    VkResult on_vkCreateSamplerYcbcrConversionKHR(
+        void* context, VkResult,
+        VkDevice device,
+        const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkSamplerYcbcrConversion* pYcbcrConversion) {
+
+        VkSamplerYcbcrConversionCreateInfo localCreateInfo = *pCreateInfo;
+        VkSamplerYcbcrConversionCreateInfo* pCreateInfo_mut = &localCreateInfo;
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkExternalFormatANDROID localExtFormatAndroid;
+        VkExternalFormatANDROID* extFormatAndroidPtr =
+        (VkExternalFormatANDROID*)
+        vk_find_struct(
+            (vk_struct_common*)pCreateInfo_mut,
+            VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+        if (extFormatAndroidPtr) {
+            localExtFormatAndroid = *extFormatAndroidPtr;
+        }
+#endif
+
+        vk_struct_common* structChain =
+            vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut);
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        if (extFormatAndroidPtr) {
+            pCreateInfo_mut->format =
+                vk_format_from_android(extFormatAndroidPtr->externalFormat);
+        }
+#endif
+
+        VkEncoder* enc = (VkEncoder*)context;
+        return enc->vkCreateSamplerYcbcrConversionKHR(
+            device, pCreateInfo, pAllocator, pYcbcrConversion);
+    }
+
     void on_vkDestroyImage(
         void* context,
         VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
@@ -1724,7 +1972,7 @@
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetImageMemoryRequirements(
             device, image, pMemoryRequirements);
-        transformExternalImageMemoryRequirementsForGuest(
+        transformImageMemoryRequirementsForGuest(
             image, pMemoryRequirements);
     }
 
@@ -1734,9 +1982,8 @@
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetImageMemoryRequirements2(
             device, pInfo, pMemoryRequirements);
-        transformExternalImageMemoryRequirementsForGuest(
-            pInfo->image,
-            &pMemoryRequirements->memoryRequirements);
+        transformImageMemoryRequirements2ForGuest(
+            pInfo->image, pMemoryRequirements);
     }
 
     void on_vkGetImageMemoryRequirements2KHR(
@@ -1745,9 +1992,8 @@
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetImageMemoryRequirements2KHR(
             device, pInfo, pMemoryRequirements);
-        transformExternalImageMemoryRequirementsForGuest(
-            pInfo->image,
-            &pMemoryRequirements->memoryRequirements);
+        transformImageMemoryRequirements2ForGuest(
+            pInfo->image, pMemoryRequirements);
     }
 
     VkResult on_vkBindImageMemory(
@@ -1852,7 +2098,7 @@
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetBufferMemoryRequirements(
             device, buffer, pMemoryRequirements);
-        transformExternalBufferMemoryRequirementsForGuest(
+        transformBufferMemoryRequirementsForGuest(
             buffer, pMemoryRequirements);
     }
 
@@ -1861,9 +2107,8 @@
         VkMemoryRequirements2* pMemoryRequirements) {
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
-        transformExternalBufferMemoryRequirementsForGuest(
-            pInfo->buffer,
-            &pMemoryRequirements->memoryRequirements);
+        transformBufferMemoryRequirements2ForGuest(
+            pInfo->buffer, pMemoryRequirements);
     }
 
     void on_vkGetBufferMemoryRequirements2KHR(
@@ -1871,9 +2116,8 @@
         VkMemoryRequirements2* pMemoryRequirements) {
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetBufferMemoryRequirements2KHR(device, pInfo, pMemoryRequirements);
-        transformExternalBufferMemoryRequirementsForGuest(
-            pInfo->buffer,
-            &pMemoryRequirements->memoryRequirements);
+        transformBufferMemoryRequirements2ForGuest(
+            pInfo->buffer, pMemoryRequirements);
     }
 
     VkResult on_vkBindBufferMemory(
@@ -1900,6 +2144,18 @@
             device, bindInfoCount, pBindInfos);
     }
 
+    void ensureSyncDeviceFd() {
+        if (mSyncDeviceFd >= 0) return;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        mSyncDeviceFd = goldfish_sync_open();
+        if (mSyncDeviceFd >= 0) {
+            ALOGD("%s: created sync device for current Vulkan process: %d\n", __func__, mSyncDeviceFd);
+        } else {
+            ALOGD("%s: failed to create sync device for current Vulkan process\n", __func__);
+        }
+#endif
+    }
+
     VkResult on_vkCreateSemaphore(
         void* context, VkResult input_result,
         VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo,
@@ -1910,15 +2166,16 @@
 
         VkSemaphoreCreateInfo finalCreateInfo = *pCreateInfo;
 
+        VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr =
+            (VkExportSemaphoreCreateInfoKHR*)vk_find_struct(
+                (vk_struct_common*)pCreateInfo,
+                VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR);
+
 #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));
 
-        VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr =
-            (VkExportSemaphoreCreateInfoKHR*)vk_find_struct((vk_struct_common*)pCreateInfo,
-                VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR);
-
         bool exportFence = false;
 
         if (exportSemaphoreInfoPtr) {
@@ -1929,6 +2186,21 @@
         }
 
 #endif
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        VkImportSemaphoreFdInfoKHR* importSempahoreFdPtr =
+            (VkImportSemaphoreFdInfoKHR*)vk_find_struct(
+                (vk_struct_common*)pCreateInfo,
+                VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR);
+
+        bool exportSyncFd = exportSemaphoreInfoPtr &&
+            (exportSemaphoreInfoPtr->handleTypes &
+             VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT);
+        bool importSyncFd = importSempahoreFdPtr &&
+            (importSempahoreFdPtr->handleType &
+             VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT);
+
+#endif
         input_result = enc->vkCreateSemaphore(
             device, &finalCreateInfo, pAllocator, pSemaphore);
 
@@ -1950,6 +2222,27 @@
         info.device = device;
         info.eventHandle = event_handle;
 
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        if (exportSyncFd || importSyncFd) {
+
+            ensureSyncDeviceFd();
+
+            if (exportSyncFd) {
+                int syncFd = -1;
+                goldfish_sync_queue_work(
+                    mSyncDeviceFd,
+                    get_host_u64_VkSemaphore(*pSemaphore) /* the handle */,
+                    GOLDFISH_SYNC_VULKAN_SEMAPHORE_SYNC /* thread handle (doubling as type field) */,
+                    &syncFd);
+                info.syncFd = syncFd;
+            }
+
+            if (importSyncFd) {
+                info.syncFd = importSempahoreFdPtr->fd;
+            }
+        }
+#endif
+
         return VK_SUCCESS;
     }
 
@@ -1970,6 +2263,19 @@
         int* pFd) {
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
         VkEncoder* enc = (VkEncoder*)context;
+        bool getSyncFd =
+            pGetFdInfo->handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+
+        if (getSyncFd) {
+            AutoLock lock(mLock);
+            auto it = info_VkSemaphore.find(pGetFdInfo->semaphore);
+            if (it == info_VkSemaphore.end()) return VK_ERROR_OUT_OF_HOST_MEMORY;
+            auto& semInfo = it->second;
+            *pFd = dup(semInfo.syncFd);
+            return VK_SUCCESS;
+        }
+
+        // opaque fd
         int hostFd = 0;
         VkResult result = enc->vkGetSemaphoreFdKHR(device, pGetFdInfo, &hostFd);
         if (result != VK_SUCCESS) {
@@ -2023,12 +2329,12 @@
 
         std::vector<VkSemaphore> pre_signal_semaphores;
         std::vector<zx_handle_t> post_wait_events;
+        std::vector<int> post_wait_sync_fds;
         VkDevice device = VK_NULL_HANDLE;
         VkFence* pFence = nullptr;
 
         VkEncoder* enc = (VkEncoder*)context;
 
-#ifdef VK_USE_PLATFORM_FUCHSIA
         AutoLock lock(mLock);
 
         for (uint32_t i = 0; i < submitCount; ++i) {
@@ -2036,6 +2342,7 @@
                 auto it = info_VkSemaphore.find(pSubmits[i].pWaitSemaphores[j]);
                 if (it != info_VkSemaphore.end()) {
                     auto& semInfo = it->second;
+#ifdef VK_USE_PLATFORM_FUCHSIA
                     if (semInfo.eventHandle) {
                         // Wait here instead of passing semaphore to host.
                         zx_object_wait_one(semInfo.eventHandle,
@@ -2044,22 +2351,38 @@
                                            nullptr);
                         pre_signal_semaphores.push_back(pSubmits[i].pWaitSemaphores[j]);
                     }
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+                    if (semInfo.syncFd >= 0) {
+                        // Wait here instead of passing semaphore to host.
+                        sync_wait(semInfo.syncFd, 3000);
+                        pre_signal_semaphores.push_back(pSubmits[i].pWaitSemaphores[j]);
+                    }
+#endif
                 }
             }
             for (uint32_t j = 0; j < pSubmits[i].signalSemaphoreCount; ++j) {
                 auto it = info_VkSemaphore.find(pSubmits[i].pSignalSemaphores[j]);
                 if (it != info_VkSemaphore.end()) {
                     auto& semInfo = it->second;
+#ifdef VK_USE_PLATFORM_FUCHSIA
                     if (semInfo.eventHandle) {
                         post_wait_events.push_back(semInfo.eventHandle);
                         device = semInfo.device;
                         pFence = &info_VkDevice[device].fence;
                     }
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+                    if (semInfo.syncFd >= 0) {
+                        post_wait_sync_fds.push_back(semInfo.syncFd);
+                        device = semInfo.device;
+                        pFence = &info_VkDevice[device].fence;
+                    }
+#endif
                 }
             }
         }
         lock.unlock();
-#endif
 
         if (!pre_signal_semaphores.empty()) {
             VkSubmitInfo submit_info = {
@@ -2096,6 +2419,11 @@
             zx_object_signal(event, 0, ZX_EVENT_SIGNALED);
         }
 #endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        for (auto& fd : post_wait_sync_fds) {
+            goldfish_sync_signal(fd);
+        }
+#endif
 
         return VK_SUCCESS;
     }
@@ -2271,6 +2599,8 @@
 
     std::vector<VkExtensionProperties> mHostInstanceExtensions;
     std::vector<VkExtensionProperties> mHostDeviceExtensions;
+
+    int mSyncDeviceFd = -1;
 };
 
 ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { }
@@ -2713,6 +3043,26 @@
 }
 #endif
 
+VkResult ResourceTracker::on_vkCreateSamplerYcbcrConversion(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return mImpl->on_vkCreateSamplerYcbcrConversion(
+        context, input_result, device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+VkResult ResourceTracker::on_vkCreateSamplerYcbcrConversionKHR(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkSamplerYcbcrConversion* pYcbcrConversion) {
+    return mImpl->on_vkCreateSamplerYcbcrConversionKHR(
+        context, input_result, device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
 VkResult ResourceTracker::on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
     void* context,
     VkResult input_result,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index 5665cf0..905d9f7 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -252,6 +252,19 @@
         struct AHardwareBuffer** pBuffer);
 #endif
 
+    VkResult on_vkCreateSamplerYcbcrConversion(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkSamplerYcbcrConversion* pYcbcrConversion);
+    VkResult on_vkCreateSamplerYcbcrConversionKHR(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkSamplerYcbcrConversion* pYcbcrConversion);
+
     VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
         void* context,
         VkResult input_result,
diff --git a/system/vulkan_enc/vk_format_info.h b/system/vulkan_enc/vk_format_info.h
index c0548a0..3bac828 100644
--- a/system/vulkan_enc/vk_format_info.h
+++ b/system/vulkan_enc/vk_format_info.h
@@ -40,6 +40,7 @@
    case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
       return VK_FORMAT_R8G8B8A8_UNORM;
    case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+      return VK_FORMAT_R8G8B8A8_UNORM;
    case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
       return VK_FORMAT_R8G8B8_UNORM;
    case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
@@ -149,4 +150,4 @@
    return aspects & VK_IMAGE_ASPECT_DEPTH_BIT;
 }
 
-#endif /* VK_FORMAT_INFO_H */
\ No newline at end of file
+#endif /* VK_FORMAT_INFO_H */