Snap for 5536470 from 9705efe8ed88729f4c7397535b58a24a0db5f2df to emu-29.0-release

Change-Id: I23b45f278c13a9de5fbd34b1bdcc01ce4ae4b75a
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..2f333a0
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,112 @@
+cc_library_shared {
+    name: "libvulkan_goldfish",
+
+    srcs: [
+        "android-emu/android/base/AlignedBuf.cpp",
+        "android-emu/android/base/Pool.cpp",
+        "android-emu/android/base/SubAllocator.cpp",
+        "android-emu/android/base/files/MemStream.cpp",
+        "android-emu/android/base/files/Stream.cpp",
+        "android-emu/android/base/files/StreamSerializing.cpp",
+        "android-emu/android/base/Tracing.cpp",
+        "shared/OpenglCodecCommon/ChecksumCalculator.cpp",
+        "shared/OpenglCodecCommon/glUtils.cpp",
+        "shared/OpenglCodecCommon/goldfish_address_space.cpp",
+        "shared/OpenglCodecCommon/goldfish_dma.cpp",
+        "system/OpenglSystemCommon/HostConnection.cpp",
+        "system/OpenglSystemCommon/ProcessPipe.cpp",
+        "system/OpenglSystemCommon/ThreadInfo.cpp",
+        "system/renderControl_enc/renderControl_enc.cpp",
+        "system/vulkan/func_table.cpp",
+        "system/vulkan/goldfish_vulkan.cpp",
+        "system/vulkan_enc/HostVisibleMemoryVirtualization.cpp",
+        "system/vulkan_enc/ResourceTracker.cpp",
+        "system/vulkan_enc/Resources.cpp",
+        "system/vulkan_enc/Validation.cpp",
+        "system/vulkan_enc/VkEncoder.cpp",
+        "system/vulkan_enc/VulkanHandleMapping.cpp",
+        "system/vulkan_enc/VulkanStreamGuest.cpp",
+        "system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp",
+        "system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp",
+        "system/vulkan_enc/goldfish_vk_marshaling_guest.cpp",
+        "system/vulkan_enc/goldfish_vk_transform_guest.cpp",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"goldfish_vulkan\"",
+        "-DGOLDFISH_VULKAN",
+        "-DGOLDFISH_NO_GL",
+        "-DPAGE_SIZE=4096",
+        "-Wno-unused-parameter",
+        "-Wno-missing-field-initializers",
+        "-Wno-newline-eof",
+        "-Wno-unused-function",
+        "-Wno-unused-value",
+        "-Wno-unused-variable",
+    ],
+
+    include_dirs: [
+        "external/vulkan-headers/include",
+    ],
+
+    local_include_dirs: [
+        "android-emu",
+        "host/include/libOpenglRender",
+        "shared/OpenglCodecCommon",
+        "system/OpenglSystemCommon",
+        "system/renderControl_enc",
+        "system/vulkan_enc",
+        "system/include",
+    ],
+
+    // Only enable on fuchsia.
+    enabled: false,
+    target: {
+        fuchsia: {
+            // TODO(reveman): Enable when not breaking the build.
+            //enabled: true,
+
+            srcs: [
+                "fuchsia/port.cc",
+                "system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp",
+            ],
+
+            cflags: [
+                "-DVK_USE_PLATFORM_FUCHSIA",
+                "-DPLATFORM_SDK_VERSION=1",
+                "-DFUCHSIA_NO_TRACE",
+                "-DQEMU_PIPE_PATH=\"/dev/class/goldfish-pipe/000\"",
+                "-DGOLDFISH_ADDRESS_SPACE_DEVICE_NAME=\"/dev/class/goldfish-address-space/000\"",
+            ],
+
+            stl: "libc++_static",
+
+            local_include_dirs: [
+                "fuchsia/include",
+            ],
+
+            static_libs: [
+                "libasync",
+                "libfidl",
+                "libfidl_base",
+                "libfidl_cpp",
+                "libfidl_cpp_base",
+                "libfidl_cpp_sync",
+                "libfuchsia.hardware.goldfish.address.space",
+                "libfuchsia.hardware.goldfish.control",
+                "libfuchsia.hardware.goldfish.pipe",
+                "libfuchsia.sysmem",
+                "libzx",
+            ],
+
+            shared_libs: [
+                "libasync-default",
+                "libfdio",
+            ],
+
+            required: [
+                "libzircon",
+            ],
+        },
+    },
+}
diff --git a/BUILD.gn b/BUILD.gn
index 348ab87..ccb8fe2 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1,4 +1,4 @@
-shared_library("vulkan_goldfish") {
+shared_library("libvulkan_goldfish") {
   sources = [
     "android-emu/android/base/AlignedBuf.cpp",
     "android-emu/android/base/AlignedBuf.h",
@@ -79,9 +79,11 @@
   ]
 
   cflags_cc = [
-    "-Wno-unused-function",
-    "-Wno-unused-variable",
     "-Wno-missing-field-initializers",
+    "-Wno-newline-eof",
+    "-Wno-unused-function",
+    "-Wno-unused-value",
+    "-Wno-unused-variable",
   ]
 
   ldflags = [ "-static-libstdc++" ]
@@ -94,8 +96,8 @@
     ]
 
     include_dirs += [
-      "//third_party/vulkan_loader_and_validation_layers/include",
       "fuchsia/include",
+      "../../../external/qemu/android/android-emugl/host/include"
     ]
 
     libs = [
@@ -103,9 +105,9 @@
     ]
 
     deps = [
-      "//zircon/public/fidl/fuchsia-hardware-goldfish-address-space:fuchsia-hardware-goldfish-address-space_c",
-      "//zircon/public/fidl/fuchsia-hardware-goldfish-control:fuchsia-hardware-goldfish-control_c",
-      "//zircon/public/fidl/fuchsia-hardware-goldfish-pipe:fuchsia-hardware-goldfish-pipe_c",
+      "//zircon/public/fidl/fuchsia-hardware-goldfish-address-space",
+      "//zircon/public/fidl/fuchsia-hardware-goldfish-control",
+      "//zircon/public/fidl/fuchsia-hardware-goldfish-pipe",
       "//zircon/public/fidl/fuchsia-sysmem",
       "//zircon/public/lib/fdio",
       "//zircon/public/lib/trace",
diff --git a/android-emu/android/base/Tracing.cpp b/android-emu/android/base/Tracing.cpp
index 8b254d2..ff72093 100644
--- a/android-emu/android/base/Tracing.cpp
+++ b/android-emu/android/base/Tracing.cpp
@@ -36,7 +36,9 @@
 
 #elif __Fuchsia__
 
+#ifndef FUCHSIA_NO_TRACE
 #include <trace/event.h>
+#endif
 
 #define VK_TRACE_TAG "gfx"
 
@@ -44,11 +46,15 @@
 namespace base {
 
 void ScopedTrace::beginTraceImpl(const char* name) {
+#ifndef FUCHSIA_NO_TRACE
     TRACE_DURATION_BEGIN(VK_TRACE_TAG, name);
+#endif
 }
 
 void ScopedTrace::endTraceImpl(const char* name) {
+#ifndef FUCHSIA_NO_TRACE
     TRACE_DURATION_END(VK_TRACE_TAG, name);
+#endif
 }
 
 } // namespace base
diff --git a/fuchsia/releasepackage.py b/fuchsia/releasepackage.py
new file mode 100644
index 0000000..8f18d68
--- /dev/null
+++ b/fuchsia/releasepackage.py
@@ -0,0 +1,111 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import shutil
+import subprocess
+import argparse
+import re
+
+parser = argparse.ArgumentParser(description="Upload goldfish libvulkan to CIPD")
+
+parser.add_argument("--release-dir")
+parser.add_argument("--arch")
+parser.add_argument("--dry-run", action="store_true")
+parser.add_argument("--ignore-branch", action="store_true")
+parser.add_argument("--ignore-rebuild", action="store_true")
+parser.add_argument("--ignore-buildtype", action="store_true")
+
+args = parser.parse_args()
+
+dir_path = os.path.dirname(os.path.realpath(__file__))
+
+os.chdir(dir_path)
+
+fuchsia_root = os.path.abspath(os.path.join(dir_path, "../../../"))
+
+if args.release_dir:
+  release_dir = os.path.abspath(args.release_dir)
+else:
+  release_dir = os.path.join(fuchsia_root, "out/default")
+
+if not os.path.exists(release_dir):
+  print "Release dir: %s doesn't exist" % release_dir
+  sys.exit(1)
+
+if args.arch:
+  arch = args.arch
+else:
+  arch = "x64"
+
+target_name = "%s-shared/libvulkan_goldfish.so" % arch
+git_repo_location = "%s/third_party/goldfish-opengl" % fuchsia_root
+package_dir = "libvulkan_goldfish/%s" % arch
+package_name = "fuchsia/lib/libvulkan/%s" % package_dir
+
+git_branch = subprocess.check_output([
+    "git", "-C", git_repo_location, "rev-parse", "--abbrev-ref", "HEAD"
+]).strip()
+if git_branch != "master":
+  print("Git repo %s on incorrect branch %s (should be master)" %
+        (repo_name, git_branch))
+  if args.ignore_branch:
+    print("Ignoring")
+  else:
+    print("Use --ignore-branch flag to upload anyway")
+    sys.exit(1)
+
+# Force ninja dry-run
+ninja_output = subprocess.check_output([
+    os.path.join(fuchsia_root, "buildtools/ninja"), "-C", release_dir, "-v",
+    "-n",
+    target_name
+])
+
+if "ninja: no work to do." not in ninja_output:
+  print("Ninja reported work needed to be done for %s" % target_name)
+  if args.ignore_rebuild:
+    print("Ignoring")
+  else:
+    print("Use --ignore-rebuild flag to upload anyway")
+    sys.exit(1)
+
+gn_output = subprocess.check_output([
+    os.path.join(fuchsia_root, "buildtools/gn"), "args", release_dir,
+    "--list=is_debug", "--short"
+]).strip()
+if gn_output != "is_debug = false":
+  print("GN argument \"%s\" unexpected" % gn_output)
+  if args.ignore_buildtype:
+    print("Ignoring")
+  else:
+    print("Use --ignore-buildtype flag to upload anyway")
+    sys.exit(1)
+
+file_name = "libvulkan_goldfish.so"
+full_name = os.path.join(package_dir, file_name)
+
+source_file_name = os.path.join(release_dir, target_name)
+try:
+  os.remove(full_name)
+except:
+  pass
+shutil.copyfile(source_file_name, full_name)
+
+cipd_path = os.path.join(fuchsia_root, "buildtools/cipd")
+git_rev = subprocess.check_output(
+    ["git", "-C", git_repo_location, "rev-parse", "HEAD"]).strip()
+
+cipd_command = "%s create -in %s -name %s -ref latest -tag git_revision:%s" % (
+    cipd_path, package_dir, package_name, git_rev)
+print cipd_command
+if not args.dry_run:
+  subprocess.check_call(cipd_command.split(" "))
+
+print ("""
+  <package name="%s"
+           version="git_revision:%s"
+           path="prebuild/third_party/%s"/>
+""" % (package_name, git_rev, package_dir))[1:-1]
\ No newline at end of file
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.cpp b/shared/OpenglCodecCommon/goldfish_address_space.cpp
index bbc59c6..da6831e 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space.cpp
+++ b/shared/OpenglCodecCommon/goldfish_address_space.cpp
@@ -127,8 +127,9 @@
 }
 #elif __Fuchsia__
 #include <fcntl.h>
-#include <fuchsia/hardware/goldfish/address/space/c/fidl.h>
 #include <lib/fdio/fdio.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/vmo.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -138,17 +139,25 @@
 #include <zircon/syscalls/object.h>
 
 GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider() {
-    fdio_get_service_handle(::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR), &m_channel);
+    zx::channel channel;
+    zx_status_t status =
+        fdio_get_service_handle(::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR),
+                                channel.reset_and_get_address());
+    if (status != ZX_OK) {
+        ALOGE("%s: failed to get service handle for " GOLDFISH_ADDRESS_SPACE_DEVICE_NAME ": %d",
+              __FUNCTION__, status);
+        return;
+    }
+    m_device.Bind(std::move(channel));
 }
 
 GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider()
 {
-    zx_handle_close(m_channel);
 }
 
 GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
-    : m_vmo(ZX_HANDLE_INVALID)
-    , m_channel(ZX_HANDLE_INVALID)
+    : m_device(NULL)
+    , m_vmo(ZX_HANDLE_INVALID)
     , m_mmaped_ptr(NULL)
     , m_phys_addr(0)
     , m_host_addr(0)
@@ -168,7 +177,7 @@
     m_host_addr = rhs.m_host_addr;
     m_offset = rhs.m_offset;
     m_size = rhs.m_size;
-    m_channel = rhs.m_channel;
+    m_device = rhs.m_device;
 
     return *this;
 }
@@ -184,10 +193,11 @@
         return false;
     }
 
+    fuchsia::hardware::goldfish::address::space::DeviceSyncPtr* device = &provider->m_device;
+
     int32_t res = ZX_OK;
-    zx_status_t status =
-        fuchsia_hardware_goldfish_address_space_DeviceAllocateBlock(
-            provider->m_channel, size, &res, &m_phys_addr, &m_vmo);
+    zx::vmo vmo;
+    zx_status_t status = (*device)->AllocateBlock(size, &res, &m_phys_addr, &vmo);
     if (status != ZX_OK || res != ZX_OK) {
         ALOGE("%s: allocate block failed: %d:%d", __func__, status, res);
         return false;
@@ -195,12 +205,13 @@
 
     m_offset = 0;
     m_size = size;
+    m_vmo = vmo.release();
 
     ALOGD("%s: allocate returned offset 0x%llx size 0x%llx\n", __func__,
           (unsigned long long)m_offset,
           (unsigned long long)m_size);
 
-    m_channel = provider->m_channel;
+    m_device = device;
     return true;
 }
 
@@ -264,13 +275,11 @@
         zx_handle_close(m_vmo);
         m_vmo = ZX_HANDLE_INVALID;
         int32_t res = ZX_OK;
-        zx_status_t status =
-            fuchsia_hardware_goldfish_address_space_DeviceDeallocateBlock(
-                m_channel, m_phys_addr, &res);
+        zx_status_t status = (*m_device)->DeallocateBlock(m_phys_addr, &res);
         if (status != ZX_OK || res != ZX_OK) {
             ALOGE("%s: deallocate block failed: %d:%d", __func__, status, res);
         }
-        m_channel = ZX_HANDLE_INVALID;
+        m_device = NULL;
         m_phys_addr = 0;
         m_host_addr = 0;
         m_offset = 0;
@@ -290,7 +299,7 @@
 
 bool GoldfishAddressSpaceBlockProvider::is_opened()
 {
-    return m_channel != ZX_HANDLE_INVALID;
+    return m_device.is_bound();
 }
 #else
 #include <linux/types.h>
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.h b/shared/OpenglCodecCommon/goldfish_address_space.h
index 7ebb451..250c476 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space.h
+++ b/shared/OpenglCodecCommon/goldfish_address_space.h
@@ -18,6 +18,10 @@
 #include <inttypes.h>
 #include <stddef.h>
 
+#ifdef __Fuchsia__
+#include <fuchsia/hardware/goldfish/address/space/cpp/fidl.h>
+#endif
+
 class GoldfishAddressSpaceBlock;
 
 #ifdef HOST_BUILD
@@ -46,7 +50,7 @@
 
    bool is_opened();
 #ifdef __Fuchsia__
-   uint32_t m_channel;
+   fuchsia::hardware::goldfish::address::space::DeviceSyncPtr m_device;
 #else
    int m_fd;
 #endif
@@ -78,8 +82,8 @@
     GoldfishAddressSpaceBlockProvider* m_provider;
 #else
 #ifdef __Fuchsia__
+    fuchsia::hardware::goldfish::address::space::DeviceSyncPtr* m_device;
     uint32_t  m_vmo;
-    uint32_t  m_channel;
 #else
     int       m_fd;
 #endif
diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp
index ad0527a..5fe9fa3 100644
--- a/system/OpenglSystemCommon/ProcessPipe.cpp
+++ b/system/OpenglSystemCommon/ProcessPipe.cpp
@@ -25,6 +25,12 @@
 #include <pthread.h>
 #include <errno.h>
 
+#ifdef __Fuchsia__
+#include <fuchsia/hardware/goldfish/pipe/cpp/fidl.h>
+#include <lib/fdio/fdio.h>
+#include <lib/zx/vmo.h>
+#endif
+
 static QEMU_PIPE_HANDLE   sProcPipe = 0;
 static pthread_once_t     sProcPipeOnce = PTHREAD_ONCE_INIT;
 // sProcUID is a unique ID per process assigned by the host.
@@ -38,6 +44,79 @@
 // It will fallback to the default path if the host does not support it.
 // Processes are identified by acquiring a per-process 64bit unique ID from the
 // host.
+#ifdef __Fuchsia__
+static void processPipeInitOnce() {
+    int fd = ::open(QEMU_PIPE_PATH, O_RDWR);
+    if (fd < 0) {
+        ALOGE("%s: failed to open " QEMU_PIPE_PATH ": %s",
+              __FUNCTION__, strerror(errno));
+        return;
+    }
+
+    zx::channel channel;
+    zx_status_t status = fdio_get_service_handle(
+        fd, channel.reset_and_get_address());
+    if (status != ZX_OK) {
+        ALOGE("%s: failed to get service handle for " QEMU_PIPE_PATH ": %d",
+              __FUNCTION__, status);
+        close(fd);
+        return;
+    }
+
+    fuchsia::hardware::goldfish::pipe::DeviceSyncPtr device;
+    device.Bind(std::move(channel));
+
+    zx_status_t status2 = ZX_OK;
+    zx::vmo vmo;
+    status = device->GetBuffer(&status2, &vmo);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
+        return;
+    }
+
+    size_t len = strlen("pipe:GLProcessPipe");
+    status = vmo.write("pipe:GLProcessPipe", 0, len + 1);
+    if (status != ZX_OK) {
+        ALOGE("%s: failed write pipe name", __FUNCTION__);
+        return;
+    }
+    uint64_t actual;
+    status = device->Write(len + 1, 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: connecting to pipe service failed: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+
+    // Send a confirmation int to the host
+    int32_t confirmInt = 100;
+    status = vmo.write(&confirmInt, 0, sizeof(confirmInt));
+    if (status != ZX_OK) {
+        ALOGE("%s: failed write confirm int", __FUNCTION__);
+        return;
+    }
+    status = device->Write(sizeof(confirmInt), 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: failed to send confirm value: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+
+    // Ask the host for per-process unique ID
+    status = device->Read(sizeof(sProcUID), 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: failed to recv per-process ID: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+    status = vmo.read(&sProcUID, 0, sizeof(sProcUID));
+    if (status != ZX_OK) {
+        ALOGE("%s: failed read per-process ID: %d", __FUNCTION__, status);
+        return;
+    }
+    sProcPipe = device.Unbind().TakeChannel().release();
+}
+#else
 static void processPipeInitOnce() {
     sProcPipe = qemu_pipe_open("GLProcessPipe");
     if (!qemu_pipe_valid(sProcPipe)) {
@@ -76,6 +155,7 @@
         return;
     }
 }
+#endif
 
 bool processPipeInit(renderControl_encoder_context_t *rcEnc) {
     pthread_once(&sProcPipeOnce, processPipeInitOnce);
diff --git a/system/OpenglSystemCommon/QemuPipeStream.h b/system/OpenglSystemCommon/QemuPipeStream.h
index 8d64ab8..a6a3d88 100644
--- a/system/OpenglSystemCommon/QemuPipeStream.h
+++ b/system/OpenglSystemCommon/QemuPipeStream.h
@@ -26,7 +26,7 @@
 #include "qemu_pipe.h"
 
 #ifdef __Fuchsia__
-#include <lib/zx/channel.h>
+#include <fuchsia/hardware/goldfish/pipe/cpp/fidl.h>
 #include <lib/zx/event.h>
 #include <lib/zx/vmo.h>
 #endif
@@ -55,7 +55,7 @@
     size_t m_bufsize;
     unsigned char *m_buf;
 #ifdef __Fuchsia__
-    zx::channel m_channel;
+    fuchsia::hardware::goldfish::pipe::DeviceSyncPtr m_device;
     zx::event m_event;
     zx::vmo m_vmo;
 #endif
diff --git a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
index f4ee61c..4377d40 100644
--- a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
+++ b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
@@ -17,8 +17,8 @@
 
 #include <cutils/log.h>
 #include <errno.h>
-#include <fuchsia/hardware/goldfish/pipe/c/fidl.h>
 #include <lib/fdio/fdio.h>
+#include <lib/zx/channel.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -45,7 +45,7 @@
 
 QemuPipeStream::~QemuPipeStream()
 {
-    if (m_channel.is_valid()) {
+    if (m_device.is_bound()) {
         flush();
     }
     if (m_buf) {
@@ -77,6 +77,7 @@
         close(fd);
         return -1;
     }
+    m_device.Bind(std::move(channel));
 
     zx::event event;
     status = zx::event::create(0, &event);
@@ -91,8 +92,7 @@
         return -1;
     }
 
-    status = fuchsia_hardware_goldfish_pipe_DeviceSetEvent(
-        channel.get(), event_copy.release());
+    status = m_device->SetEvent(std::move(event_copy));
     if (status != ZX_OK) {
         ALOGE("%s: failed to set event: %d:%d", __FUNCTION__, status);
         return -1;
@@ -100,8 +100,7 @@
 
     zx_status_t status2 = ZX_OK;
     zx::vmo vmo;
-    status = fuchsia_hardware_goldfish_pipe_DeviceGetBuffer(
-        channel.get(), &status2, vmo.reset_and_get_address());
+    status = m_device->GetBuffer(&status2, &vmo);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
         return -1;
@@ -115,15 +114,13 @@
     }
 
     uint64_t actual;
-    status = fuchsia_hardware_goldfish_pipe_DeviceWrite(
-        channel.get(), len + 1, 0, &status2, &actual);
+    status = m_device->Write(len + 1, 0, &status2, &actual);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGD("%s: connecting to pipe service failed: %d:%d", __FUNCTION__,
               status, status2);
         return -1;
     }
 
-    m_channel = std::move(channel);
     m_event = std::move(event);
     m_vmo = std::move(vmo);
     return 0;
@@ -149,16 +146,14 @@
     size_t allocSize = m_bufsize < minSize ? minSize : m_bufsize;
 
     zx_status_t status2 = ZX_OK;
-    status = fuchsia_hardware_goldfish_pipe_DeviceSetBufferSize(
-        m_channel.get(), allocSize, &status2);
+    status = m_device->SetBufferSize(allocSize, &status2);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
         return nullptr;
     }
 
     zx::vmo vmo;
-    status = fuchsia_hardware_goldfish_pipe_DeviceGetBuffer(
-        m_channel.get(), &status2, vmo.reset_and_get_address());
+    status = m_device->GetBuffer(&status2, &vmo);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
         return nullptr;
@@ -187,8 +182,8 @@
     while (remaining) {
         zx_status_t status2 = ZX_OK;
         uint64_t actual = 0;
-        zx_status_t status = fuchsia_hardware_goldfish_pipe_DeviceWrite(
-            m_channel.get(), remaining, size - remaining, &status2, &actual);
+        zx_status_t status = m_device->Write(
+            remaining, size - remaining, &status2, &actual);
         if (status != ZX_OK) {
             ALOGD("%s: Failed writing to pipe: %d", __FUNCTION__, status);
             return -1;
@@ -203,14 +198,14 @@
         }
         zx_signals_t observed = ZX_SIGNAL_NONE;
         status = m_event.wait_one(
-            fuchsia_hardware_goldfish_pipe_SIGNAL_WRITABLE |
-            fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP,
+            fuchsia::hardware::goldfish::pipe::SIGNAL_WRITABLE |
+            fuchsia::hardware::goldfish::pipe::SIGNAL_HANGUP,
             zx::time::infinite(), &observed);
         if (status != ZX_OK) {
             ALOGD("%s: wait_one failed: %d", __FUNCTION__, status);
             return -1;
         }
-        if (observed & fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP) {
+        if (observed & fuchsia::hardware::goldfish::pipe::SIGNAL_HANGUP) {
             ALOGD("%s: Remote end hungup", __FUNCTION__);
             return -1;
         }
@@ -232,7 +227,7 @@
 
 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len)
 {
-    if (!m_channel.is_valid()) return nullptr;
+    if (!m_device.is_bound()) return nullptr;
 
     if (!buf) {
         if (len > 0) {
@@ -248,8 +243,7 @@
         size_t readSize = m_bufsize < remaining ? m_bufsize : remaining;
         zx_status_t status2 = ZX_OK;
         uint64_t actual = 0;
-        zx_status_t status = fuchsia_hardware_goldfish_pipe_DeviceRead(
-            m_channel.get(), readSize, 0, &status2, &actual);
+        zx_status_t status = m_device->Read(readSize, 0, &status2, &actual);
         if (status != ZX_OK) {
             ALOGD("%s: Failed reading from pipe: %d", __FUNCTION__, status);
             return nullptr;
@@ -265,14 +259,14 @@
         }
         zx_signals_t observed = ZX_SIGNAL_NONE;
         status = m_event.wait_one(
-            fuchsia_hardware_goldfish_pipe_SIGNAL_READABLE |
-            fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP,
+            fuchsia::hardware::goldfish::pipe::SIGNAL_READABLE |
+            fuchsia::hardware::goldfish::pipe::SIGNAL_HANGUP,
             zx::time::infinite(), &observed);
         if (status != ZX_OK) {
             ALOGD("%s: wait_one failed: %d", __FUNCTION__, status);
             return nullptr;
         }
-        if (observed & fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP) {
+        if (observed & fuchsia::hardware::goldfish::pipe::SIGNAL_HANGUP) {
             ALOGD("%s: Remote end hungup", __FUNCTION__);
             return nullptr;
         }
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 44e385d..f5b380e 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -666,7 +666,8 @@
     AEMU_SCOPED_TRACE("vkCreateImageView");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateImageView_VkResult_return = (VkResult)0;
-    vkCreateImageView_VkResult_return = vkEnc->vkCreateImageView(device, pCreateInfo, pAllocator, pView);
+    auto resources = ResourceTracker::get();
+    vkCreateImageView_VkResult_return = resources->on_vkCreateImageView(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pView);
     return vkCreateImageView_VkResult_return;
 }
 static void entry_vkDestroyImageView(
diff --git a/system/vulkan_enc/AndroidHardwareBuffer.cpp b/system/vulkan_enc/AndroidHardwareBuffer.cpp
index 84086e1..5cebdc2 100644
--- a/system/vulkan_enc/AndroidHardwareBuffer.cpp
+++ b/system/vulkan_enc/AndroidHardwareBuffer.cpp
@@ -59,9 +59,7 @@
     VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
 
     VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
-        vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(
-            pProperties,
-            VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
+        vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
 
     if (ahbFormatProps) {
         AHardwareBuffer_Desc desc;
@@ -76,7 +74,7 @@
             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
         }
 
-        ahbFormatProps->format = VK_FORMAT_UNDEFINED;
+        ahbFormatProps->format = vk_format_from_android(desc.format);
         ahbFormatProps->externalFormat = desc.format;
 
         // The formatFeatures member must include
@@ -101,7 +99,10 @@
         ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
         ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
 
-        ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
+        ahbFormatProps->suggestedYcbcrModel =
+            android_format_is_yuv(desc.format) ?
+                VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 :
+                VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
         ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
 
         ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 3b5bdb8..98f5527 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -14,6 +14,7 @@
 // limitations under the License.
 
 #include "ResourceTracker.h"
+#include "goldfish_vk_private_defs.h"
 
 #include "../OpenglSystemCommon/EmulatorFeatureInfo.h"
 
@@ -26,31 +27,6 @@
 void zx_handle_close(zx_handle_t) { }
 void zx_event_create(int, zx_handle_t*) { }
 
-typedef struct VkImportMemoryZirconHandleInfoFUCHSIA {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagBits    handleType;
-    uint32_t                              handle;
-} VkImportMemoryZirconHandleInfoFUCHSIA;
-
-typedef uint32_t VkBufferCollectionFUCHSIA;
-
-typedef struct VkImportMemoryBufferCollectionFUCHSIA {
-    VkStructureType              sType;
-    const void*                  pNext;
-    VkBufferCollectionFUCHSIA    collection;
-    uint32_t                     index;
-} VkImportMemoryBufferCollectionFUCHSIA;
-
-#define VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA \
-    ((VkStructureType)1001000000)
-#define VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA \
-    ((VkStructureType)1001000000)
-#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA \
-    ((VkStructureType)0x00000800)
-#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA \
-    ((VkStructureType)0x00000020)
-
 #include "AndroidHardwareBuffer.h"
 
 #endif // VK_USE_PLATFORM_ANDROID_KHR
@@ -58,13 +34,14 @@
 #ifdef VK_USE_PLATFORM_FUCHSIA
 
 #include <cutils/native_handle.h>
-#include <fuchsia/hardware/goldfish/control/c/fidl.h>
+#include <fuchsia/hardware/goldfish/control/cpp/fidl.h>
 #include <fuchsia/sysmem/cpp/fidl.h>
 #include <lib/fdio/directory.h>
 #include <lib/fdio/fd.h>
 #include <lib/fdio/fdio.h>
 #include <lib/fdio/io.h>
 #include <lib/zx/channel.h>
+#include <lib/zx/vmo.h>
 #include <zircon/process.h>
 #include <zircon/syscalls.h>
 #include <zircon/syscalls/object.h>
@@ -570,14 +547,14 @@
                 ALOGE("failed to open control device");
                 abort();
             }
-            zx_status_t status = fdio_get_service_handle(fd, &mControlDevice);
+            zx::channel channel;
+            zx_status_t status = fdio_get_service_handle(fd, channel.reset_and_get_address());
             if (status != ZX_OK) {
                 ALOGE("failed to get control service handle, status %d", status);
                 abort();
             }
-            status = fuchsia_hardware_goldfish_control_DeviceConnectSysmem(
-                mControlDevice,
-                mSysmemAllocator.NewRequest().TakeChannel().release());
+            mControlDevice.Bind(std::move(channel));
+            status = mControlDevice->ConnectSysmem(mSysmemAllocator.NewRequest().TakeChannel());
             if (status != ZX_OK) {
                 ALOGE("failed to get sysmem connection, status %d", status);
                 abort();
@@ -1185,9 +1162,6 @@
         if (handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA) {
             return VK_ERROR_INITIALIZATION_FAILED;
         }
-        if (pProperties->sType != VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA) {
-            return VK_ERROR_INITIALIZATION_FAILED;
-        }
 
         AutoLock lock(mLock);
 
@@ -1548,24 +1522,19 @@
         // };
 
         const VkExportMemoryAllocateInfo* exportAllocateInfoPtr =
-            vk_find_struct<VkExportMemoryAllocateInfo>(pAllocateInfo,
-                VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO);
+            vk_find_struct<VkExportMemoryAllocateInfo>(pAllocateInfo);
 
         const VkImportAndroidHardwareBufferInfoANDROID* importAhbInfoPtr =
-            vk_find_struct<VkImportAndroidHardwareBufferInfoANDROID>(pAllocateInfo,
-                VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
+            vk_find_struct<VkImportAndroidHardwareBufferInfoANDROID>(pAllocateInfo);
 
         const VkImportMemoryBufferCollectionFUCHSIA* importBufferCollectionInfoPtr =
-            vk_find_struct<VkImportMemoryBufferCollectionFUCHSIA>(pAllocateInfo,
-                VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
+            vk_find_struct<VkImportMemoryBufferCollectionFUCHSIA>(pAllocateInfo);
 
         const VkImportMemoryZirconHandleInfoFUCHSIA* importVmoInfoPtr =
-            vk_find_struct<VkImportMemoryZirconHandleInfoFUCHSIA>(pAllocateInfo,
-                VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA);
+            vk_find_struct<VkImportMemoryZirconHandleInfoFUCHSIA>(pAllocateInfo);
 
         const VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
-            vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo,
-                VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO);
+            vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo);
 
         bool shouldPassThroughDedicatedAllocInfo =
             !exportAllocateInfoPtr &&
@@ -1786,18 +1755,19 @@
 
                 collection->Close();
 
-                zx_handle_t vmo_copy;
-                status = zx_handle_duplicate(vmo_handle, ZX_RIGHT_SAME_RIGHTS, &vmo_copy);
+                zx::vmo vmo_copy;
+                status = zx_handle_duplicate(vmo_handle,
+                                             ZX_RIGHT_SAME_RIGHTS,
+                                             vmo_copy.reset_and_get_address());
                 if (status != ZX_OK) {
                     ALOGE("Failed to duplicate VMO: %d", status);
                     abort();
                 }
-                status = fuchsia_hardware_goldfish_control_DeviceCreateColorBuffer(
-                    mControlDevice,
-                    vmo_copy,
+                status = mControlDevice->CreateColorBuffer(
+                    std::move(vmo_copy),
                     imageCreateInfo.extent.width,
                     imageCreateInfo.extent.height,
-                    fuchsia_hardware_goldfish_control_FormatType_BGRA,
+                    fuchsia::hardware::goldfish::control::FormatType::BGRA,
                     &status2);
                 if (status != ZX_OK || status2 != ZX_OK) {
                     ALOGE("CreateColorBuffer failed: %d:%d", status, status2);
@@ -1807,17 +1777,17 @@
         }
 
         if (vmo_handle != ZX_HANDLE_INVALID) {
-            zx_handle_t vmo_copy;
+            zx::vmo vmo_copy;
             zx_status_t status = zx_handle_duplicate(vmo_handle,
                                                      ZX_RIGHT_SAME_RIGHTS,
-                                                     &vmo_copy);
+                                                     vmo_copy.reset_and_get_address());
             if (status != ZX_OK) {
                 ALOGE("Failed to duplicate VMO: %d", status);
                 abort();
             }
             zx_status_t status2 = ZX_OK;
-            status = fuchsia_hardware_goldfish_control_DeviceGetColorBuffer(
-                mControlDevice, vmo_copy, &status2, &importCbInfo.colorBuffer);
+            status = mControlDevice->GetColorBuffer(
+                std::move(vmo_copy), &status2, &importCbInfo.colorBuffer);
             if (status != ZX_OK || status2 != ZX_OK) {
                 ALOGE("GetColorBuffer failed: %d:%d", status, status2);
             }
@@ -2116,8 +2086,7 @@
         transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements);
 
         VkMemoryDedicatedRequirements* dedicatedReqs =
-            vk_find_struct<VkMemoryDedicatedRequirements>(
-                reqs2, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS);
+            vk_find_struct<VkMemoryDedicatedRequirements>(reqs2);
 
         if (!dedicatedReqs) return;
 
@@ -2146,8 +2115,7 @@
         transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements);
 
         VkMemoryDedicatedRequirements* dedicatedReqs =
-            vk_find_struct<VkMemoryDedicatedRequirements>(
-                reqs2, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS);
+            vk_find_struct<VkMemoryDedicatedRequirements>(reqs2);
 
         if (!dedicatedReqs) return;
 
@@ -2167,9 +2135,7 @@
         VkExternalMemoryImageCreateInfo localExtImgCi;
 
         const VkExternalMemoryImageCreateInfo* extImgCiPtr =
-            vk_find_struct<VkExternalMemoryImageCreateInfo>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
+            vk_find_struct<VkExternalMemoryImageCreateInfo>(pCreateInfo);
         if (extImgCiPtr) {
             localExtImgCi = vk_make_orphan_copy(*extImgCiPtr);
             vk_append_struct(&structChainIter, &localExtImgCi);
@@ -2178,9 +2144,7 @@
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
         VkNativeBufferANDROID localAnb;
         const VkNativeBufferANDROID* anbInfoPtr =
-            vk_find_struct<VkNativeBufferANDROID>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID);
+            vk_find_struct<VkNativeBufferANDROID>(pCreateInfo);
         if (anbInfoPtr) {
             localAnb = vk_make_orphan_copy(*anbInfoPtr);
             vk_append_struct(&structChainIter, &localAnb);
@@ -2188,9 +2152,7 @@
 
         VkExternalFormatANDROID localExtFormatAndroid;
         const VkExternalFormatANDROID* extFormatAndroidPtr =
-            vk_find_struct<VkExternalFormatANDROID>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+            vk_find_struct<VkExternalFormatANDROID>(pCreateInfo);
         if (extFormatAndroidPtr) {
             localExtFormatAndroid = vk_make_orphan_copy(*extFormatAndroidPtr);
 
@@ -2208,34 +2170,31 @@
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
         const VkBufferCollectionImageCreateInfoFUCHSIA* extBufferCollectionPtr =
-            vk_find_struct<VkBufferCollectionImageCreateInfoFUCHSIA>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA);
+            vk_find_struct<VkBufferCollectionImageCreateInfoFUCHSIA>(pCreateInfo);
         if (extBufferCollectionPtr) {
             auto collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(
                 extBufferCollectionPtr->collection);
             uint32_t index = extBufferCollectionPtr->index;
-            zx_handle_t vmo_handle = ZX_HANDLE_INVALID;
+            zx::vmo vmo;
 
             fuchsia::sysmem::BufferCollectionInfo_2 info;
             zx_status_t status2;
             zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info);
             if (status == ZX_OK && status2 == ZX_OK) {
                 if (index < info.buffer_count) {
-                    vmo_handle = info.buffers[index].vmo.release();
+                    vmo = std::move(info.buffers[index].vmo);
                 }
             } else {
                 ALOGE("WaitForBuffersAllocated failed: %d %d", status, status2);
             }
 
-            if (vmo_handle != ZX_HANDLE_INVALID) {
+            if (vmo.is_valid()) {
                 zx_status_t status2 = ZX_OK;
-                status = fuchsia_hardware_goldfish_control_DeviceCreateColorBuffer(
-                    mControlDevice,
-                    vmo_handle,
+                status = mControlDevice->CreateColorBuffer(
+                    std::move(vmo),
                     localCreateInfo.extent.width,
                     localCreateInfo.extent.height,
-                    fuchsia_hardware_goldfish_control_FormatType_BGRA,
+                    fuchsia::hardware::goldfish::control::FormatType::BGRA,
                     &status2);
                 if (status != ZX_OK || status2 != ZX_OK) {
                     ALOGE("CreateColorBuffer failed: %d:%d", status, status2);
@@ -2288,9 +2247,7 @@
 
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
         const VkExternalFormatANDROID* extFormatAndroidPtr =
-            vk_find_struct<VkExternalFormatANDROID>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+            vk_find_struct<VkExternalFormatANDROID>(pCreateInfo);
         if (extFormatAndroidPtr) {
             if (extFormatAndroidPtr->externalFormat) {
                 localCreateInfo.format =
@@ -2315,9 +2272,7 @@
 
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
         const VkExternalFormatANDROID* extFormatAndroidPtr =
-            vk_find_struct<VkExternalFormatANDROID>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+            vk_find_struct<VkExternalFormatANDROID>(pCreateInfo);
         if (extFormatAndroidPtr) {
             if (extFormatAndroidPtr->externalFormat) {
                 localCreateInfo.format =
@@ -2412,8 +2367,7 @@
         info.createInfo.pNext = nullptr;
 
         const VkExternalMemoryBufferCreateInfo* extBufCi =
-            vk_find_struct<VkExternalMemoryBufferCreateInfo>(pCreateInfo,
-                VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO);
+            vk_find_struct<VkExternalMemoryBufferCreateInfo>(pCreateInfo);
 
         if (!extBufCi) return res;
 
@@ -2504,9 +2458,7 @@
         VkSemaphoreCreateInfo finalCreateInfo = *pCreateInfo;
 
         const VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr =
-            vk_find_struct<VkExportSemaphoreCreateInfoKHR>(
-                pCreateInfo,
-                VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR);
+            vk_find_struct<VkExportSemaphoreCreateInfoKHR>(pCreateInfo);
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
         bool exportEvent = exportSemaphoreInfoPtr &&
@@ -3075,9 +3027,7 @@
         (void)input_result;
 
         VkAndroidHardwareBufferUsageANDROID* output_ahw_usage =
-            vk_find_struct<VkAndroidHardwareBufferUsageANDROID>(
-                pImageFormatProperties,
-                VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID);
+            vk_find_struct<VkAndroidHardwareBufferUsageANDROID>(pImageFormatProperties);
 
         VkResult hostRes;
 
@@ -3170,6 +3120,32 @@
         return VK_SUCCESS;
     }
 
+    VkResult on_vkCreateImageView(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkImageViewCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkImageView* pView) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+        (void)input_result;
+
+        VkImageViewCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo);
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        const VkExternalFormatANDROID* extFormatAndroidPtr =
+            vk_find_struct<VkExternalFormatANDROID>(pCreateInfo);
+        if (extFormatAndroidPtr) {
+            if (extFormatAndroidPtr->externalFormat) {
+                localCreateInfo.format =
+                    vk_format_from_android(extFormatAndroidPtr->externalFormat);
+            }
+        }
+#endif
+
+        return enc->vkCreateImageView(device, &localCreateInfo, pAllocator, pView);
+    }
+
     uint32_t getApiVersionFromInstance(VkInstance instance) const {
         AutoLock lock(mLock);
         uint32_t api = kMinApiVersion;
@@ -3227,7 +3203,7 @@
     int mSyncDeviceFd = -1;
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
-    zx_handle_t mControlDevice = ZX_HANDLE_INVALID;
+    fuchsia::hardware::goldfish::control::DeviceSyncPtr mControlDevice;
     fuchsia::sysmem::AllocatorSyncPtr mSysmemAllocator;
 #endif
 };
@@ -3811,6 +3787,16 @@
         context, input_result, commandBuffer, flags);
 }
 
+VkResult ResourceTracker::on_vkCreateImageView(
+    void* context, VkResult input_result,
+    VkDevice device,
+    const VkImageViewCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkImageView* pView) {
+    return mImpl->on_vkCreateImageView(
+        context, input_result, device, pCreateInfo, pAllocator, pView);
+}
+
 void ResourceTracker::deviceMemoryTransform_tohost(
     VkDeviceMemory* memory, uint32_t memoryCount,
     VkDeviceSize* offset, uint32_t offsetCount,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index 1f073c8..6429d6f 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -334,6 +334,13 @@
         VkCommandBuffer commandBuffer,
         VkCommandBufferResetFlags flags);
 
+    VkResult on_vkCreateImageView(
+        void* context, VkResult input_result,
+        VkDevice device,
+        const VkImageViewCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkImageView* pView);
+
     bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
     uint8_t* getMappedPointer(VkDeviceMemory memory);
     VkDeviceSize getMappedSize(VkDeviceMemory memory);
diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h
index 3eed244..35d4425 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -425,6 +425,104 @@
     VkCommandBuffer commandBuffer,
     VkCommandBufferResetFlags flags);
 
+#ifndef VK_FUCHSIA_buffer_collection
+#define VK_FUCHSIA_buffer_collection 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA)
+
+#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 1
+#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection"
+
+typedef struct VkBufferCollectionCreateInfoFUCHSIA {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           collectionToken;
+} VkBufferCollectionCreateInfoFUCHSIA;
+
+typedef struct VkImportMemoryBufferCollectionFUCHSIA {
+    VkStructureType              sType;
+    const void*                  pNext;
+    VkBufferCollectionFUCHSIA    collection;
+    uint32_t                     index;
+} VkImportMemoryBufferCollectionFUCHSIA;
+
+typedef struct VkBufferCollectionImageCreateInfoFUCHSIA {
+    VkStructureType              sType;
+    const void*                  pNext;
+    VkBufferCollectionFUCHSIA    collection;
+    uint32_t                     index;
+} VkBufferCollectionImageCreateInfoFUCHSIA;
+
+typedef struct VkBufferCollectionPropertiesFUCHSIA {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           memoryTypeBits;
+    uint32_t           count;
+} VkBufferCollectionPropertiesFUCHSIA;
+
+#define VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA       \
+    ((VkStructureType)1001004004)
+#define VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA \
+    ((VkStructureType)1001004005)
+#endif  // VK_FUCHSIA_buffer_collection
+
+#ifndef VK_FUCHSIA_external_memory
+#define VK_FUCHSIA_external_memory 1
+#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1
+#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory"
+
+typedef struct VkImportMemoryZirconHandleInfoFUCHSIA {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+    uint32_t                              handle;
+} VkImportMemoryZirconHandleInfoFUCHSIA;
+
+typedef struct VkMemoryZirconHandlePropertiesFUCHSIA {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           memoryTypeBits;
+} VkMemoryZirconHandlePropertiesFUCHSIA;
+
+typedef struct VkMemoryGetZirconHandleInfoFUCHSIA {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkDeviceMemory                        memory;
+    VkExternalMemoryHandleTypeFlagBits    handleType;
+} VkMemoryGetZirconHandleInfoFUCHSIA;
+
+#define VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA \
+    ((VkStructureType)1001005000)
+#define VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA \
+    ((VkStructureType)1001005001)
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA \
+    ((VkExternalMemoryHandleTypeFlagBits)0x00100000)
+#endif  // VK_FUCHSIA_external_memory
+
+#ifndef VK_FUCHSIA_external_semaphore
+#define VK_FUCHSIA_external_semaphore 1
+#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
+#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore"
+
+typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkSemaphoreImportFlags                   flags;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+    uint32_t                                 handle;
+} VkImportSemaphoreZirconHandleInfoFUCHSIA;
+
+typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkSemaphore                              semaphore;
+    VkExternalSemaphoreHandleTypeFlagBits    handleType;
+} VkSemaphoreGetZirconHandleInfoFUCHSIA;
+
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA \
+    ((VkExternalSemaphoreHandleTypeFlagBits)0x00100000)
+#endif  // VK_FUCHSIA_external_semaphore
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/system/vulkan_enc/vk_format_info.h b/system/vulkan_enc/vk_format_info.h
index 3bac828..c70f45f 100644
--- a/system/vulkan_enc/vk_format_info.h
+++ b/system/vulkan_enc/vk_format_info.h
@@ -58,7 +58,7 @@
 }
 
 static inline unsigned
-android_format_from_vk(unsigned vk_format)
+android_format_from_vk(VkFormat vk_format)
 {
    switch (vk_format) {
    case VK_FORMAT_R8G8B8A8_UNORM:
@@ -78,6 +78,18 @@
    }
 }
 
+static inline bool
+android_format_is_yuv(unsigned android_format)
+{
+   switch (android_format) {
+   case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
+      return true;
+
+   default:
+      return false;
+   }
+}
+
 static inline VkImageAspectFlags
 vk_format_aspects(VkFormat format)
 {
diff --git a/system/vulkan_enc/vk_struct_id.h b/system/vulkan_enc/vk_struct_id.h
new file mode 100644
index 0000000..561b430
--- /dev/null
+++ b/system/vulkan_enc/vk_struct_id.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2018 The Android Open Source Project
+// Copyright (C) 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <vulkan/vulkan.h>
+#include "goldfish_vk_private_defs.h"
+
+template <class T> struct vk_get_vk_struct_id;
+
+#define REGISTER_VK_STRUCT_ID(T, ID) \
+    template <> struct vk_get_vk_struct_id<T> { static constexpr VkStructureType id = ID; };
+
+REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferPropertiesANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID);
+REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferFormatPropertiesANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
+REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferUsageANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID);
+REGISTER_VK_STRUCT_ID(VkBufferCreateInfo, VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkImageCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkImageFormatProperties2, VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2);
+REGISTER_VK_STRUCT_ID(VkNativeBufferANDROID, VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID);
+REGISTER_VK_STRUCT_ID(VkExternalFormatANDROID, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
+REGISTER_VK_STRUCT_ID(VkExternalMemoryBufferCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkExternalMemoryImageCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkMemoryAllocateInfo, VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
+REGISTER_VK_STRUCT_ID(VkMemoryDedicatedAllocateInfo, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO);
+REGISTER_VK_STRUCT_ID(VkMemoryDedicatedRequirements, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS);
+REGISTER_VK_STRUCT_ID(VkImportAndroidHardwareBufferInfoANDROID, VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
+REGISTER_VK_STRUCT_ID(VkExportMemoryAllocateInfo, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO);
+REGISTER_VK_STRUCT_ID(VkMemoryRequirements2, VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2);
+REGISTER_VK_STRUCT_ID(VkSemaphoreCreateInfo, VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkExportSemaphoreCreateInfoKHR, VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR);
+REGISTER_VK_STRUCT_ID(VkSamplerYcbcrConversionCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkImportColorBufferGOOGLE, VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE);
+REGISTER_VK_STRUCT_ID(VkImageViewCreateInfo, VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+REGISTER_VK_STRUCT_ID(VkImportMemoryBufferCollectionFUCHSIA, VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
+REGISTER_VK_STRUCT_ID(VkImportMemoryZirconHandleInfoFUCHSIA, VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA);
+REGISTER_VK_STRUCT_ID(VkBufferCollectionImageCreateInfoFUCHSIA, VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA);
+
+#undef REGISTER_VK_STRUCT_ID
diff --git a/system/vulkan_enc/vk_util.h b/system/vulkan_enc/vk_util.h
index 41410d3..39de991 100644
--- a/system/vulkan_enc/vk_util.h
+++ b/system/vulkan_enc/vk_util.h
@@ -27,6 +27,7 @@
 
 #include <vulkan/vulkan.h>
 #include <stdlib.h>
+#include "vk_struct_id.h"
 
 struct vk_struct_common {
     VkStructureType sType;
@@ -196,23 +197,17 @@
    return NULL;
 }
 
-template <class T> void vk_is_vk_struct(T *s)
+template <class T, class H> T* vk_find_struct(H* head)
 {
-    static_assert(sizeof(s->sType) == sizeof(VkStructureType), "Vulkan structures has the sType field of type VkStructureType");
-    static_assert(sizeof(s->pNext) == sizeof(void*), "Vulkan structures has the pNext field of void*");
+    vk_get_vk_struct_id<H>::id;
+    return static_cast<T*>(__vk_find_struct(static_cast<void*>(head), vk_get_vk_struct_id<T>::id));
 }
 
-template <class T, class H> T* vk_find_struct(H* head, VkStructureType sType)
+template <class T, class H> const T* vk_find_struct(const H* head)
 {
-    vk_is_vk_struct(head);
-    return static_cast<T*>(__vk_find_struct(static_cast<void*>(head), sType));
-}
-
-template <class T, class H> const T* vk_find_struct(const H* head, VkStructureType sType)
-{
-    vk_is_vk_struct(head);
+    vk_get_vk_struct_id<H>::id;
     return static_cast<const T*>(__vk_find_struct(const_cast<void*>(static_cast<const void*>(head)),
-                                 sType));
+                                 vk_get_vk_struct_id<T>::id));
 }
 
 uint32_t vk_get_driver_version(void);
@@ -233,14 +228,14 @@
 
 template <class T> vk_struct_chain_iterator vk_make_chain_iterator(T* vk_struct)
 {
-    vk_is_vk_struct(vk_struct);
+    vk_get_vk_struct_id<T>::id;
     vk_struct_chain_iterator result = { reinterpret_cast<vk_struct_common*>(vk_struct) };
     return result;
 }
 
 template <class T> void vk_append_struct(vk_struct_chain_iterator* i, T* vk_struct)
 {
-    vk_is_vk_struct(vk_struct);
+    vk_get_vk_struct_id<T>::id;
 
     vk_struct_common* p = i->value;
     if (p->pNext) {