Flush host connection on rcFBPost am: 8c6155f638 am: e21eaf905b am: 86db2b292d

Original change: https://googleplex-android-review.googlesource.com/c/device/generic/goldfish-opengl/+/10598279

Change-Id: I020587322990fe8bbbcee5d7a09bcc8d39f9bdb1
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..482e5a6
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+soong_namespace {}
diff --git a/Android.mk b/Android.mk
index 7afa40a..90d028b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -130,6 +130,9 @@
 # Note that the build system will complain if you try to import a
 # module that hasn't been declared yet anyway.
 #
+include $(GOLDFISH_OPENGL_PATH)/shared/qemupipe/Android.mk
+include $(GOLDFISH_OPENGL_PATH)/shared/gralloc_cb/Android.mk
+include $(GOLDFISH_OPENGL_PATH)/shared/GoldfishAddressSpace/Android.mk
 include $(GOLDFISH_OPENGL_PATH)/shared/OpenglCodecCommon/Android.mk
 
 # Encoder shared libraries
@@ -154,8 +157,6 @@
 include $(GOLDFISH_OPENGL_PATH)/system/hals/Android.mk
 endif
 
-include $(GOLDFISH_OPENGL_PATH)/system/cbmanager/Android.mk
-
 include $(GOLDFISH_OPENGL_PATH)/system/egl/Android.mk
 
 ifeq (true,$(BUILD_EMULATOR_VULKAN)) # Vulkan libs
diff --git a/BUILD.gn b/BUILD.gn
index 0e2fea1..62cb990 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -28,14 +28,19 @@
     "android-emu/android/base/threads/AndroidWorkPool.cpp",
     "android-emu/android/base/Tracing.cpp",
     "android-emu/android/base/Tracing.h",
+    "shared/GoldfishAddressSpace/goldfish_address_space.cpp",
+    "shared/GoldfishAddressSpace/goldfish_address_space.h",
     "shared/OpenglCodecCommon/ChecksumCalculator.cpp",
     "shared/OpenglCodecCommon/ChecksumCalculator.h",
     "shared/OpenglCodecCommon/glUtils.cpp",
     "shared/OpenglCodecCommon/glUtils.h",
-    "shared/OpenglCodecCommon/goldfish_address_space.cpp",
-    "shared/OpenglCodecCommon/goldfish_address_space.h",
     "shared/OpenglCodecCommon/goldfish_dma.cpp",
     "shared/OpenglCodecCommon/goldfish_dma.h",
+    "shared/gralloc_cb/include/gralloc_cb_bp.h",
+    "shared/qemupipe/include/qemu_pipe_bp.h",
+    "shared/qemupipe/include-types/qemu_pipe_types_bp.h",
+    "shared/qemupipe/qemu_pipe_common.cpp",
+    "shared/qemupipe/qemu_pipe_guest.cpp",
     "system/OpenglSystemCommon/AddressSpaceStream.cpp",
     "system/OpenglSystemCommon/HostConnection.cpp",
     "system/OpenglSystemCommon/HostConnection.h",
@@ -77,7 +82,11 @@
   include_dirs = [
     "android-emu",
     "host/include/libOpenglRender",
+    "shared/GoldfishAddressSpace/include",
     "shared/OpenglCodecCommon",
+    "shared/gralloc_cb/include",
+    "shared/qemupipe/include",
+    "shared/qemupipe/include-types",
     "system/OpenglSystemCommon",
     "system/renderControl_enc",
     "system/vulkan_enc",
@@ -131,12 +140,12 @@
 
     deps = [
       "//sdk/fidl/fuchsia.hardware.goldfish",
-      "//zircon/system/fidl/fuchsia-sysmem",
-      "//zircon/public/lib/trace-with-static-engine",
-      "//zircon/public/lib/syslog-static",
+      "//sdk/fidl/fuchsia.logger:fuchsia.logger_llcpp",
+      "//sdk/fidl/fuchsia.sysmem",
       "//zircon/public/lib/zx",
       "//zircon/public/lib/zxio",
-      "//zircon/system/fidl/fuchsia-logger:llcpp",
+      "//zircon/system/ulib/syslog:syslog-static",
+      "//zircon/system/ulib/trace:trace-with-static-engine",
     ]
 
     defines += [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c58ad1..80c99c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,10 @@
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
 set(GOLDFISH_DEVICE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/./Android.mk" "c8e5536771d09cd120c3e396beac994a1e2d2880f37b4e3bd1844be4cfc31555")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/./Android.mk" "a370ddecca4c7d13811527b2f1f30e2f0ef5153a58edeb36eeb306c41efb9158")
+add_subdirectory(shared/qemupipe)
+add_subdirectory(shared/gralloc_cb)
+add_subdirectory(shared/GoldfishAddressSpace)
 add_subdirectory(shared/OpenglCodecCommon)
 add_subdirectory(system/GLESv1_enc)
 add_subdirectory(system/GLESv2_enc)
diff --git a/android-emu/Android.bp b/android-emu/Android.bp
new file mode 100644
index 0000000..68df03e
--- /dev/null
+++ b/android-emu/Android.bp
@@ -0,0 +1,35 @@
+cc_library_shared {
+    name: "libandroidemu",
+    vendor: true,
+    srcs: [
+        "android/base/AlignedBuf.cpp",
+        "android/base/files/MemStream.cpp",
+        "android/base/files/Stream.cpp",
+        "android/base/files/StreamSerializing.cpp",
+        "android/base/Pool.cpp",
+        "android/base/ring_buffer.c",
+        "android/base/StringFormat.cpp",
+        "android/base/AndroidSubAllocator.cpp",
+        "android/base/synchronization/AndroidMessageChannel.cpp",
+        "android/base/threads/AndroidFunctorThread.cpp",
+        "android/base/threads/AndroidThreadStore.cpp",
+        "android/base/threads/AndroidThread_pthread.cpp",
+        "android/base/threads/AndroidWorkPool.cpp",
+        "android/base/Tracing.cpp",
+        "android/utils/debug.c",
+    ],
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "liblog",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"androidemu\"",
+        "-Wno-missing-field-initializers",
+        "-fvisibility=default",
+        "-fstrict-aliasing",
+    ],
+}
diff --git a/android-emu/Android.mk b/android-emu/Android.mk
index 4be199b..ef67ddc 100644
--- a/android-emu/Android.mk
+++ b/android-emu/Android.mk
@@ -1,3 +1,4 @@
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
 LOCAL_PATH := $(call my-dir)
 
 $(call emugl-begin-shared-library,libandroidemu)
@@ -28,3 +29,4 @@
     android/utils/debug.c \
 
 $(call emugl-end-module)
+endif
diff --git a/android-emu/CMakeLists.txt b/android-emu/CMakeLists.txt
index f490697..cfdf39b 100644
--- a/android-emu/CMakeLists.txt
+++ b/android-emu/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "e7c9acc2277e7c651d6e722f96705a1fd445441b5ab6bb5b6d5b4c46dddfc702")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "bd7f25228f5fed42d7a66a35c585d88bd77221db773a6aeb42403089703819e9")
 set(androidemu_src android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/ring_buffer.c android/base/StringFormat.cpp android/base/AndroidSubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
 android_add_library(TARGET androidemu SHARED LICENSE Apache-2.0 SRC android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/ring_buffer.c android/base/StringFormat.cpp android/base/AndroidSubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
 target_include_directories(androidemu PRIVATE ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(androidemu PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"androidemu\"")
 target_compile_options(androidemu PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-missing-field-initializers" "-fstrict-aliasing")
-target_link_libraries(androidemu PRIVATE cutils utils log OpenglCodecCommon_host android-emu-shared)
\ No newline at end of file
+target_link_libraries(androidemu PRIVATE cutils utils log OpenglCodecCommon_host android-emu-shared PRIVATE qemupipe_host)
\ No newline at end of file
diff --git a/android-emu/android/base/AlignedBuf.h b/android-emu/android/base/AlignedBuf.h
index fc74e32..5955fa1 100644
--- a/android-emu/android/base/AlignedBuf.h
+++ b/android-emu/android/base/AlignedBuf.h
@@ -1,13 +1,16 @@
 // Copyright 2018 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/Compiler.h b/android-emu/android/base/Compiler.h
index ddfd992..00261b0 100644
--- a/android-emu/android/base/Compiler.h
+++ b/android-emu/android/base/Compiler.h
@@ -1,13 +1,16 @@
 // Copyright 2014 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/EnumFlags.h b/android-emu/android/base/EnumFlags.h
index fec56b9..1597dda 100644
--- a/android-emu/android/base/EnumFlags.h
+++ b/android-emu/android/base/EnumFlags.h
@@ -1,13 +1,16 @@
 // Copyright 2015 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/Optional.h b/android-emu/android/base/Optional.h
index c599828..4ed0c39 100644
--- a/android-emu/android/base/Optional.h
+++ b/android-emu/android/base/Optional.h
@@ -1,13 +1,16 @@
 // Copyright 2015-2016 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/StringFormat.cpp b/android-emu/android/base/StringFormat.cpp
index 73a0e7a..58fb947 100644
--- a/android-emu/android/base/StringFormat.cpp
+++ b/android-emu/android/base/StringFormat.cpp
@@ -1,13 +1,16 @@
 // Copyright 2014 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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.
 
 #include "android/base/StringFormat.h"
 
diff --git a/android-emu/android/base/StringFormat.h b/android-emu/android/base/StringFormat.h
index 184ee5f..d0fd3df 100644
--- a/android-emu/android/base/StringFormat.h
+++ b/android-emu/android/base/StringFormat.h
@@ -1,13 +1,16 @@
 // Copyright 2014 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/StringView.h b/android-emu/android/base/StringView.h
index f97ac5f..a6d9a61 100644
--- a/android-emu/android/base/StringView.h
+++ b/android-emu/android/base/StringView.h
@@ -1,13 +1,16 @@
 // Copyright 2014 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/Tracing.cpp b/android-emu/android/base/Tracing.cpp
index ff72093..a4c097f 100644
--- a/android-emu/android/base/Tracing.cpp
+++ b/android-emu/android/base/Tracing.cpp
@@ -37,7 +37,7 @@
 #elif __Fuchsia__
 
 #ifndef FUCHSIA_NO_TRACE
-#include <trace/event.h>
+#include <lib/trace/event.h>
 #endif
 
 #define VK_TRACE_TAG "gfx"
diff --git a/android-emu/android/base/containers/SmallVector.h b/android-emu/android/base/containers/SmallVector.h
index dc49a70..92e2d27 100644
--- a/android-emu/android/base/containers/SmallVector.h
+++ b/android-emu/android/base/containers/SmallVector.h
@@ -1,13 +1,16 @@
 // Copyright 2016 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/files/MemStream.cpp b/android-emu/android/base/files/MemStream.cpp
index 4f8291f..f2b0055 100644
--- a/android-emu/android/base/files/MemStream.cpp
+++ b/android-emu/android/base/files/MemStream.cpp
@@ -1,13 +1,16 @@
 // Copyright 2015 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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.
 
 #include "android/base/files/MemStream.h"
 
diff --git a/android-emu/android/base/files/MemStream.h b/android-emu/android/base/files/MemStream.h
index e256a68..5c5b0f6 100644
--- a/android-emu/android/base/files/MemStream.h
+++ b/android-emu/android/base/files/MemStream.h
@@ -1,13 +1,16 @@
 // Copyright 2015 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/files/Stream.cpp b/android-emu/android/base/files/Stream.cpp
index dd4c9ef..db34ed3 100644
--- a/android-emu/android/base/files/Stream.cpp
+++ b/android-emu/android/base/files/Stream.cpp
@@ -1,13 +1,16 @@
 // Copyright 2015 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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.
 
 #include "android/base/files/Stream.h"
 
diff --git a/android-emu/android/base/files/Stream.h b/android-emu/android/base/files/Stream.h
index 8e2b0a0..3a5632e 100644
--- a/android-emu/android/base/files/Stream.h
+++ b/android-emu/android/base/files/Stream.h
@@ -1,13 +1,16 @@
 // Copyright 2015 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/files/StreamSerializing.cpp b/android-emu/android/base/files/StreamSerializing.cpp
index 2a9d77a..d88a1fc 100644
--- a/android-emu/android/base/files/StreamSerializing.cpp
+++ b/android-emu/android/base/files/StreamSerializing.cpp
@@ -1,13 +1,16 @@
 // Copyright 2017 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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.
 
 #include "android/base/files/StreamSerializing.h"
 
diff --git a/android-emu/android/base/files/StreamSerializing.h b/android-emu/android/base/files/StreamSerializing.h
index 8e56a6e..56613f5 100644
--- a/android-emu/android/base/files/StreamSerializing.h
+++ b/android-emu/android/base/files/StreamSerializing.h
@@ -1,13 +1,16 @@
 // Copyright 2017 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/base/ring_buffer.c b/android-emu/android/base/ring_buffer.c
index f6b3b78..527d2ea 100644
--- a/android-emu/android/base/ring_buffer.c
+++ b/android-emu/android/base/ring_buffer.c
@@ -405,13 +405,7 @@
     return (long)steps;
 }
 
-void ring_buffer_yield() {
-#ifdef _WIN32
-    ring_buffer_pause();
-#else
-    sched_yield();
-#endif
-}
+void ring_buffer_yield() { }
 
 static void ring_buffer_sleep() {
 #ifdef _WIN32
@@ -421,26 +415,12 @@
 #endif
 }
 
-static uint64_t ring_buffer_curr_us() {
-    uint64_t res;
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    res = tv.tv_sec * 1000000ULL + tv.tv_usec;
-    return res;
-}
-
-static const uint32_t yield_backoff_us = 1000;
-static const uint32_t sleep_backoff_us = 2000;
-
 bool ring_buffer_wait_write(
     const struct ring_buffer* r,
     const struct ring_buffer_view* v,
     uint32_t bytes,
     uint64_t timeout_us) {
 
-    uint64_t start_us = ring_buffer_curr_us();
-    uint64_t curr_wait_us;
-
     bool can_write =
         v ? ring_buffer_view_can_write(r, v, bytes) :
             ring_buffer_can_write(r, bytes);
@@ -481,7 +461,6 @@
     struct ring_buffer_view* v,
     uint32_t bytes) {
 
-    uint32_t step_shift = 0;
     uint32_t available = v ? (v->size >> 1) : (RING_BUFFER_SIZE >> 1);
     uint32_t res = available < bytes ? available : bytes;
 
diff --git a/android-emu/android/utils/compiler.h b/android-emu/android/utils/compiler.h
index 0d72fee..fae0918 100644
--- a/android-emu/android/utils/compiler.h
+++ b/android-emu/android/utils/compiler.h
@@ -1,13 +1,16 @@
 // Copyright 2014 The Android Open Source Project
 //
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
+// 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
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// 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
 
diff --git a/android-emu/android/utils/debug.c b/android-emu/android/utils/debug.c
index 238bd87..27ad1d6 100644
--- a/android-emu/android/utils/debug.c
+++ b/android-emu/android/utils/debug.c
@@ -1,14 +1,16 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-*/
+// Copyright 2007-2008 The Android Open Source Project
+//
+// 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.
 #include "android/utils/debug.h"
 
 #include <fcntl.h>
diff --git a/android-emu/android/utils/debug.h b/android-emu/android/utils/debug.h
index a6cdc02..be1c1b2 100644
--- a/android-emu/android/utils/debug.h
+++ b/android-emu/android/utils/debug.h
@@ -1,14 +1,16 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-*/
+// Copyright 2007-2008 The Android Open Source Project
+//
+// 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
 
diff --git a/cmake_transform.py b/cmake_transform.py
index 3583ec8..298e454 100644
--- a/cmake_transform.py
+++ b/cmake_transform.py
@@ -106,7 +106,7 @@
     flags = [escape(d) for d in module['cflags'] if not d.startswith('-D')]
 
     # Make sure we remove the lib prefix from all our dependencies.
-    libs = [remove_lib_prefix(l) for l in module['libs']]
+    libs = [remove_lib_prefix(l) for l in module.get('libs', [])]
     staticlibs = [remove_lib_prefix(l) for l in
                       module.get('staticlibs', [])
                       if l != "libandroidemu"]
diff --git a/host/include/libOpenglRender/IOStream.h b/host/include/libOpenglRender/IOStream.h
index 2f699bc..9173d31 100644
--- a/host/include/libOpenglRender/IOStream.h
+++ b/host/include/libOpenglRender/IOStream.h
@@ -93,7 +93,11 @@
         return readFully(buf, len);
     }
 
+    // These two methods are defined and used in GLESv2_enc. Any reference
+    // outside of GLESv2_enc will produce a link error. This is intentional
+    // (technical debt).
     void readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels);
+    void uploadPixels(void* context, int width, int height, int depth, unsigned int format, unsigned int type, const void* pixels);
 
 
 private:
diff --git a/shared/GoldfishAddressSpace/Android.bp b/shared/GoldfishAddressSpace/Android.bp
new file mode 100644
index 0000000..6dcdb56
--- /dev/null
+++ b/shared/GoldfishAddressSpace/Android.bp
@@ -0,0 +1,16 @@
+cc_library_static {
+    name: "libGoldfishAddressSpace",
+    vendor: true,
+    srcs: [
+        "goldfish_address_space.cpp",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"goldfish-address-space\"",
+    ],
+}
diff --git a/shared/GoldfishAddressSpace/Android.mk b/shared/GoldfishAddressSpace/Android.mk
new file mode 100644
index 0000000..221ea8b
--- /dev/null
+++ b/shared/GoldfishAddressSpace/Android.mk
@@ -0,0 +1,15 @@
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+
+LOCAL_PATH := $(call my-dir)
+
+$(call emugl-begin-static-library,libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX))
+
+LOCAL_SRC_FILES := goldfish_address_space.cpp
+
+LOCAL_CFLAGS += -DLOG_TAG=\"goldfish-address-space\"
+
+$(call emugl-export,SHARED_LIBRARIES,liblog android-emu-shared)
+$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include)
+$(call emugl-end-module)
+
+endif
diff --git a/shared/GoldfishAddressSpace/CMakeLists.txt b/shared/GoldfishAddressSpace/CMakeLists.txt
new file mode 100644
index 0000000..c89a436
--- /dev/null
+++ b/shared/GoldfishAddressSpace/CMakeLists.txt
@@ -0,0 +1,10 @@
+# This is an autogenerated file! Do not edit!
+# instead run make from .../device/generic/goldfish-opengl
+# which will re-generate this file.
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/Android.mk" "2b12d7f8c4c62c3a909b9771662cf18c9e4d16c58c95a11e225fe2b46432e862")
+set(GoldfishAddressSpace_host_src goldfish_address_space.cpp)
+android_add_library(TARGET GoldfishAddressSpace_host LICENSE Apache-2.0 SRC goldfish_address_space.cpp)
+target_include_directories(GoldfishAddressSpace_host PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_compile_definitions(GoldfishAddressSpace_host PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"goldfish-address-space\"")
+target_compile_options(GoldfishAddressSpace_host PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
+target_link_libraries(GoldfishAddressSpace_host PRIVATE log android-emu-shared)
\ No newline at end of file
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.cpp b/shared/GoldfishAddressSpace/goldfish_address_space.cpp
similarity index 100%
rename from shared/OpenglCodecCommon/goldfish_address_space.cpp
rename to shared/GoldfishAddressSpace/goldfish_address_space.cpp
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.h b/shared/GoldfishAddressSpace/include/goldfish_address_space.h
similarity index 86%
rename from shared/OpenglCodecCommon/goldfish_address_space.h
rename to shared/GoldfishAddressSpace/include/goldfish_address_space.h
index 064f601..044e18a 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space.h
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
 
 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
@@ -48,6 +48,7 @@
     Graphics = 0,
     Media = 1,
     HostMemoryAllocator = 5,
+    SharedSlotsHostMemoryAllocator = 6,
 };
 
 class GoldfishAddressSpaceBlockProvider {
@@ -114,7 +115,7 @@
 
 class GoldfishAddressSpaceHostMemoryAllocator {
 public:
-    GoldfishAddressSpaceHostMemoryAllocator();
+    GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots);
 
     long hostMalloc(GoldfishAddressSpaceBlock *block, size_t size);
     void hostFree(GoldfishAddressSpaceBlock *block);
@@ -125,6 +126,7 @@
 
 private:
     GoldfishAddressSpaceBlockProvider m_provider;
+    bool                              m_useSharedSlots;
 };
 
 // Convenience functions that run address space driver api without wrapping in
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_android.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
similarity index 89%
rename from shared/OpenglCodecCommon/goldfish_address_space_android.impl
rename to shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
index 646695f..8ff7e78 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_android.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
@@ -25,11 +25,7 @@
 #include <errno.h>
 #include <memory>
 
-#if PLATFORM_SDK_VERSION < 26
-#include <cutils/log.h>
-#else
 #include <log/log.h>
-#endif
 
 #include "goldfish_address_space.h"
 
@@ -86,7 +82,12 @@
     request.version = sizeof(request);
     request.metadata = type;
 
-    return ioctl_ping(fd, &request);
+    long ret = ioctl_ping(fd, &request);
+    if (ret) {
+        return ret;
+    }
+
+    return request.metadata;
 }
 
 long ioctl_claim_shared(int fd, struct goldfish_address_space_claim_shared *request)
@@ -106,7 +107,7 @@
 {
     if ((subdevice != GoldfishAddressSpaceSubdeviceType::NoSubdevice) && is_opened()) {
         const long ret = set_address_space_subdevice_type(m_handle, subdevice);
-        if (ret) {
+        if (ret != 0 && ret != subdevice) {  // TODO: retire the 'ret != subdevice' check
             ALOGE("%s: set_address_space_subdevice_type failed for device_type=%lu, ret=%ld",
                   __func__, static_cast<unsigned long>(subdevice), ret);
             close();
@@ -337,8 +338,12 @@
     ::munmap(ptr, size);
 }
 
-GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
-  : m_provider(GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator) {}
+GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots)
+  : m_provider(useSharedSlots
+        ? GoldfishAddressSpaceSubdeviceType::SharedSlotsHostMemoryAllocator
+        : GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator),
+    m_useSharedSlots(useSharedSlots)
+{}
 
 bool GoldfishAddressSpaceHostMemoryAllocator::is_opened() const { return m_provider.is_opened(); }
 
@@ -353,24 +358,45 @@
     if (!m_provider.is_opened()) {
         return -ENODEV;
     }
-    if (!block->allocate(&m_provider, size)) {
-        return -ENOMEM;
-    }
 
     struct goldfish_address_space_ping request;
-    ::memset(&request, 0, sizeof(request));
-    request.version = sizeof(request);
-    request.offset = block->offset();
-    request.size = block->size();
-    request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
+    if (m_useSharedSlots) {
+        // shared memory slots are supported
+        ::memset(&request, 0, sizeof(request));
+        request.version = sizeof(request);
+        request.size = size;
+        request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
 
-    long ret = ioctl_ping(m_provider.m_handle, &request);
-    if (ret) {
-        return ret;
-    }
-    ret = static_cast<long>(request.metadata);
-    if (ret) {
-        return ret;
+        long ret = ioctl_ping(m_provider.m_handle, &request);
+        if (ret) {
+            return ret;
+        }
+        ret = static_cast<long>(request.metadata);
+        if (ret) {
+            return ret;
+        }
+
+        block->claimShared(&m_provider, request.offset, request.size);
+    } else {
+        // shared memory slots are not supported
+        if (!block->allocate(&m_provider, size)) {
+            return -ENOMEM;
+        }
+
+        ::memset(&request, 0, sizeof(request));
+        request.version = sizeof(request);
+        request.offset = block->offset();
+        request.size = block->size();
+        request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
+
+        long ret = ioctl_ping(m_provider.m_handle, &request);
+        if (ret) {
+            return ret;
+        }
+        ret = static_cast<long>(request.metadata);
+        if (ret) {
+            return ret;
+        }
     }
 
     block->mmap(0);
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
similarity index 99%
rename from shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
rename to shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
index 4d54eed..e16bd80 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
@@ -228,7 +228,7 @@
     }
 }
 
-GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
+GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots)
   : m_provider(GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator) { }
 
 long GoldfishAddressSpaceHostMemoryAllocator::hostMalloc(GoldfishAddressSpaceBlock *block, size_t size)
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_host.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
similarity index 87%
rename from shared/OpenglCodecCommon/goldfish_address_space_host.impl
rename to shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
index 6630ed7..8995c6b 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_host.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
@@ -231,8 +231,12 @@
 
 void GoldfishAddressSpaceBlock::memoryUnmap(void *ptr, size_t size) {}
 
-GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
-  : m_provider(GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator) {}
+GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots)
+  : m_provider(useSharedSlots
+        ? GoldfishAddressSpaceSubdeviceType::SharedSlotsHostMemoryAllocator
+        : GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator),
+    m_useSharedSlots(useSharedSlots)
+{}
 
 bool GoldfishAddressSpaceHostMemoryAllocator::is_opened() const { return m_provider.is_opened(); }
 
@@ -247,20 +251,34 @@
     if (!m_provider.is_opened()) {
         return -ENODEV;
     }
-    if (!block->allocate(&m_provider, size)) {
-        return -ENOMEM;
-    }
 
     AddressSpaceDevicePingInfo request;
-    ::memset(&request, 0, sizeof(request));
-    request.phys_addr = block->physAddr();
-    request.size = block->size();
-    request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
+    if (m_useSharedSlots) {
+        ::memset(&request, 0, sizeof(request));
+        request.size = block->size();
+        request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
 
-    HostAddressSpaceDevice::get()->ping(m_provider.m_handle, &request);
+        HostAddressSpaceDevice::get()->ping(m_provider.m_handle, &request);
 
-    void *hostPtr = HostAddressSpaceDevice::get()->getHostAddr(block->physAddr());
-    block->mmap(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(hostPtr)));
+        block->claimShared(&m_provider, request.phys_addr, request.size);
+
+        void *hostPtr = HostAddressSpaceDevice::get()->getHostAddr(block->physAddr());
+        block->mmap(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(hostPtr)));
+    } else {
+        if (!block->allocate(&m_provider, size)) {
+            return -ENOMEM;
+        }
+
+        ::memset(&request, 0, sizeof(request));
+        request.phys_addr = block->physAddr();
+        request.size = block->size();
+        request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;
+
+        HostAddressSpaceDevice::get()->ping(m_provider.m_handle, &request);
+
+        void *hostPtr = HostAddressSpaceDevice::get()->getHostAddr(block->physAddr());
+        block->mmap(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(hostPtr)));
+    }
 
     return 0;
 }
diff --git a/shared/OpenglCodecCommon/Android.bp b/shared/OpenglCodecCommon/Android.bp
deleted file mode 100644
index e56dfcd..0000000
--- a/shared/OpenglCodecCommon/Android.bp
+++ /dev/null
@@ -1,5 +0,0 @@
-cc_library_headers {
-    name: "goldfish_pipe_headers",
-    vendor_available: true,
-    export_include_dirs: ["."],
-}
diff --git a/shared/OpenglCodecCommon/Android.mk b/shared/OpenglCodecCommon/Android.mk
index af7c65d..d9970d5 100644
--- a/shared/OpenglCodecCommon/Android.mk
+++ b/shared/OpenglCodecCommon/Android.mk
@@ -13,13 +13,11 @@
         SocketStream.cpp \
         TcpStream.cpp \
         auto_goldfish_dma_context.cpp \
-        goldfish_address_space.cpp \
 
 ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
 
 commonSources += \
         goldfish_dma_host.cpp \
-        qemu_pipe_host.cpp \
 
 else
 
@@ -31,6 +29,12 @@
 ### CodecCommon  guest ##############################################
 $(call emugl-begin-shared-library,libOpenglCodecCommon$(GOLDFISH_OPENGL_LIB_SUFFIX))
 
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-import,libqemupipe$(GOLDFISH_OPENGL_LIB_SUFFIX))
+else
+$(call emugl-export,STATIC_LIBRARIES,libqemupipe.ranchu)
+endif
+
 LOCAL_SRC_FILES := $(commonSources)
 
 LOCAL_CFLAGS += -DLOG_TAG=\"eglCodecCommon\"
diff --git a/shared/OpenglCodecCommon/CMakeLists.txt b/shared/OpenglCodecCommon/CMakeLists.txt
index 4528e13..6a1ac4a 100644
--- a/shared/OpenglCodecCommon/CMakeLists.txt
+++ b/shared/OpenglCodecCommon/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon/Android.mk" "b93e7098601bba92b0e1b4d4a94cee25d2181a9842c7902d5f339c405c862cea")
-set(OpenglCodecCommon_host_src GLClientState.cpp GLESTextureUtils.cpp ChecksumCalculator.cpp GLSharedGroup.cpp glUtils.cpp IndexRangeCache.cpp SocketStream.cpp TcpStream.cpp auto_goldfish_dma_context.cpp goldfish_address_space.cpp goldfish_dma_host.cpp qemu_pipe_host.cpp)
-android_add_library(TARGET OpenglCodecCommon_host SHARED LICENSE Apache-2.0 SRC GLClientState.cpp GLESTextureUtils.cpp ChecksumCalculator.cpp GLSharedGroup.cpp glUtils.cpp IndexRangeCache.cpp SocketStream.cpp TcpStream.cpp auto_goldfish_dma_context.cpp goldfish_address_space.cpp goldfish_dma_host.cpp qemu_pipe_host.cpp)
-target_include_directories(OpenglCodecCommon_host PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon/Android.mk" "87f5c2c694647e3a38b4da1b4c653b99cd27d934b60ecd43aff59d3765daabfd")
+set(OpenglCodecCommon_host_src GLClientState.cpp GLESTextureUtils.cpp ChecksumCalculator.cpp GLSharedGroup.cpp glUtils.cpp IndexRangeCache.cpp SocketStream.cpp TcpStream.cpp auto_goldfish_dma_context.cpp goldfish_dma_host.cpp)
+android_add_library(TARGET OpenglCodecCommon_host SHARED LICENSE Apache-2.0 SRC GLClientState.cpp GLESTextureUtils.cpp ChecksumCalculator.cpp GLSharedGroup.cpp glUtils.cpp IndexRangeCache.cpp SocketStream.cpp TcpStream.cpp auto_goldfish_dma_context.cpp goldfish_dma_host.cpp)
+target_include_directories(OpenglCodecCommon_host PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(OpenglCodecCommon_host PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"eglCodecCommon\"")
 target_compile_options(OpenglCodecCommon_host PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-unused-private-field")
-target_link_libraries(OpenglCodecCommon_host PRIVATE android-emu-shared cutils utils log)
\ No newline at end of file
+target_link_libraries(OpenglCodecCommon_host PRIVATE android-emu-shared cutils utils log PRIVATE qemupipe_host)
\ No newline at end of file
diff --git a/shared/OpenglCodecCommon/ErrorLog.h b/shared/OpenglCodecCommon/ErrorLog.h
index fa2b0a2..7f693b7 100644
--- a/shared/OpenglCodecCommon/ErrorLog.h
+++ b/shared/OpenglCodecCommon/ErrorLog.h
@@ -17,11 +17,7 @@
 #define _ERROR_LOG_H_
 
 #if defined(__ANDROID__)
-#    if PLATFORM_SDK_VERSION < 26
-#        include <cutils/log.h>
-#    else
-#        include <log/log.h>
-#    endif
+#    include <log/log.h>
 #    define ERR(...)    ALOGE(__VA_ARGS__)
 #    ifdef EMUGL_DEBUG
 #        define DBG(...)    ALOGD(__VA_ARGS__)
@@ -29,7 +25,7 @@
 #        define DBG(...)    ((void)0)
 #    endif
 #else
-#     include <stdio.h>
+#    include <stdio.h>
 #    define ERR(...)    fprintf(stderr, __VA_ARGS__)
 #    ifdef EMUGL_DEBUG
 #        define DBG(...)    fprintf(stderr, __VA_ARGS__)
diff --git a/shared/OpenglCodecCommon/FixedBuffer.h b/shared/OpenglCodecCommon/FixedBuffer.h
deleted file mode 100644
index 8c34749..0000000
--- a/shared/OpenglCodecCommon/FixedBuffer.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* 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.
-*/
-#ifndef _FIXED_BUFFER_H
-#define _FIXED_BUFFER_H
-
-#if PLATFORM_SDK_VERSION < 26
-#include <cutils/log.h>
-#else
-#include <log/log.h>
-#endif
-
-class FixedBuffer {
-public:
-    FixedBuffer(size_t initialSize = 0) {
-        m_buffer = NULL;
-        m_bufferLen = initialSize;
-        alloc(m_bufferLen);
-    }
-
-    ~FixedBuffer() {
-        delete [] m_buffer;
-        m_bufferLen = 0;
-    }
-
-    void * alloc(size_t size) {
-        if (m_bufferLen >= size)
-            return (void *)(m_buffer);
-
-        if (m_buffer != NULL)
-            delete[] m_buffer;
-
-        m_bufferLen = size;
-        m_buffer = new unsigned char[m_bufferLen];
-        if (m_buffer == NULL)
-            m_bufferLen = 0;
-
-        return m_buffer;
-    }
-    void *ptr() { return m_buffer; }
-    size_t len() { return m_bufferLen; }
-private:
-    unsigned char *m_buffer;
-    size_t m_bufferLen;
-};
-
-#endif
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index c6140db..a31f697 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -852,7 +852,7 @@
     return 1;
 }
 
-void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
+void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
 {
     if (width <= 0 || height <= 0) {
         *startOffset = 0;
@@ -868,6 +868,7 @@
             m_pixelStore.pack_row_length,
             m_pixelStore.pack_skip_pixels,
             m_pixelStore.pack_skip_rows,
+            bpp,
             startOffset,
             pixelRowSize,
             totalRowSize);
@@ -875,6 +876,59 @@
     *skipRows = m_pixelStore.pack_skip_rows;
 }
 
+void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
+{
+    if (width <= 0 || height <= 0) {
+        *startOffset = 0;
+        *pixelRowSize = 0;
+        *totalRowSize = 0;
+        return;
+    }
+
+    GLESTextureUtils::computePackingOffsets2D(
+            width, height,
+            format, type,
+            m_pixelStore.unpack_alignment,
+            m_pixelStore.unpack_row_length,
+            m_pixelStore.unpack_skip_pixels,
+            m_pixelStore.unpack_skip_rows,
+            bpp,
+            startOffset,
+            pixelRowSize,
+            totalRowSize);
+
+    *skipRows = m_pixelStore.unpack_skip_rows;
+}
+
+void GLClientState::getUnpackingOffsets3D(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* pixelImageSize, int* totalImageSize, int* skipRows, int* skipImages) const
+{
+    if (width <= 0 || height <= 0) {
+        *startOffset = 0;
+        *pixelRowSize = 0;
+        *totalRowSize = 0;
+        return;
+    }
+
+    GLESTextureUtils::computePackingOffsets3D(
+            width, height, depth,
+            format, type,
+            m_pixelStore.unpack_alignment,
+            m_pixelStore.unpack_row_length,
+            m_pixelStore.unpack_image_height,
+            m_pixelStore.unpack_skip_pixels,
+            m_pixelStore.unpack_skip_rows,
+            m_pixelStore.unpack_skip_images,
+            bpp,
+            startOffset,
+            pixelRowSize,
+            totalRowSize,
+            pixelImageSize,
+            totalImageSize);
+
+    *skipRows = m_pixelStore.unpack_skip_rows;
+    *skipImages = m_pixelStore.unpack_skip_images;
+}
+
 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
     UniformBlockInfoKey key;
     key.program = program;
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index 5180338..b7f5655 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -253,7 +253,9 @@
     size_t pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
     size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
     size_t clearBufferNumElts(GLenum buffer) const;
-    void getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
+    void getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
+    void getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
+    void getUnpackingOffsets3D(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* pixelImageSize, int* totalImageSize, int* skipRows, int* skipImages) const;
 
     void setCurrentProgram(GLint program) { m_currentProgram = program; }
     void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.cpp b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
index 297a862..cedcda8 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.cpp
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
@@ -207,7 +207,9 @@
     GLsizei alignedPitch = computePitch(width, format, type, align);
     int packingOffsetRows =
         (skipImages * height + skipRows);
-    return packingOffsetRows * alignedPitch + skipPixels * computePixelSize(format, type);
+    int res = packingOffsetRows * alignedPitch + skipPixels * computePixelSize(format, type);
+
+    return res;
 }
 
 void computeTextureStartEnd(
@@ -295,6 +297,7 @@
         int packRowLength,
         int packSkipPixels,
         int packSkipRows,
+        int* bpp,
         int* startOffset,
         int* packingPixelRowSize,
         int* packingTotalRowSize) {
@@ -307,10 +310,46 @@
         computePackingOffset(
                 format, type, widthTotal, height, packAlignment, packSkipPixels, packSkipRows, 0 /* skip images = 0 */);
 
+    if (bpp) *bpp = computePixelSize(format, type);
     if (startOffset) *startOffset = packingOffsetStart;
     if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
     if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
 }
 
+void computePackingOffsets3D(
+        GLsizei width, GLsizei height, GLsizei depth,
+        GLenum format, GLenum type,
+        int packAlignment,
+        int packRowLength,
+        int packImageHeight,
+        int packSkipPixels,
+        int packSkipRows,
+        int packSkipImages,
+        int* bpp,
+        int* startOffset,
+        int* packingPixelRowSize,
+        int* packingTotalRowSize,
+        int* packingPixelImageSize,
+        int* packingTotalImageSize) {
+
+    int widthTotal = (packRowLength == 0) ? width : packRowLength;
+    int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
+    int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
+
+    int heightTotal = packImageHeight == 0 ? height : packImageHeight;
+    int totalImageSize = totalRowSize * heightTotal;
+    int pixelsOnlyImageSize = totalRowSize * height;
+
+    int packingOffsetStart =
+        computePackingOffset(
+                format, type, widthTotal, heightTotal, packAlignment, packSkipPixels, packSkipRows, packSkipImages);
+
+    if (bpp) *bpp = computePixelSize(format, type);
+    if (startOffset) *startOffset = packingOffsetStart;
+    if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
+    if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
+    if (packingPixelImageSize) *packingPixelImageSize = pixelsOnlyImageSize;
+    if (packingTotalImageSize) *packingTotalImageSize = totalImageSize;
+}
 
 } // namespace GLESTextureUtils
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.h b/shared/OpenglCodecCommon/GLESTextureUtils.h
index f623d23..1d26b3a 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.h
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.h
@@ -49,9 +49,27 @@
         int packRowLength,
         int packSkipPixels,
         int packSkipRows,
+        int* bpp,
         int* startOffset,
         int* packingPixelRowSize,
         int* packingTotalRowSize);
 
+// For processing 3D textures exactly to the sizes of client buffers.
+void computePackingOffsets3D(
+        GLsizei width, GLsizei height, GLsizei depth,
+        GLenum format, GLenum type,
+        int packAlignment,
+        int packRowLength,
+        int packImageHeight,
+        int packSkipPixels,
+        int packSkipRows,
+        int packSkipImages,
+        int* bpp,
+        int* startOffset,
+        int* packingPixelRowSize,
+        int* packingTotalRowSize,
+        int* packingPixelImageSize,
+        int* packingTotalImageSize);
+
 } // namespace GLESTextureUtils
 #endif
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.cpp b/shared/OpenglCodecCommon/GLSharedGroup.cpp
index 46d94a9..5273e4c 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -25,11 +25,13 @@
 BufferData::BufferData(GLsizeiptr size, const void* data) :
     m_size(size), m_usage(0), m_mapped(false) {
 
-    void * buffer = NULL;
+    if (size > 0) {
+        m_fixedBuffer.resize(size);
+    }
 
-    if (size>0) buffer = m_fixedBuffer.alloc(size);
-
-    if (data) memcpy(buffer, data, size);
+    if (data) {
+        memcpy(m_fixedBuffer.data(), data, size);
+    }
 }
 
 /**** ProgramData ****/
@@ -271,7 +273,7 @@
         return GL_INVALID_VALUE;
     }
 
-    memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
+    memcpy(&buf->m_fixedBuffer[offset], data, size);
 
     buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
     return GL_NO_ERROR;
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.h b/shared/OpenglCodecCommon/GLSharedGroup.h
index d471795..bbee27a 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -37,7 +37,6 @@
 #include <stdlib.h>
 #include "ErrorLog.h"
 #include <utils/threads.h>
-#include "FixedBuffer.h"
 #include "auto_goldfish_dma_context.h"
 #include "IndexRangeCache.h"
 #include "SmartPtr.h"
@@ -58,7 +57,7 @@
     uint64_t m_guest_paddr;
 
     // Internal bookkeeping
-    FixedBuffer m_fixedBuffer; // actual buffer is shadowed here
+    std::vector<char> m_fixedBuffer; // actual buffer is shadowed here
     IndexRangeCache m_indexRangeCache;
 
     // DMA support
diff --git a/shared/OpenglCodecCommon/auto_goldfish_dma_context.cpp b/shared/OpenglCodecCommon/auto_goldfish_dma_context.cpp
index 280262d..c638c2b 100644
--- a/shared/OpenglCodecCommon/auto_goldfish_dma_context.cpp
+++ b/shared/OpenglCodecCommon/auto_goldfish_dma_context.cpp
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
 
 #include "auto_goldfish_dma_context.h"
 
diff --git a/shared/OpenglCodecCommon/auto_goldfish_dma_context.h b/shared/OpenglCodecCommon/auto_goldfish_dma_context.h
index 7d97fc2..c8ee738 100644
--- a/shared/OpenglCodecCommon/auto_goldfish_dma_context.h
+++ b/shared/OpenglCodecCommon/auto_goldfish_dma_context.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
 
 #ifndef ANDROID_INCLUDE_HARDWARE_AUTO_GOLDFISH_DMA_CONTEXT_H
 #define ANDROID_INCLUDE_HARDWARE_AUTO_GOLDFISH_DMA_CONTEXT_H
diff --git a/shared/OpenglCodecCommon/glUtils.cpp b/shared/OpenglCodecCommon/glUtils.cpp
index 58ca392..a0ec240 100644
--- a/shared/OpenglCodecCommon/glUtils.cpp
+++ b/shared/OpenglCodecCommon/glUtils.cpp
@@ -417,8 +417,7 @@
         s = 16;
     break;
     default:
-        ERR("glUtilsParamSize: unknow param 0x%08x\n", param);
-        s = 1; // assume 1
+        s = 1; // assume 1 for everything else
     }
     return s;
 }
diff --git a/shared/OpenglCodecCommon/goldfish_dma.cpp b/shared/OpenglCodecCommon/goldfish_dma.cpp
index dbb1f8d..f3cefec 100644
--- a/shared/OpenglCodecCommon/goldfish_dma.cpp
+++ b/shared/OpenglCodecCommon/goldfish_dma.cpp
@@ -1,19 +1,20 @@
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
 
 #include "goldfish_dma.h"
-#include "qemu_pipe.h"
+
+#include <qemu_pipe_bp.h>
 
 #if PLATFORM_SDK_VERSION < 26
 #include <cutils/log.h>
@@ -32,6 +33,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 /* There is an ioctl associated with goldfish dma driver.
  * Make it conflict with ioctls that are not likely to be used
diff --git a/shared/OpenglCodecCommon/goldfish_dma.h b/shared/OpenglCodecCommon/goldfish_dma.h
index ee3df59..278e035 100644
--- a/shared/OpenglCodecCommon/goldfish_dma.h
+++ b/shared/OpenglCodecCommon/goldfish_dma.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
 
 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
diff --git a/shared/OpenglCodecCommon/qemu_pipe.h b/shared/OpenglCodecCommon/qemu_pipe.h
deleted file mode 100644
index 55ebb74..0000000
--- a/shared/OpenglCodecCommon/qemu_pipe.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.
- */
-#ifndef ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
-#define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <errno.h>
-
-#ifdef HOST_BUILD
-
-#ifndef QEMU_PIPE_RETRY
-#define QEMU_PIPE_RETRY TEMP_FAILURE_RETRY
-#endif
-
-typedef void* QEMU_PIPE_HANDLE;
-
-#define QEMU_PIPE_INVALID_HANDLE NULL
-
-QEMU_PIPE_HANDLE qemu_pipe_open(const char* pipeName);
-void qemu_pipe_close(QEMU_PIPE_HANDLE pipe);
-
-ssize_t qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, size_t len);
-ssize_t qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, size_t len);
-
-bool qemu_pipe_try_again();
-bool qemu_pipe_valid(QEMU_PIPE_HANDLE pipe);
-
-void qemu_pipe_print_error(QEMU_PIPE_HANDLE pipe);
-
-#else
-
-typedef int QEMU_PIPE_HANDLE;
-
-#define QEMU_PIPE_INVALID_HANDLE (-1)
-
-#ifndef QEMU_PIPE_RETRY
-#define QEMU_PIPE_RETRY(exp) ({ \
-    __typeof__(exp) _rc; \
-    do { \
-        _rc = (exp); \
-    } while (_rc == -1 && (errno == EINTR || errno == EAGAIN)); \
-    _rc; }) \
-
-#endif
-
-#ifndef QEMU_PIPE_PATH
-#define QEMU_PIPE_PATH "/dev/qemu_pipe"
-#endif
-
-#if PLATFORM_SDK_VERSION < 26
-#include <cutils/log.h>
-#else
-#include <log/log.h>
-#endif
-#ifdef __ANDROID__
-#include <sys/cdefs.h>
-#endif
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <pthread.h>  /* for pthread_once() */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef D
-#  define  D(...)   do{}while(0)
-#endif
-
-/* Try to open a new Qemu fast-pipe. This function returns a file descriptor
- * that can be used to communicate with a named service managed by the
- * emulator.
- *
- * This file descriptor can be used as a standard pipe/socket descriptor.
- *
- * 'pipeName' is the name of the emulator service you want to connect to.
- * E.g. 'opengles' or 'camera'.
- *
- * On success, return a valid file descriptor
- * Returns -1 on error, and errno gives the error code, e.g.:
- *
- *    EINVAL  -> unknown/unsupported pipeName
- *    ENOSYS  -> fast pipes not available in this system.
- *
- * ENOSYS should never happen, except if you're trying to run within a
- * misconfigured emulator.
- *
- * You should be able to open several pipes to the same pipe service,
- * except for a few special cases (e.g. GSM modem), where EBUSY will be
- * returned if more than one client tries to connect to it.
- */
-
-static __inline__ ssize_t
-qemu_pipe_write_fully(QEMU_PIPE_HANDLE pipe, const void* buffer, ssize_t len);
-
-static __inline__ QEMU_PIPE_HANDLE
-qemu_pipe_open_ns(const char* ns, const char* pipeName, int flags) {
-    char  buff[256];
-    int   buffLen;
-    QEMU_PIPE_HANDLE   fd;
-
-    if (pipeName == NULL || pipeName[0] == '\0') {
-        errno = EINVAL;
-        return -1;
-    }
-
-    if (ns) {
-        buffLen = snprintf(buff, sizeof(buff), "pipe:%s:%s", ns, pipeName);
-    } else {
-        buffLen = snprintf(buff, sizeof(buff), "pipe:%s", pipeName);
-    }
-
-    fd = QEMU_PIPE_RETRY(open(QEMU_PIPE_PATH, flags));
-    if (fd < 0 && errno == ENOENT) {
-        fd = QEMU_PIPE_RETRY(open("/dev/goldfish_pipe", flags));
-    }
-    if (fd < 0) {
-        D("%s: Could not open " QEMU_PIPE_PATH ": %s", __FUNCTION__, strerror(errno));
-        //errno = ENOSYS;
-        return -1;
-    }
-
-    if (qemu_pipe_write_fully(fd, buff, buffLen + 1)) {
-        D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno));
-        return -1;
-    }
-
-    return fd;
-}
-
-static __inline__ QEMU_PIPE_HANDLE
-qemu_pipe_open(const char* pipeName) {
-    return qemu_pipe_open_ns(NULL, pipeName, O_RDWR | O_NONBLOCK);
-}
-
-static __inline__ void
-qemu_pipe_close(QEMU_PIPE_HANDLE pipe) {
-    close(pipe);
-}
-
-static __inline__ ssize_t
-qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, size_t len) {
-    return read(pipe, buffer, len);
-}
-
-static __inline__ ssize_t
-qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, size_t len) {
-    return write(pipe, buffer, len);
-}
-
-static __inline__ bool
-qemu_pipe_try_again() {
-    return errno == EINTR || errno == EAGAIN;
-}
-
-static __inline__ bool
-qemu_pipe_valid(QEMU_PIPE_HANDLE pipe) {
-    return pipe >= 0;
-}
-
-static __inline__ void
-qemu_pipe_print_error(QEMU_PIPE_HANDLE pipe) {
-    ALOGE("pipe error: fd %d errno %d", pipe, errno);
-}
-
-
-#endif // !HOST_BUILD
-
-#ifndef TEMP_FAILURE_RETRY
-#define TEMP_FAILURE_RETRY(exp) ({         \
-    __typeof__(exp) _rc;                   \
-    do {                                   \
-        _rc = (exp);                       \
-    } while (_rc == -1 && errno == EINTR); \
-    _rc; })
-#endif
-
-static __inline__ ssize_t
-qemu_pipe_read_fully(QEMU_PIPE_HANDLE pipe, void* buffer, ssize_t len) {
-    char* p = (char*)buffer;
-
-    while (len > 0) {
-      ssize_t n = QEMU_PIPE_RETRY(qemu_pipe_read(pipe, p, len));
-      if (n < 0) return n;
-
-      p += n;
-      len -= n;
-    }
-
-    return 0;
-}
-
-static __inline__ ssize_t
-qemu_pipe_write_fully(QEMU_PIPE_HANDLE pipe, const void* buffer, ssize_t len) {
-    const char* p = (const char*)buffer;
-
-    while (len > 0) {
-      ssize_t n = QEMU_PIPE_RETRY(qemu_pipe_write(pipe, p, len));
-      if (n < 0) return n;
-
-      p += n;
-      len -= n;
-    }
-
-    return 0;
-}
-
-#endif /* ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H */
diff --git a/shared/gralloc_cb/Android.bp b/shared/gralloc_cb/Android.bp
new file mode 100644
index 0000000..faea798
--- /dev/null
+++ b/shared/gralloc_cb/Android.bp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+cc_library_headers {
+    name: "libgralloc_cb.ranchu",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+    header_libs: [
+        "libcutils_headers",
+        "libqemupipe-types.ranchu",
+    ],
+    export_header_lib_headers: [
+        "libcutils_headers",
+        "libqemupipe-types.ranchu"
+    ],
+}
diff --git a/shared/gralloc_cb/Android.mk b/shared/gralloc_cb/Android.mk
new file mode 100644
index 0000000..9c1f038
--- /dev/null
+++ b/shared/gralloc_cb/Android.mk
@@ -0,0 +1,10 @@
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+
+LOCAL_PATH := $(call my-dir)
+
+$(call emugl-begin-static-library,libgralloc_cb$(GOLDFISH_OPENGL_LIB_SUFFIX))
+LOCAL_SRC_FILES := empty.cpp
+$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include)
+$(call emugl-end-module)
+
+endif
diff --git a/shared/gralloc_cb/CMakeLists.txt b/shared/gralloc_cb/CMakeLists.txt
new file mode 100644
index 0000000..f9e7b71
--- /dev/null
+++ b/shared/gralloc_cb/CMakeLists.txt
@@ -0,0 +1,10 @@
+# This is an autogenerated file! Do not edit!
+# instead run make from .../device/generic/goldfish-opengl
+# which will re-generate this file.
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/Android.mk" "8d9adf5ce35036abff985952ba984a3fcefcc2156ff36facfe51ba7d7adaab9d")
+set(gralloc_cb_host_src empty.cpp)
+android_add_library(TARGET gralloc_cb_host LICENSE Apache-2.0 SRC empty.cpp)
+target_include_directories(gralloc_cb_host PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_compile_definitions(gralloc_cb_host PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN")
+target_compile_options(gralloc_cb_host PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
+target_link_libraries(gralloc_cb_host PRIVATE android-emu-shared)
\ No newline at end of file
diff --git a/shared/gralloc_cb/empty.cpp b/shared/gralloc_cb/empty.cpp
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/shared/gralloc_cb/empty.cpp
@@ -0,0 +1 @@
+/* empty */
diff --git a/shared/OpenglCodecCommon/gralloc_cb.h b/shared/gralloc_cb/include/gralloc_cb_bp.h
similarity index 98%
rename from shared/OpenglCodecCommon/gralloc_cb.h
rename to shared/gralloc_cb/include/gralloc_cb_bp.h
index 26d6026..259ed85 100644
--- a/shared/OpenglCodecCommon/gralloc_cb.h
+++ b/shared/gralloc_cb/include/gralloc_cb_bp.h
@@ -18,7 +18,7 @@
 #define __GRALLOC_CB_H__
 
 #include <cutils/native_handle.h>
-#include "qemu_pipe.h"
+#include <qemu_pipe_types_bp.h>
 
 const uint32_t CB_HANDLE_MAGIC_MASK = 0xFFFFFFF0;
 const uint32_t CB_HANDLE_MAGIC_BASE = 0xABFABFA0;
diff --git a/shared/qemupipe/Android.bp b/shared/qemupipe/Android.bp
new file mode 100644
index 0000000..fe72943
--- /dev/null
+++ b/shared/qemupipe/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+cc_library_headers {
+    name: "libqemupipe-types.ranchu",
+    vendor_available: true,
+    export_include_dirs: ["include-types"],
+}
+
+cc_library {
+    name: "libqemupipe.ranchu",
+    vendor_available: true,
+    srcs: [
+        "qemu_pipe_common.cpp",
+        "qemu_pipe_guest.cpp",
+    ],
+    header_libs: ["libqemupipe-types.ranchu"],
+    export_header_lib_headers: ["libqemupipe-types.ranchu"],
+    shared_libs: ["liblog"],
+    export_include_dirs: ["include"],
+}
diff --git a/shared/qemupipe/Android.mk b/shared/qemupipe/Android.mk
new file mode 100644
index 0000000..f665982
--- /dev/null
+++ b/shared/qemupipe/Android.mk
@@ -0,0 +1,16 @@
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+
+LOCAL_PATH := $(call my-dir)
+
+$(call emugl-begin-static-library,libqemupipe$(GOLDFISH_OPENGL_LIB_SUFFIX))
+
+LOCAL_SRC_FILES := \
+    qemu_pipe_common.cpp \
+    qemu_pipe_host.cpp
+
+$(call emugl-export,SHARED_LIBRARIES,android-emu-shared)
+$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include-types)
+$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/include)
+$(call emugl-end-module)
+
+endif
diff --git a/shared/qemupipe/CMakeLists.txt b/shared/qemupipe/CMakeLists.txt
new file mode 100644
index 0000000..2229681
--- /dev/null
+++ b/shared/qemupipe/CMakeLists.txt
@@ -0,0 +1,10 @@
+# This is an autogenerated file! Do not edit!
+# instead run make from .../device/generic/goldfish-opengl
+# which will re-generate this file.
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/Android.mk" "8554a162304f69cc357d5e35cf614ca278135bf4cea3431da69a08b9af234777")
+set(qemupipe_host_src qemu_pipe_common.cpp qemu_pipe_host.cpp)
+android_add_library(TARGET qemupipe_host LICENSE Apache-2.0 SRC qemu_pipe_common.cpp qemu_pipe_host.cpp)
+target_include_directories(qemupipe_host PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_compile_definitions(qemupipe_host PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN")
+target_compile_options(qemupipe_host PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
+target_link_libraries(qemupipe_host PRIVATE android-emu-shared)
\ No newline at end of file
diff --git a/shared/qemupipe/include-types/qemu_pipe_types_bp.h b/shared/qemupipe/include-types/qemu_pipe_types_bp.h
new file mode 100644
index 0000000..d786fe5
--- /dev/null
+++ b/shared/qemupipe/include-types/qemu_pipe_types_bp.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 <stddef.h>
+#include <stdbool.h>
+
+#ifdef HOST_BUILD
+
+typedef void* QEMU_PIPE_HANDLE;
+#define QEMU_PIPE_INVALID_HANDLE NULL
+
+inline bool qemu_pipe_valid(QEMU_PIPE_HANDLE h) {
+    return h != QEMU_PIPE_INVALID_HANDLE;
+}
+
+#else  // ifdef HOST_BUILD
+
+typedef int QEMU_PIPE_HANDLE;
+#define QEMU_PIPE_INVALID_HANDLE (-1)
+
+inline bool qemu_pipe_valid(QEMU_PIPE_HANDLE h) {
+    return h > QEMU_PIPE_INVALID_HANDLE;
+}
+
+#endif // ifdef HOST_BUILD
diff --git a/shared/qemupipe/include/qemu_pipe_bp.h b/shared/qemupipe/include/qemu_pipe_bp.h
new file mode 100644
index 0000000..4338ee5
--- /dev/null
+++ b/shared/qemupipe/include/qemu_pipe_bp.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 <qemu_pipe_types_bp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+QEMU_PIPE_HANDLE qemu_pipe_open_ns(const char* ns, const char* pipeName, int flags);
+QEMU_PIPE_HANDLE qemu_pipe_open(const char* pipeName);
+void qemu_pipe_close(QEMU_PIPE_HANDLE pipe);
+
+int qemu_pipe_read_fully(QEMU_PIPE_HANDLE pipe, void* buffer, int size);
+int qemu_pipe_write_fully(QEMU_PIPE_HANDLE pipe, const void* buffer, int size);
+int qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, int size);
+int qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, int size);
+
+int qemu_pipe_try_again(int ret);
+void qemu_pipe_print_error(QEMU_PIPE_HANDLE pipe);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#define QEMU_PIPE_RETRY(exp) ({ \
+    __typeof__(exp) _rc; \
+    do { \
+        _rc = (exp); \
+    } while (qemu_pipe_try_again(_rc)); \
+    _rc; })
diff --git a/shared/qemupipe/qemu_pipe_common.cpp b/shared/qemupipe/qemu_pipe_common.cpp
new file mode 100644
index 0000000..859bd3f
--- /dev/null
+++ b/shared/qemupipe/qemu_pipe_common.cpp
@@ -0,0 +1,43 @@
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
+
+#include <qemu_pipe_bp.h>
+
+int qemu_pipe_read_fully(QEMU_PIPE_HANDLE pipe, void* buffer, int size) {
+    char* p = (char*)buffer;
+
+    while (size > 0) {
+      int n = QEMU_PIPE_RETRY(qemu_pipe_read(pipe, p, size));
+      if (n < 0) return n;
+
+      p += n;
+      size -= n;
+    }
+
+    return 0;
+}
+
+int qemu_pipe_write_fully(QEMU_PIPE_HANDLE pipe, const void* buffer, int size) {
+    const char* p = (const char*)buffer;
+
+    while (size > 0) {
+      int n = QEMU_PIPE_RETRY(qemu_pipe_write(pipe, p, size));
+      if (n < 0) return n;
+
+      p += n;
+      size -= n;
+    }
+
+    return 0;
+}
diff --git a/shared/qemupipe/qemu_pipe_guest.cpp b/shared/qemupipe/qemu_pipe_guest.cpp
new file mode 100644
index 0000000..1732a51
--- /dev/null
+++ b/shared/qemupipe/qemu_pipe_guest.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#include <errno.h>
+#include <log/log.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <qemu_pipe_bp.h>
+
+namespace {
+int open_verbose(const char* name, int flags) {
+    const int fd = QEMU_PIPE_RETRY(open(name, flags));
+    if (fd < 0) {
+        ALOGE("%s:%d: Could not open '%s': %s",
+              __func__, __LINE__, name, strerror(errno));
+    }
+    return fd;
+}
+
+}  // namespace
+
+extern "C" {
+
+int qemu_pipe_open_ns(const char* ns, const char* pipeName, int flags) {
+    if (pipeName == NULL || pipeName[0] == '\0') {
+        errno = EINVAL;
+        return -1;
+    }
+
+    const int fd = open_verbose("/dev/goldfish_pipe", flags);
+    if (fd < 0) {
+        return fd;
+    }
+
+    char buf[256];
+    int bufLen;
+    if (ns) {
+        bufLen = snprintf(buf, sizeof(buf), "pipe:%s:%s", ns, pipeName);
+    } else {
+        bufLen = snprintf(buf, sizeof(buf), "pipe:%s", pipeName);
+    }
+
+    if (qemu_pipe_write_fully(fd, buf, bufLen + 1)) {
+        ALOGE("%s:%d: Could not connect to the '%s' service: %s",
+              __func__, __LINE__, buf, strerror(errno));
+        return -1;
+    }
+
+    return fd;
+}
+
+int qemu_pipe_open(const char* pipeName) {
+    return qemu_pipe_open_ns(NULL, pipeName, O_RDWR | O_NONBLOCK);
+}
+
+void qemu_pipe_close(int pipe) {
+    close(pipe);
+}
+
+int qemu_pipe_read(int pipe, void* buffer, int size) {
+    return read(pipe, buffer, size);
+}
+
+int qemu_pipe_write(int pipe, const void* buffer, int size) {
+    return write(pipe, buffer, size);
+}
+
+int qemu_pipe_try_again(int ret) {
+    return (ret < 0) && (errno == EINTR || errno == EAGAIN);
+}
+
+void qemu_pipe_print_error(int pipe) {
+    ALOGE("pipe error: fd %d errno %d", pipe, errno);
+}
+
+}  // extern "C"
diff --git a/shared/OpenglCodecCommon/qemu_pipe_host.cpp b/shared/qemupipe/qemu_pipe_host.cpp
similarity index 77%
rename from shared/OpenglCodecCommon/qemu_pipe_host.cpp
rename to shared/qemupipe/qemu_pipe_host.cpp
index c53a8eb..38f2f63 100644
--- a/shared/OpenglCodecCommon/qemu_pipe_host.cpp
+++ b/shared/qemupipe/qemu_pipe_host.cpp
@@ -11,7 +11,8 @@
 // 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.
-#include "qemu_pipe.h"
+
+#include <qemu_pipe_bp.h>
 
 #include "android/emulation/hostdevices/HostGoldfishPipe.h"
 
@@ -33,21 +34,21 @@
     HostGoldfishPipeDevice::get()->close(pipe);
 }
 
-ssize_t qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, size_t len) {
+int qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, int len) {
     return HostGoldfishPipeDevice::get()->read(pipe, buffer, len);
 }
 
-ssize_t qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, size_t len) {
+int qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, int len) {
     return HostGoldfishPipeDevice::get()->write(pipe, buffer, len);
 }
 
-bool qemu_pipe_try_again() {
-    int err = HostGoldfishPipeDevice::get()->getErrno();
-    return err == EINTR || err == EAGAIN;
-}
-
-bool qemu_pipe_valid(QEMU_PIPE_HANDLE pipe) {
-    return pipe != NULL;
+int qemu_pipe_try_again(int ret) {
+    if (ret < 0) {
+        int err = HostGoldfishPipeDevice::get()->getErrno();
+        return err == EINTR || err == EAGAIN;
+    } else {
+        return false;
+    }
 }
 
 void qemu_pipe_print_error(QEMU_PIPE_HANDLE pipe) {
diff --git a/system/GLESv1/CMakeLists.txt b/system/GLESv1/CMakeLists.txt
index a8dc669..5436e5f 100644
--- a/system/GLESv1/CMakeLists.txt
+++ b/system/GLESv1/CMakeLists.txt
@@ -4,7 +4,7 @@
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/GLESv1/Android.mk" "e095cb082e3791719749cfc80b90560afd7348eb0d7895449d2509aa129bea75")
 set(GLESv1_CM_emulation_src gl.cpp)
 android_add_library(TARGET GLESv1_CM_emulation SHARED LICENSE Apache-2.0 SRC gl.cpp)
-target_include_directories(GLESv1_CM_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(GLESv1_CM_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(GLESv1_CM_emulation PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"GLES_emulation\"")
 target_compile_options(GLESv1_CM_emulation PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
-target_link_libraries(GLESv1_CM_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(GLESv1_CM_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/GLESv1_enc/CMakeLists.txt b/system/GLESv1_enc/CMakeLists.txt
index 8acc4ff..0a9bc52 100644
--- a/system/GLESv1_enc/CMakeLists.txt
+++ b/system/GLESv1_enc/CMakeLists.txt
@@ -4,7 +4,7 @@
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc/Android.mk" "953e6b7371d10eed63a4be555f8f1fb6f347338484a78102fa8f55dff96f5d3b")
 set(GLESv1_enc_src GLEncoder.cpp GLEncoderUtils.cpp gl_client_context.cpp gl_enc.cpp gl_entry.cpp)
 android_add_library(TARGET GLESv1_enc SHARED LICENSE Apache-2.0 SRC GLEncoder.cpp GLEncoderUtils.cpp gl_client_context.cpp gl_enc.cpp gl_entry.cpp)
-target_include_directories(GLESv1_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(GLESv1_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(GLESv1_enc PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"emuglGLESv1_enc\"")
 target_compile_options(GLESv1_enc PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
-target_link_libraries(GLESv1_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared)
\ No newline at end of file
+target_link_libraries(GLESv1_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared PRIVATE qemupipe_host)
\ No newline at end of file
diff --git a/system/GLESv1_enc/GLEncoder.cpp b/system/GLESv1_enc/GLEncoder.cpp
index 1fa0dac..20f2c02 100644
--- a/system/GLESv1_enc/GLEncoder.cpp
+++ b/system/GLESv1_enc/GLEncoder.cpp
@@ -15,15 +15,9 @@
 */
 #include "GLEncoder.h"
 #include "glUtils.h"
-#include "FixedBuffer.h"
-
-#if PLATFORM_SDK_VERSION < 26
-#include <cutils/log.h>
-#else
 #include <log/log.h>
-#endif
-
 #include <assert.h>
+#include <vector>
 
 #ifndef MIN
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -584,7 +578,7 @@
         } else {
             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
-            indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
+            indices = &buf->m_fixedBuffer[(GLintptr)indices];
         }
     }
     if (adjustIndices) {
@@ -596,7 +590,8 @@
         case GL_UNSIGNED_BYTE:
             GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
             if (minIndex != 0) {
-                adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
+                ctx->m_fixedBuffer.resize(glSizeof(type) * count);
+                adjustedIndices = ctx->m_fixedBuffer.data();
                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
                                                  (unsigned char *)adjustedIndices,
                                                  count, -minIndex);
@@ -606,7 +601,8 @@
         case GL_UNSIGNED_SHORT:
             GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
             if (minIndex != 0) {
-                adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
+                ctx->m_fixedBuffer.resize(glSizeof(type) * count);
+                adjustedIndices = ctx->m_fixedBuffer.data();
                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
                                                  (unsigned short *)adjustedIndices,
                                                  count, -minIndex);
@@ -616,7 +612,8 @@
         case GL_UNSIGNED_INT:
             GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
             if (minIndex != 0) {
-                adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
+                ctx->m_fixedBuffer.resize(glSizeof(type) * count);
+                adjustedIndices = ctx->m_fixedBuffer.data();
                 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
                                                  (unsigned int *)adjustedIndices,
                                                  count, -minIndex);
diff --git a/system/GLESv1_enc/GLEncoder.h b/system/GLESv1_enc/GLEncoder.h
index 95537a2..a26636c 100644
--- a/system/GLESv1_enc/GLEncoder.h
+++ b/system/GLESv1_enc/GLEncoder.h
@@ -16,10 +16,11 @@
 #ifndef _GL_ENCODER_H_
 #define _GL_ENCODER_H_
 
+#include <vector>
+
 #include "gl_enc.h"
 #include "GLClientState.h"
 #include "GLSharedGroup.h"
-#include "FixedBuffer.h"
 #include "ChecksumCalculator.h"
 
 class GLEncoder : public gl_encoder_context_t {
@@ -53,7 +54,7 @@
     GLClientState *m_state;
     GLSharedGroupPtr m_shared;
     GLenum  m_error;
-    FixedBuffer m_fixedBuffer;
+    std::vector<char> m_fixedBuffer;
     GLint *m_compressedTextureFormats;
     GLint m_num_compressedTextureFormats;
 
diff --git a/system/GLESv2/CMakeLists.txt b/system/GLESv2/CMakeLists.txt
index e2f5f4e..d90502a 100644
--- a/system/GLESv2/CMakeLists.txt
+++ b/system/GLESv2/CMakeLists.txt
@@ -4,7 +4,7 @@
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/GLESv2/Android.mk" "d8f9dda69ec57ad8b7a65f02c3335b16a4724f612dec1d1a2cd793c28c0a10f9")
 set(GLESv2_emulation_src gl2.cpp)
 android_add_library(TARGET GLESv2_emulation SHARED LICENSE Apache-2.0 SRC gl2.cpp)
-target_include_directories(GLESv2_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(GLESv2_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(GLESv2_emulation PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"GLESv2_emulation\"")
 target_compile_options(GLESv2_emulation PRIVATE "-fvisibility=default" "-Wno-unused-parameter")
-target_link_libraries(GLESv2_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(GLESv2_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/GLESv2_enc/Android.mk b/system/GLESv2_enc/Android.mk
index af95736..40acfc5 100644
--- a/system/GLESv2_enc/Android.mk
+++ b/system/GLESv2_enc/Android.mk
@@ -10,7 +10,7 @@
     gl2_client_context.cpp \
     gl2_enc.cpp \
     gl2_entry.cpp \
-    ../enc_common/IOStream_common.cpp \
+    IOStream2.cpp \
 
 LOCAL_CFLAGS += -DLOG_TAG=\"emuglGLESv2_enc\"
 LOCAL_CFLAGS += -Wno-unused-private-field
diff --git a/system/GLESv2_enc/CMakeLists.txt b/system/GLESv2_enc/CMakeLists.txt
index 72afa76..39a479f 100644
--- a/system/GLESv2_enc/CMakeLists.txt
+++ b/system/GLESv2_enc/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc/Android.mk" "d4fc971ccdbafbf971253b27bbc2168682b2994476079f4f81fb7a33c27070e0")
-set(GLESv2_enc_src GL2EncoderUtils.cpp GL2Encoder.cpp GLESv2Validation.cpp gl2_client_context.cpp gl2_enc.cpp gl2_entry.cpp ../enc_common/IOStream_common.cpp)
-android_add_library(TARGET GLESv2_enc SHARED LICENSE Apache-2.0 SRC GL2EncoderUtils.cpp GL2Encoder.cpp GLESv2Validation.cpp gl2_client_context.cpp gl2_enc.cpp gl2_entry.cpp ../enc_common/IOStream_common.cpp)
-target_include_directories(GLESv2_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc/Android.mk" "df543672d1f36e43fb783b08200aa85dbf3a2e7167f8ecd7e4c01c80e6fd1650")
+set(GLESv2_enc_src GL2EncoderUtils.cpp GL2Encoder.cpp GLESv2Validation.cpp gl2_client_context.cpp gl2_enc.cpp gl2_entry.cpp IOStream2.cpp)
+android_add_library(TARGET GLESv2_enc SHARED LICENSE Apache-2.0 SRC GL2EncoderUtils.cpp GL2Encoder.cpp GLESv2Validation.cpp gl2_client_context.cpp gl2_enc.cpp gl2_entry.cpp IOStream2.cpp)
+target_include_directories(GLESv2_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(GLESv2_enc PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"emuglGLESv2_enc\"")
 target_compile_options(GLESv2_enc PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-unused-private-field")
-target_link_libraries(GLESv2_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared)
\ No newline at end of file
+target_link_libraries(GLESv2_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared PRIVATE qemupipe_host)
\ No newline at end of file
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index cc009a9..bafd1b6 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -372,6 +372,9 @@
     OVERRIDE_CUSTOM(glReadnPixelsEXT);
     OVERRIDE_CUSTOM(glGetnUniformfvEXT);
     OVERRIDE_CUSTOM(glGetnUniformivEXT);
+
+    OVERRIDE(glInvalidateFramebuffer);
+    OVERRIDE(glInvalidateSubFramebuffer);
 }
 
 GL2Encoder::~GL2Encoder()
@@ -1119,7 +1122,8 @@
     void* adjustedIndices = (void*)src;
 
     if (minIndex != 0) {
-        adjustedIndices = m_fixedBuffer.alloc(glSizeof(type) * count);
+        m_fixedBuffer.resize(glSizeof(type) * count);
+        adjustedIndices = m_fixedBuffer.data();
         switch(type) {
         case GL_BYTE:
         case GL_UNSIGNED_BYTE:
@@ -1371,7 +1375,7 @@
     if (ctx->m_state->currentIndexVbo() != 0) {
         buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
         offset = (GLintptr)indices;
-        indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
+        indices = &buf->m_fixedBuffer[offset];
         ctx->getBufferIndexRange(buf,
                                  indices,
                                  type,
@@ -1486,7 +1490,7 @@
         } else {
             buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
             offset = (GLintptr)indices;
-            indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
+            indices = &buf->m_fixedBuffer[offset];
             ctx->getBufferIndexRange(buf,
                                      indices,
                                      type,
@@ -1901,7 +1905,10 @@
                 break;
             }
         }
-        memcpy(source, returned.substr(0, bufsize - 1).c_str(), bufsize);
+        std::string ret = returned.substr(0, bufsize - 1);
+
+        size_t toCopy = bufsize < (ret.size() + 1) ? bufsize : ret.size() + 1;
+        memcpy(source, ret.c_str(), toCopy);
     }
 }
 
@@ -2937,7 +2944,7 @@
 void* GL2Encoder::s_glMapBufferRangeAEMUImpl(GL2Encoder* ctx, GLenum target,
                                              GLintptr offset, GLsizeiptr length,
                                              GLbitfield access, BufferData* buf) {
-    char* bits = (char*)buf->m_fixedBuffer.ptr() + offset;
+    char* bits = &buf->m_fixedBuffer[offset];
 
     if ((access & GL_MAP_READ_BIT) ||
         ((access & GL_MAP_WRITE_BIT) &&
@@ -3048,7 +3055,7 @@
     GLboolean host_res = GL_TRUE;
 
     if (buf->dma_buffer.get().mapped_addr) {
-        memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
+        memcpy(&buf->m_fixedBuffer[buf->m_mappedOffset],
                reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr),
                buf->m_mappedLength);
 
@@ -3066,7 +3073,7 @@
                     buf->m_mappedOffset,
                     buf->m_mappedLength,
                     buf->m_mappedAccess,
-                    (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
+                    &buf->m_fixedBuffer[buf->m_mappedOffset],
                     &host_res);
         } else {
             if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
@@ -3075,7 +3082,7 @@
                         buf->m_mappedOffset,
                         buf->m_mappedLength,
                         buf->m_mappedAccess,
-                        (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
+                        &buf->m_fixedBuffer[buf->m_mappedOffset],
                         &host_res);
             }
         }
@@ -3116,14 +3123,14 @@
                 totalOffset,
                 length,
                 buf->m_mappedAccess,
-                (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
+                &buf->m_fixedBuffer[totalOffset]);
     } else {
         ctx->glFlushMappedBufferRangeAEMU(
                 ctx, target,
                 totalOffset,
                 length,
                 buf->m_mappedAccess,
-                (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
+                &buf->m_fixedBuffer[totalOffset]);
     }
 }
 
@@ -3482,7 +3489,7 @@
 
     if (!buf || !buf->m_mapped) { *params = NULL; return; }
 
-    *params = (GLvoid*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset);
+    *params = &buf->m_fixedBuffer[buf->m_mappedOffset];
 }
 
 static const char* const kNameDelimiter = ";";
@@ -4122,6 +4129,7 @@
     assert(ctx->m_state != NULL);
     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
+    SET_ERROR_IF(primcount < 0, GL_INVALID_VALUE);
 
     bool has_client_vertex_arrays = false;
     bool has_indirect_arrays = false;
@@ -4147,6 +4155,7 @@
     assert(ctx->m_state != NULL);
     SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM);
     SET_ERROR_IF(count < 0, GL_INVALID_VALUE);
+    SET_ERROR_IF(primcount < 0, GL_INVALID_VALUE);
     SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM);
     SET_ERROR_IF(ctx->m_state->getTransformFeedbackActiveUnpaused(), GL_INVALID_OPERATION);
 
@@ -4174,7 +4183,7 @@
     if (ctx->m_state->currentIndexVbo() != 0) {
         buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
         offset = (GLintptr)indices;
-        indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
+        indices = &buf->m_fixedBuffer[offset];
         ctx->getBufferIndexRange(buf,
                                  indices,
                                  type,
@@ -4264,13 +4273,13 @@
     // caching previous results.
     if (ctx->m_state->currentIndexVbo() != 0) {
         buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
-        ALOGV("%s: current index vbo: %p len %zu count %zu\n", __func__, buf, (size_t)buf->m_fixedBuffer.len(), (size_t)count);
+        ALOGV("%s: current index vbo: %p len %zu count %zu\n", __func__, buf, buf->m_fixedBuffer.size(), (size_t)count);
         offset = (GLintptr)indices;
         void* oldIndices = (void*)indices;
-        indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
+        indices = &buf->m_fixedBuffer[offset];
         ALOGV("%s: indices arg: %p buffer start: %p indices: %p\n", __func__,
                 (void*)(uintptr_t)(oldIndices),
-                buf->m_fixedBuffer.ptr(),
+                buf->m_fixedBuffer.data(),
                 indices);
         ctx->getBufferIndexRange(buf,
                                  indices,
@@ -5435,3 +5444,17 @@
         location)), GL_INVALID_OPERATION);
     s_glGetUniformiv(self, program, location, params);
 }
+
+void GL2Encoder::s_glInvalidateFramebuffer(void* self, GLenum target, GLsizei numAttachments, const GLenum *attachments) {
+    GL2Encoder *ctx = (GL2Encoder*)self;
+    SET_ERROR_IF(numAttachments < 0, GL_INVALID_VALUE);
+    ctx->m_glInvalidateFramebuffer_enc(ctx, target, numAttachments, attachments);
+}
+
+void GL2Encoder::s_glInvalidateSubFramebuffer(void* self, GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
+    GL2Encoder *ctx = (GL2Encoder*)self;
+    SET_ERROR_IF(numAttachments < 0, GL_INVALID_VALUE);
+    SET_ERROR_IF(width < 0, GL_INVALID_VALUE);
+    SET_ERROR_IF(height < 0, GL_INVALID_VALUE);
+    ctx->m_glInvalidateSubFramebuffer_enc(ctx, target, numAttachments, attachments, x, y, width, height);
+}
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index d016898..0ceb9de 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -16,10 +16,11 @@
 #ifndef _GL2_ENCODER_H_
 #define _GL2_ENCODER_H_
 
+#include <vector>
+
 #include "gl2_enc.h"
 #include "GLClientState.h"
 #include "GLSharedGroup.h"
-#include "FixedBuffer.h"
 
 #include <string>
 #include <vector>
@@ -136,7 +137,7 @@
     GLuint m_ssbo_offset_align;
     GLuint m_ubo_offset_align;
 
-    FixedBuffer m_fixedBuffer;
+    std::vector<char> m_fixedBuffer;
 
     uint32_t m_drawCallFlushInterval;
     uint32_t m_drawCallFlushCount;
@@ -760,6 +761,14 @@
             GLsizei bufSize, GLfloat* params);
     static void s_glGetnUniformivEXT(void *self, GLuint program, GLint location,
             GLsizei bufSize, GLint* params);
+
+    // Invalidate framebuffer
+    static void s_glInvalidateFramebuffer(void* self, GLenum target, GLsizei numAttachments, const GLenum *attachments);
+    static void s_glInvalidateSubFramebuffer(void* self, GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+
+    glInvalidateFramebuffer_client_proc_t m_glInvalidateFramebuffer_enc;
+    glInvalidateSubFramebuffer_client_proc_t m_glInvalidateSubFramebuffer_enc;;
+
 public:
     glEGLImageTargetTexture2DOES_client_proc_t m_glEGLImageTargetTexture2DOES_enc;
 
diff --git a/system/GLESv2_enc/GLESv2Validation.cpp b/system/GLESv2_enc/GLESv2Validation.cpp
index 9f72853..aff7902 100644
--- a/system/GLESv2_enc/GLESv2Validation.cpp
+++ b/system/GLESv2_enc/GLESv2Validation.cpp
@@ -797,6 +797,35 @@
     f(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) \
     f(GL_COMPRESSED_RGBA8_ETC2_EAC) \
     f(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) \
+    f(GL_COMPRESSED_RGBA_ASTC_4x4_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_5x4_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_5x5_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_6x5_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_6x6_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_8x5_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_8x6_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_8x8_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_10x5_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_10x6_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_10x8_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_10x10_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_12x10_KHR) \
+    f(GL_COMPRESSED_RGBA_ASTC_12x12_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) \
+    f(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) \
+
 
 bool pixelInternalFormat(GLenum internalformat) {
 #define VALID_INTERNAL_FORMAT(format) \
diff --git a/system/GLESv2_enc/IOStream2.cpp b/system/GLESv2_enc/IOStream2.cpp
new file mode 100644
index 0000000..4890852
--- /dev/null
+++ b/system/GLESv2_enc/IOStream2.cpp
@@ -0,0 +1,225 @@
+#include "IOStream.h"
+
+#include "GL2Encoder.h"
+
+#include <GLES3/gl31.h>
+
+#include <vector>
+
+#include <assert.h>
+
+void IOStream::readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels) {
+    GL2Encoder *ctx = (GL2Encoder *)context;
+    assert (ctx->state() != NULL);
+
+    int bpp = 0;
+    int startOffset = 0;
+    int pixelRowSize = 0;
+    int totalRowSize = 0;
+    int skipRows = 0;
+
+    ctx->state()->getPackingOffsets2D(width, height, format, type,
+                                      &bpp,
+                                      &startOffset,
+                                      &pixelRowSize,
+                                      &totalRowSize,
+                                      &skipRows);
+
+    size_t pixelDataSize =
+        ctx->state()->pixelDataSize(
+            width, height, 1, format, type, 1 /* is pack */);
+
+    if (startOffset == 0 &&
+        pixelRowSize == totalRowSize) {
+        // fast path
+        readback(pixels, pixelDataSize);
+    } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) {
+        // fast path but with skip in the beginning
+        std::vector<char> paddingToDiscard(startOffset, 0);
+        readback(&paddingToDiscard[0], startOffset);
+        readback((char*)pixels + startOffset, pixelDataSize - startOffset);
+    } else {
+        int totalReadback = 0;
+
+        if (startOffset > 0) {
+            std::vector<char> paddingToDiscard(startOffset, 0);
+            readback(&paddingToDiscard[0], startOffset);
+            totalReadback += startOffset;
+        }
+        // need to read back row by row
+        size_t paddingSize = totalRowSize - pixelRowSize;
+        std::vector<char> paddingToDiscard(paddingSize, 0);
+
+        char* start = (char*)pixels + startOffset;
+
+        for (int i = 0; i < height; i++) {
+            if (pixelRowSize != width * bpp) {
+                size_t rowSlack = pixelRowSize - width * bpp;
+                std::vector<char> rowSlackToDiscard(rowSlack, 0);
+                readback(start, width * bpp);
+                readback(&rowSlackToDiscard[0], rowSlack);
+                totalReadback += pixelRowSize;
+                readback(&paddingToDiscard[0], paddingSize);
+                totalReadback += paddingSize;
+                start += totalRowSize;
+            } else {
+                readback(start, pixelRowSize);
+                totalReadback += pixelRowSize;
+                readback(&paddingToDiscard[0], paddingSize);
+                totalReadback += paddingSize;
+                start += totalRowSize;
+            }
+        }
+    }
+}
+
+void IOStream::uploadPixels(void* context, int width, int height, int depth, unsigned int format, unsigned int type, const void* pixels) {
+    GL2Encoder *ctx = (GL2Encoder *)context;
+    assert (ctx->state() != NULL);
+
+    if (1 == depth) {
+        int bpp = 0;
+        int startOffset = 0;
+        int pixelRowSize = 0;
+        int totalRowSize = 0;
+        int skipRows = 0;
+
+        ctx->state()->getUnpackingOffsets2D(width, height, format, type,
+                &bpp,
+                &startOffset,
+                &pixelRowSize,
+                &totalRowSize,
+                &skipRows);
+
+        size_t pixelDataSize =
+            ctx->state()->pixelDataSize(
+                    width, height, 1, format, type, 0 /* is unpack */);
+
+        if (startOffset == 0 &&
+                pixelRowSize == totalRowSize) {
+            // fast path
+            writeFully(pixels, pixelDataSize);
+        } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) {
+            // fast path but with skip in the beginning
+            std::vector<char> paddingToDiscard(startOffset, 0);
+            writeFully(&paddingToDiscard[0], startOffset);
+            writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
+        } else {
+            int totalReadback = 0;
+
+            if (startOffset > 0) {
+                std::vector<char> paddingToDiscard(startOffset, 0);
+                writeFully(&paddingToDiscard[0], startOffset);
+                totalReadback += startOffset;
+            }
+            // need to upload row by row
+            size_t paddingSize = totalRowSize - pixelRowSize;
+            std::vector<char> paddingToDiscard(paddingSize, 0);
+
+            char* start = (char*)pixels + startOffset;
+
+            for (int i = 0; i < height; i++) {
+                if (pixelRowSize != width * bpp) {
+                    size_t rowSlack = pixelRowSize - width * bpp;
+                    std::vector<char> rowSlackToDiscard(rowSlack, 0);
+                    writeFully(start, width * bpp);
+                    writeFully(&rowSlackToDiscard[0], rowSlack);
+                    totalReadback += pixelRowSize;
+                    writeFully(&paddingToDiscard[0], paddingSize);
+                    totalReadback += paddingSize;
+                    start += totalRowSize;
+                } else {
+                    writeFully(start, pixelRowSize);
+                    totalReadback += pixelRowSize;
+                    writeFully(&paddingToDiscard[0], paddingSize);
+                    totalReadback += paddingSize;
+                    start += totalRowSize;
+                }
+            }
+        }
+    } else {
+        int bpp = 0;
+        int startOffset = 0;
+        int pixelRowSize = 0;
+        int totalRowSize = 0;
+        int pixelImageSize = 0;
+        int totalImageSize = 0;
+        int skipRows = 0;
+        int skipImages = 0;
+
+        ctx->state()->getUnpackingOffsets3D(width, height, depth, format, type,
+                &bpp,
+                &startOffset,
+                &pixelRowSize,
+                &totalRowSize,
+                &pixelImageSize,
+                &totalImageSize,
+                &skipRows,
+                &skipImages);
+
+        size_t pixelDataSize =
+            ctx->state()->pixelDataSize(
+                    width, height, depth, format, type, 0 /* is unpack */);
+
+        size_t sent = 0;
+
+        if (startOffset == 0 &&
+            pixelRowSize == totalRowSize &&
+            pixelImageSize == totalImageSize) {
+            // fast path
+            writeFully(pixels, pixelDataSize);
+            sent += pixelDataSize;
+        } else if (pixelRowSize == totalRowSize &&
+                   pixelImageSize == totalImageSize &&
+                   pixelRowSize == (width * bpp)) {
+            // fast path but with skip in the beginning
+            std::vector<char> paddingToDiscard(startOffset, 0);
+            writeFully(&paddingToDiscard[0], startOffset);
+            writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
+            sent += pixelDataSize;
+        } else {
+            int totalReadback = 0;
+
+            if (startOffset > 0) {
+                std::vector<char> paddingToDiscard(startOffset, 0);
+                writeFully(&paddingToDiscard[0], startOffset);
+                totalReadback += startOffset;
+            }
+            // need to upload row by row
+            size_t paddingSize = totalRowSize - pixelRowSize;
+            std::vector<char> paddingToDiscard(paddingSize, 0);
+
+            char* start = (char*)pixels + startOffset;
+
+            size_t rowSlack = pixelRowSize - width * bpp;
+            std::vector<char> rowSlackToDiscard(rowSlack, 0);
+
+            size_t imageSlack = totalImageSize - pixelImageSize;
+            std::vector<char> imageSlackToDiscard(imageSlack, 0);
+
+            for (int k = 0; k < depth; ++k) {
+                for (int i = 0; i < height; i++) {
+                    if (pixelRowSize != width * bpp) {
+                        writeFully(start, width * bpp);
+                        writeFully(&rowSlackToDiscard[0], rowSlack);
+                        totalReadback += pixelRowSize;
+                        writeFully(&paddingToDiscard[0], paddingSize);
+                        totalReadback += paddingSize;
+                        start += totalRowSize;
+                    } else {
+                        writeFully(start, pixelRowSize);
+                        totalReadback += pixelRowSize;
+                        writeFully(&paddingToDiscard[0], paddingSize);
+                        totalReadback += paddingSize;
+                        start += totalRowSize;
+                    }
+                }
+                if (imageSlack > 0) {
+                    writeFully(&imageSlackToDiscard[0], imageSlack);
+                    start += imageSlack;
+                    totalReadback += imageSlack;
+                }
+            }
+        }
+    }
+}
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index 0df93f8..814021b 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -3344,7 +3344,7 @@
 	stream->writeFully(&__size_pixels,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_pixels,4);
 	if (pixels != NULL) {
-		stream->writeFully(pixels, __size_pixels);
+		 stream->uploadPixels(self, width, height, 1, format, type, pixels);
 		if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
 	}
 	buf = stream->alloc(checksumSize);
@@ -3497,7 +3497,7 @@
 	stream->writeFully(&__size_pixels,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_pixels,4);
 	if (pixels != NULL) {
-		stream->writeFully(pixels, __size_pixels);
+		 stream->uploadPixels(self, width, height, 1, format, type, pixels);
 		if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
 	}
 	buf = stream->alloc(checksumSize);
@@ -8489,7 +8489,7 @@
 	stream->writeFully(&__size_data,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_data,4);
 	if (data != NULL) {
-		stream->writeFully(data, __size_data);
+		 stream->uploadPixels(self, width, height, depth, format, type, data);
 		if (useChecksum) checksumCalculator->addBuffer(data, __size_data);
 	}
 	buf = stream->alloc(checksumSize);
@@ -8596,7 +8596,7 @@
 	stream->writeFully(&__size_data,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_data,4);
 	if (data != NULL) {
-		stream->writeFully(data, __size_data);
+		 stream->uploadPixels(self, width, height, depth, format, type, data);
 		if (useChecksum) checksumCalculator->addBuffer(data, __size_data);
 	}
 	buf = stream->alloc(checksumSize);
diff --git a/system/OpenglSystemCommon/Android.mk b/system/OpenglSystemCommon/Android.mk
index bb9e14f..fa24719 100644
--- a/system/OpenglSystemCommon/Android.mk
+++ b/system/OpenglSystemCommon/Android.mk
@@ -2,6 +2,15 @@
 
 $(call emugl-begin-shared-library,libOpenglSystemCommon)
 $(call emugl-import,libGLESv1_enc libGLESv2_enc lib_renderControl_enc)
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-import,libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX))
+$(call emugl-import,libqemupipe$(GOLDFISH_OPENGL_LIB_SUFFIX))
+$(call emugl-import,libgralloc_cb$(GOLDFISH_OPENGL_LIB_SUFFIX))
+else
+$(call emugl-export,STATIC_LIBRARIES,libGoldfishAddressSpace)
+$(call emugl-export,STATIC_LIBRARIES,libqemupipe.ranchu)
+$(call emugl-export,HEADER_LIBRARIES,libgralloc_cb.ranchu)
+endif
 
 LOCAL_SRC_FILES := \
     FormatConversions.cpp \
diff --git a/system/OpenglSystemCommon/CMakeLists.txt b/system/OpenglSystemCommon/CMakeLists.txt
index 7feb903..ff4947a 100644
--- a/system/OpenglSystemCommon/CMakeLists.txt
+++ b/system/OpenglSystemCommon/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/Android.mk" "6fedb15afaabb2c4e6cd24123f711639d6574b47356b2fa626a668bb497b8977")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/Android.mk" "1a769e79e22604f569e4345e4f432bb4bd41ca810d479b69887007b5d9bec528")
 set(OpenglSystemCommon_src FormatConversions.cpp HostConnection.cpp QemuPipeStream.cpp ProcessPipe.cpp AddressSpaceStream.cpp ThreadInfo_host.cpp)
 android_add_library(TARGET OpenglSystemCommon SHARED LICENSE Apache-2.0 SRC FormatConversions.cpp HostConnection.cpp QemuPipeStream.cpp ProcessPipe.cpp AddressSpaceStream.cpp ThreadInfo_host.cpp)
-target_include_directories(OpenglSystemCommon PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(OpenglSystemCommon PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(OpenglSystemCommon PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN")
 target_compile_options(OpenglSystemCommon PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-unused-variable")
-target_link_libraries(OpenglSystemCommon PRIVATE android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(OpenglSystemCommon PRIVATE android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index 4edf1fd..626048f 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -100,6 +100,11 @@
 // virtio-gpu-next
 static const char kVirtioGpuNext[] = "ANDROID_EMU_virtio_gpu_next";
 
+static const char kHasSharedSlotsHostMemoryAllocator[] = "ANDROID_EMU_has_shared_slots_host_memory_allocator";
+
+// Vulkan free memory sync
+static const char kVulkanFreeMemorySync[] = "ANDROID_EMU_vulkan_free_memory_sync";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -116,7 +121,10 @@
         hasVulkanIgnoredHandles(false),
         hasYUVCache (false),
         hasAsyncUnmapBuffer (false),
-        hasVirtioGpuNext (false) { }
+        hasVirtioGpuNext (false),
+        hasSharedSlotsHostMemoryAllocator(false),
+        hasVulkanFreeMemorySync(false)
+    { }
 
     SyncImpl syncImpl;
     DmaImpl dmaImpl;
@@ -131,6 +139,8 @@
     bool hasYUVCache;
     bool hasAsyncUnmapBuffer;
     bool hasVirtioGpuNext;
+    bool hasSharedSlotsHostMemoryAllocator;
+    bool hasVulkanFreeMemorySync;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/FormatConversions.cpp b/system/OpenglSystemCommon/FormatConversions.cpp
index ca4286c..cc976ed 100644
--- a/system/OpenglSystemCommon/FormatConversions.cpp
+++ b/system/OpenglSystemCommon/FormatConversions.cpp
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
 
 #include <hardware/gralloc.h>
 #include "FormatConversions.h"
diff --git a/system/OpenglSystemCommon/FormatConversions.h b/system/OpenglSystemCommon/FormatConversions.h
index f9d7806..51aab6d 100644
--- a/system/OpenglSystemCommon/FormatConversions.h
+++ b/system/OpenglSystemCommon/FormatConversions.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
 
 #ifndef __GOLDFISH_FORMATCONVERSIONS_H__
 #define __GOLDFISH_FORMATCONVERSIONS_H__
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index bbe2857..b9c97c9 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -66,8 +66,7 @@
 #include "QemuPipeStream.h"
 #include "TcpStream.h"
 #include "ThreadInfo.h"
-
-#include "gralloc_cb.h"
+#include <gralloc_cb_bp.h>
 
 #ifdef VIRTIO_GPU
 
@@ -614,6 +613,8 @@
         queryAndSetYUVCache(m_rcEnc);
         queryAndSetAsyncUnmapBuffer(m_rcEnc);
         queryAndSetVirtioGpuNext(m_rcEnc);
+        queryHasSharedSlotsHostMemoryAllocator(m_rcEnc);
+        queryAndSetVulkanFreeMemorySync(m_rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, m_rcEnc);
         }
@@ -817,3 +818,17 @@
         rcEnc->featureInfo()->hasVirtioGpuNext = true;
     }
 }
+
+void HostConnection::queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext *rcEnc) {
+    const std::string& glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kHasSharedSlotsHostMemoryAllocator) != std::string::npos) {
+        rcEnc->featureInfo()->hasSharedSlotsHostMemoryAllocator = true;
+    }
+}
+
+void HostConnection::queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext *rcEnc) {
+    const std::string& glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kVulkanFreeMemorySync) != std::string::npos) {
+        rcEnc->featureInfo()->hasVulkanFreeMemorySync = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index c91af0b..02c8681 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -204,6 +204,8 @@
     void queryAndSetYUVCache(ExtendedRCEncoderContext *mrcEnc);
     void queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVirtioGpuNext(ExtendedRCEncoderContext *rcEnc);
+    void queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext *rcEnc);
 
 private:
     HostConnectionType m_connectionType;
diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp
index 40cb298..84764f4 100644
--- a/system/OpenglSystemCommon/ProcessPipe.cpp
+++ b/system/OpenglSystemCommon/ProcessPipe.cpp
@@ -16,7 +16,8 @@
 
 #include "ProcessPipe.h"
 #include "renderControl_enc.h"
-#include "qemu_pipe.h"
+
+#include <qemu_pipe_bp.h>
 
 #if PLATFORM_SDK_VERSION < 26
 #include <cutils/log.h>
@@ -98,7 +99,7 @@
         ALOGE("%s: failed write confirm int", __FUNCTION__);
         return;
     }
-    status = pipe->Call(sizeof(confirmInt), 0, sizeof(sProcUID), 0, &status2, &actual);
+    status = pipe->DoCall(sizeof(confirmInt), 0, sizeof(sProcUID), 0, &status2, &actual);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGD("%s: failed to get per-process ID: %d:%d", __FUNCTION__,
               status, status2);
diff --git a/system/OpenglSystemCommon/QemuPipeStream.cpp b/system/OpenglSystemCommon/QemuPipeStream.cpp
index 57b60d1..d5fca2b 100644
--- a/system/OpenglSystemCommon/QemuPipeStream.cpp
+++ b/system/OpenglSystemCommon/QemuPipeStream.cpp
@@ -14,6 +14,7 @@
 * limitations under the License.
 */
 #include "QemuPipeStream.h"
+#include <qemu_pipe_bp.h>
 
 #if PLATFORM_SDK_VERSION < 26
 #include <cutils/log.h>
@@ -105,43 +106,7 @@
 
 int QemuPipeStream::writeFully(const void *buf, size_t len)
 {
-    //DBG(">> QemuPipeStream::writeFully %d\n", len);
-    if (!valid()) return -1;
-    if (!buf) {
-       if (len>0) {
-            // If len is non-zero, buf must not be NULL. Otherwise the pipe would be
-            // in a corrupted state, which is lethal for the emulator.
-           ERR("QemuPipeStream::writeFully failed, buf=NULL, len %zu,"
-                   " lethal error, exiting", len);
-           abort();
-       }
-       return 0;
-    }
-
-    size_t res = len;
-    int retval = 0;
-
-    while (res > 0) {
-        ssize_t stat = qemu_pipe_write(m_sock, (const char *)(buf) + (len - res), res);
-        if (stat > 0) {
-            res -= stat;
-            continue;
-        }
-        if (stat == 0) { /* EOF */
-            ERR("QemuPipeStream::writeFully failed: premature EOF\n");
-            retval = -1;
-            break;
-        }
-        if (qemu_pipe_try_again()) {
-            continue;
-        }
-        retval =  stat;
-        ERR("QemuPipeStream::writeFully failed: %s, lethal error, exiting.\n",
-                strerror(errno));
-        abort();
-    }
-    //DBG("<< QemuPipeStream::writeFully %d\n", len );
-    return retval;
+    return qemu_pipe_write_fully(m_sock, buf, len);
 }
 
 QEMU_PIPE_HANDLE QemuPipeStream::getSocket() const {
@@ -233,7 +198,7 @@
             continue;
         }
 
-        if (!qemu_pipe_try_again()) {
+        if (!qemu_pipe_try_again(actual)) {
             ALOGD("%s: Error reading from pipe: %d", __FUNCTION__, errno);
             return NULL;
         }
@@ -278,7 +243,7 @@
         if (res == 0) { /* EOF */
              break;
         }
-        if (qemu_pipe_try_again()) {
+        if (qemu_pipe_try_again(res)) {
             continue;
         }
 
diff --git a/system/OpenglSystemCommon/QemuPipeStream.h b/system/OpenglSystemCommon/QemuPipeStream.h
index 87638af..4e779eb 100644
--- a/system/OpenglSystemCommon/QemuPipeStream.h
+++ b/system/OpenglSystemCommon/QemuPipeStream.h
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include "IOStream.h"
 
-#include "qemu_pipe.h"
+#include <qemu_pipe_bp.h>
 
 #ifdef __Fuchsia__
 #include <fuchsia/hardware/goldfish/cpp/fidl.h>
diff --git a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
index 66dec13..5472f30 100644
--- a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
+++ b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp
@@ -180,7 +180,7 @@
 
     uint64_t actual = 0;
     zx_status_t status2 = ZX_OK;
-    zx_status_t status = m_pipe->Call(size, kWriteOffset, 0, 0, &status2, &actual);
+    zx_status_t status = m_pipe->DoCall(size, kWriteOffset, 0, 0, &status2, &actual);
     if (status != ZX_OK || status2 != ZX_OK) {
         ALOGD("%s: Pipe call failed: %d:%d", __FUNCTION__, status, status2);
         return -1;
@@ -238,7 +238,7 @@
     size_t maxRead = (m_readLeft || !remaining) ? 0 : kReadSize;
     uint64_t actual = 0;
     zx_status_t status2 = ZX_OK;
-    zx_status_t status = m_pipe->Call(size, kWriteOffset, maxRead, 0, &status2, &actual);
+    zx_status_t status = m_pipe->DoCall(size, kWriteOffset, maxRead, 0, &status2, &actual);
     if (status != ZX_OK) {
         ALOGD("%s: Pipe call failed: %d", __FUNCTION__, status);
         return nullptr;
diff --git a/system/cbmanager/Android.mk b/system/cbmanager/Android.mk
deleted file mode 100644
index 753f00a..0000000
--- a/system/cbmanager/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Copyright 2015 The Android Open-Source Project
-#
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CFLAGS += \
-    -DLOG_TAG=\"cbmanager\" \
-    -Werror \
-
-ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
-LOCAL_CFLAGS += \
-    -DHOST_BUILD \
-
-LOCAL_SRC_FILES := host.cpp
-else
-LOCAL_SHARED_LIBRARIES += \
-    liblog \
-    libcutils \
-    libutils \
-    libhidlbase \
-    android.hardware.graphics.mapper@2.0 \
-    android.hardware.graphics.mapper@3.0 \
-    android.hardware.graphics.allocator@2.0 \
-    android.hardware.graphics.allocator@3.0 \
-
-LOCAL_CFLAGS += \
-    -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
-
-LOCAL_SRC_FILES := hidl.cpp
-
-endif
-
-LOCAL_C_INCLUDES += \
-    device/generic/goldfish-opengl/system/include \
-    device/generic/goldfish-opengl/shared/OpenglCodecCommon \
-
-LOCAL_MODULE := libcbmanager
-LOCAL_VENDOR_MODULE := true
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/system/cbmanager/debug.h b/system/cbmanager/debug.h
deleted file mode 100644
index 23899bd..0000000
--- a/system/cbmanager/debug.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_DEBUG_H
-#define ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_DEBUG_H
-
-#include <log/log.h>
-
-#define CRASH(MSG) \
-    do { \
-        ALOGE("%s:%d crashed with '%s'", __func__, __LINE__, MSG); \
-        ::abort(); \
-    } while (false)
-
-#define CRASH_IF(COND, MSG) \
-    do { \
-        if ((COND)) { \
-            ALOGE("%s:%d crashed on '%s' with '%s'", __func__, __LINE__, #COND, MSG); \
-            ::abort(); \
-        } \
-    } while (false)
-
-#define RETURN_ERROR_CODE(X) \
-    do { \
-        ALOGE("%s:%d failed with '%s' (%d)", \
-              __func__, __LINE__, strerror(-(X)), -(X)); \
-        return (X); \
-    } while (false)
-
-#define RETURN_ERROR(X) \
-    do { \
-        ALOGE("%s:%d failed with '%s'", __func__, __LINE__, #X); \
-        return (X); \
-    } while (false)
-
-#define RETURN(X) return (X)
-
-#endif  // ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_DEBUG_H
diff --git a/system/cbmanager/hidl.cpp b/system/cbmanager/hidl.cpp
deleted file mode 100644
index 46b6b1b..0000000
--- a/system/cbmanager/hidl.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * 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.
- */
-
-#include <cutils/native_handle.h>
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <log/log.h>
-
-#include "cbmanager.h"
-#include "debug.h"
-
-namespace android {
-namespace {
-using hardware::hidl_handle;
-using hardware::hidl_vec;
-
-namespace IMapper2ns = hardware::graphics::mapper::V2_0;
-namespace IMapper3ns = hardware::graphics::mapper::V3_0;
-namespace IAllocator2ns = hardware::graphics::allocator::V2_0;
-namespace IAllocator3ns = hardware::graphics::allocator::V3_0;
-
-class CbManagerHidlV3Impl : public CbManager::CbManagerImpl {
-public:
-    typedef CbManager::BufferUsage BufferUsage;
-    typedef CbManager::PixelFormat PixelFormat;
-    typedef CbManager::YCbCrLayout YCbCrLayout;
-    typedef hardware::hidl_bitfield<BufferUsage> BufferUsageBits;
-
-    CbManagerHidlV3Impl(sp<IMapper3ns::IMapper> mapper,
-                        sp<IAllocator3ns::IAllocator> allocator)
-      : mMapper(mapper), mAllocator(allocator) {}
-
-    native_handle_t* allocateBuffer(int width, int height,
-                                    PixelFormat format, BufferUsageBits usage) {
-        using IMapper3ns::Error;
-        using IMapper3ns::BufferDescriptor;
-
-        IMapper3ns::IMapper::BufferDescriptorInfo descriptor_info;
-        descriptor_info.width = width;
-        descriptor_info.height = height;
-        descriptor_info.layerCount = 1;
-        descriptor_info.format =
-            static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
-        descriptor_info.usage = usage;
-        Error hidl_err = Error::NONE;
-
-        BufferDescriptor descriptor;
-        mMapper->createDescriptor(descriptor_info,
-                                  [&](const Error &_error,
-                                      const BufferDescriptor &_descriptor) {
-            hidl_err = _error;
-            descriptor = _descriptor;
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        hidl_handle raw_handle = nullptr;
-        mAllocator->allocate(descriptor, 1,
-                             [&](const Error &_error,
-                                 uint32_t _stride,
-                                 const hidl_vec<hidl_handle> &_buffers) {
-            hidl_err = _error;
-            (void)_stride;
-            raw_handle = _buffers[0];
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        native_handle_t *buf = nullptr;
-        mMapper->importBuffer(raw_handle, [&](const Error &_error,
-                                              void *_buf) {
-            hidl_err = _error;
-            buf = static_cast<native_handle_t*>(_buf);
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        RETURN(buf);
-    }
-
-    void freeBuffer(const native_handle_t* _h) {
-        using IMapper2ns::Error;
-
-        native_handle_t* h = const_cast<native_handle_t*>(_h);
-
-        mMapper->freeBuffer(h);
-        native_handle_close(h);
-        native_handle_delete(h);
-    }
-
-    int lockBuffer(native_handle_t& handle,
-                   BufferUsageBits usage,
-                   int left, int top, int width, int height,
-                   void** vaddr) {
-        using IMapper3ns::Error;
-
-        Error hidl_err = Error::NONE;
-        mMapper->lock(
-            &handle,
-            usage,
-            { left, top, width, height },  // rect
-            hidl_handle(),  // fence
-            [&hidl_err, vaddr](const Error &_error,
-                               void* _ptr,
-                               int32_t /*bytesPerPixel*/,
-                               int32_t /*bytesPerStride*/) {
-                hidl_err = _error;
-                if (_error == Error::NONE) {
-                    *vaddr = _ptr;
-                }
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-    int lockYCbCrBuffer(native_handle_t& handle,
-                        BufferUsageBits usage,
-                        int left, int top, int width, int height,
-                        YCbCrLayout* ycbcr) {
-        using IMapper3ns::Error;
-        typedef IMapper3ns::YCbCrLayout YCbCrLayout3;
-
-        Error hidl_err = Error::NONE;
-        mMapper->lockYCbCr(
-            &handle,
-            usage,
-            { left, top, width, height },  // rect
-            hidl_handle(),  // fence
-            [&hidl_err, ycbcr](const Error &_error,
-                               const YCbCrLayout3 &_ycbcr) {
-                hidl_err = _error;
-                if (_error == Error::NONE) {
-                    ycbcr->y = _ycbcr.y;
-                    ycbcr->cb = _ycbcr.cb;
-                    ycbcr->cr = _ycbcr.cr;
-                    ycbcr->yStride = _ycbcr.yStride;
-                    ycbcr->cStride = _ycbcr.cStride;
-                    ycbcr->chromaStep = _ycbcr.chromaStep;
-                }
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-    int unlockBuffer(native_handle_t& handle) {
-        using IMapper3ns::Error;
-
-        Error hidl_err = Error::NONE;
-        int fence = -1;
-        mMapper->unlock(
-            &handle,
-            [&hidl_err, &fence](const Error &_error,
-                                const hidl_handle &_fence) {
-                hidl_err = _error;
-                (void)_fence;
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-private:
-    const sp<IMapper3ns::IMapper> mMapper;
-    const sp<IAllocator3ns::IAllocator> mAllocator;
-};
-
-class CbManagerHidlV2Impl : public CbManager::CbManagerImpl {
-public:
-    typedef CbManager::BufferUsage BufferUsage;
-    typedef CbManager::PixelFormat PixelFormat;
-    typedef CbManager::YCbCrLayout YCbCrLayout;
-    typedef hardware::hidl_bitfield<BufferUsage> BufferUsageBits;
-
-    CbManagerHidlV2Impl(sp<IMapper2ns::IMapper> mapper,
-                        sp<IAllocator2ns::IAllocator> allocator)
-      : mMapper(mapper), mAllocator(allocator) {}
-
-    native_handle_t* allocateBuffer(int width, int height,
-                                    PixelFormat format, BufferUsageBits usage) {
-        using IMapper2ns::Error;
-        using IMapper2ns::BufferDescriptor;
-
-        IMapper2ns::IMapper::BufferDescriptorInfo descriptor_info;
-        descriptor_info.width = width;
-        descriptor_info.height = height;
-        descriptor_info.layerCount = 1;
-        descriptor_info.format = format;
-        descriptor_info.usage = usage;
-        Error hidl_err = Error::NONE;
-
-        BufferDescriptor descriptor;
-        mMapper->createDescriptor(descriptor_info,
-                                  [&](const Error &_error,
-                                      const BufferDescriptor &_descriptor) {
-            hidl_err = _error;
-            descriptor = _descriptor;
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        hidl_handle raw_handle = nullptr;
-        mAllocator->allocate(descriptor, 1,
-                             [&](const Error &_error,
-                                 uint32_t _stride,
-                                 const hidl_vec<hidl_handle> &_buffers) {
-            hidl_err = _error;
-            (void)_stride;
-            raw_handle = _buffers[0];
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        native_handle_t *buf = nullptr;
-        mMapper->importBuffer(raw_handle, [&](const Error &_error,
-                                              void *_buf) {
-            hidl_err = _error;
-            buf = static_cast<native_handle_t*>(_buf);
-        });
-        if (hidl_err != Error::NONE) {
-            RETURN_ERROR(nullptr);
-        }
-
-        RETURN(buf);
-    }
-
-    void freeBuffer(const native_handle_t* _h) {
-        using IMapper2ns::Error;
-
-        native_handle_t* h = const_cast<native_handle_t*>(_h);
-
-        mMapper->freeBuffer(h);
-        native_handle_close(h);
-        native_handle_delete(h);
-    }
-
-    int lockBuffer(native_handle_t& handle,
-                   BufferUsageBits usage,
-                   int left, int top, int width, int height,
-                   void** vaddr) {
-        using IMapper2ns::Error;
-
-        Error hidl_err = Error::NONE;
-        mMapper->lock(
-            &handle,
-            usage,
-            { left, top, width, height },  // rect
-            hidl_handle(),  // fence
-            [&hidl_err, vaddr](const Error &_error,
-                               void* _ptr) {
-                hidl_err = _error;
-                if (_error == Error::NONE) {
-                    *vaddr = _ptr;
-                }
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-    int lockYCbCrBuffer(native_handle_t& handle,
-                        BufferUsageBits usage,
-                        int left, int top, int width, int height,
-                        YCbCrLayout* ycbcr) {
-        using IMapper2ns::Error;
-
-        Error hidl_err = Error::NONE;
-        mMapper->lockYCbCr(
-            &handle,
-            usage,
-            { left, top, width, height },  // rect
-            hidl_handle(),  // fence
-            [&hidl_err, ycbcr](const Error &_error,
-                               const YCbCrLayout &_ycbcr) {
-                hidl_err = _error;
-                if (_error == Error::NONE) {
-                    *ycbcr = _ycbcr;
-                }
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-    int unlockBuffer(native_handle_t& handle) {
-        using IMapper2ns::Error;
-
-        Error hidl_err = Error::NONE;
-        int fence = -1;
-        mMapper->unlock(
-            &handle,
-            [&hidl_err, &fence](const Error &_error,
-                                const hidl_handle &_fence) {
-                hidl_err = _error;
-                (void)_fence;
-            });
-
-        if (hidl_err == Error::NONE) {
-            RETURN(0);
-        } else {
-            RETURN_ERROR(-1);
-        }
-    }
-
-private:
-    const sp<IMapper2ns::IMapper> mMapper;
-    const sp<IAllocator2ns::IAllocator> mAllocator;
-};
-
-std::unique_ptr<CbManager::CbManagerImpl> buildHidlImpl() {
-    {
-        sp<IMapper3ns::IMapper> mapper =
-            IMapper3ns::IMapper::getService();
-        if (!mapper) {
-           ALOGW("%s:%d: no IMapper@3.0 implementation found", __func__, __LINE__);
-        }
-
-        sp<IAllocator3ns::IAllocator> allocator =
-            IAllocator3ns::IAllocator::getService();
-        if (!allocator) {
-            ALOGW("%s:%d: no IAllocator@3.0 implementation found", __func__, __LINE__);
-        }
-
-        if (mapper && allocator) {
-            return std::make_unique<CbManagerHidlV3Impl>(mapper, allocator);
-        }
-    }
-    {
-        sp<IMapper2ns::IMapper> mapper =
-            IMapper2ns::IMapper::getService();
-        if (!mapper) {
-            ALOGW("%s:%d: no IMapper@2.0 implementation found", __func__, __LINE__);
-        }
-
-        sp<IAllocator2ns::IAllocator> allocator =
-            IAllocator2ns::IAllocator::getService();
-        if (!allocator) {
-            ALOGW("%s:%d: no IAllocator@2.0 implementation found", __func__, __LINE__);
-        }
-
-        return std::make_unique<CbManagerHidlV2Impl>(mapper, allocator);
-    }
-
-    return nullptr;
-}
-
-}  // namespace
-
-CbManager::CbManager() : mImpl(buildHidlImpl()) {}
-
-}  // namespace android
diff --git a/system/cbmanager/host.cpp b/system/cbmanager/host.cpp
deleted file mode 100644
index c1a46af..0000000
--- a/system/cbmanager/host.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * 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.
- */
-
-#include <hardware/gralloc.h>
-#include "cbmanager.h"
-
-namespace android {
-namespace {
-
-class CbManagerHostImpl : public CbManager::CbManagerImpl {
-public:
-    CbManagerHostImpl() {}
-
-    ~CbManagerHostImpl() {}
-
-    const cb_handle_t* allocateBuffer(int width, int height, int format) {
-        return nullptr;
-    }
-
-    void freeBuffer(const cb_handle_t* h) {
-    }
-
-private:
-};
-
-std::unique_ptr<CbManager::CbManagerImpl> buildHostImpl() {
-    return std::make_unique<CbManagerHostImpl>();
-}
-}  // namespace
-
-CbManager::CbManager() : mImpl(buildHostImpl()) {}
-
-}  // namespace android
diff --git a/system/codecs/omx/avcdec/Android.mk b/system/codecs/omx/avcdec/Android.mk
index 798255f..4ab6db3 100644
--- a/system/codecs/omx/avcdec/Android.mk
+++ b/system/codecs/omx/avcdec/Android.mk
@@ -49,6 +49,8 @@
 		android.hardware.graphics.mapper@3.0 \
         libstagefright_foundation
 
+LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
+
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
 $(call emugl-import,libgoldfish_codecs_common)
 $(call emugl-import,libstagefrighthw)
diff --git a/system/codecs/omx/avcdec/GoldfishAVCDec.h b/system/codecs/omx/avcdec/GoldfishAVCDec.h
index dc9dc96..0fd52b0 100644
--- a/system/codecs/omx/avcdec/GoldfishAVCDec.h
+++ b/system/codecs/omx/avcdec/GoldfishAVCDec.h
@@ -25,7 +25,7 @@
 #include <vector>
 #include <map>
 
-#include "gralloc_cb.h"
+#include <gralloc_cb_bp.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <utils/Vector.h>
diff --git a/system/codecs/omx/avcdec/exports.lds b/system/codecs/omx/avcdec/exports.lds
deleted file mode 100644
index e6674f2..0000000
--- a/system/codecs/omx/avcdec/exports.lds
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    global:
-        _Z26createGoldfishOMXComponentPKcPK16OMX_CALLBACKTYPEPvPP17OMX_COMPONENTTYPE;
-    local: *;
-};
diff --git a/system/codecs/omx/common/Android.mk b/system/codecs/omx/common/Android.mk
index 50ce286..9e233e7 100644
--- a/system/codecs/omx/common/Android.mk
+++ b/system/codecs/omx/common/Android.mk
@@ -28,5 +28,11 @@
 $(call emugl-export,SHARED_LIBRARIES,libcutils libutils liblog)
 
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
-$(call emugl-import,libOpenglSystemCommon)
+
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-import,libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX))
+else
+$(call emugl-export,STATIC_LIBRARIES,libGoldfishAddressSpace)
+endif
+
 $(call emugl-end-module)
diff --git a/system/codecs/omx/common/goldfish_media_utils.cpp b/system/codecs/omx/common/goldfish_media_utils.cpp
index 36883c2..ac1d1b0 100644
--- a/system/codecs/omx/common/goldfish_media_utils.cpp
+++ b/system/codecs/omx/common/goldfish_media_utils.cpp
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
 
 #include "goldfish_media_utils.h"
 
diff --git a/system/codecs/omx/common/goldfish_media_utils.h b/system/codecs/omx/common/goldfish_media_utils.h
index da57689..d25ee30 100644
--- a/system/codecs/omx/common/goldfish_media_utils.h
+++ b/system/codecs/omx/common/goldfish_media_utils.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2018 The Android Open Source Project
+//
+// 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.
 
 #include <linux/types.h>
 #include <stdint.h>
diff --git a/system/codecs/omx/plugin/Android.mk b/system/codecs/omx/plugin/Android.mk
index 77a2091..4adfd8a 100644
--- a/system/codecs/omx/plugin/Android.mk
+++ b/system/codecs/omx/plugin/Android.mk
@@ -35,15 +35,13 @@
 $(call emugl-export,SHARED_LIBRARIES,libcutils libutils liblog)
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
 
-
-
-LOCAL_HEADER_LIBRARIES := media_plugin_headers \
+LOCAL_HEADER_LIBRARIES += media_plugin_headers \
 	                      libmedia_headers \
 	                      libbinder_headers \
 	                      libhidlbase_impl_internal \
 	                      libbase
 
-LOCAL_SHARED_LIBRARIES :=       \
+LOCAL_SHARED_LIBRARIES +=       \
         libbinder               \
         libutils                \
         liblog                  \
diff --git a/system/codecs/omx/plugin/GoldfishOMXPlugin.cpp b/system/codecs/omx/plugin/GoldfishOMXPlugin.cpp
index 47c22a3..7ff9fa4 100644
--- a/system/codecs/omx/plugin/GoldfishOMXPlugin.cpp
+++ b/system/codecs/omx/plugin/GoldfishOMXPlugin.cpp
@@ -76,10 +76,12 @@
 }
 
 static const GoldfishComponent kComponents[] = {
-    { "OMX.google.goldfish.vp8.decoder", "vpxdec", "video_decoder.vp8" },
-    { "OMX.google.goldfish.vp9.decoder", "vpxdec", "video_decoder.vp9" },
-    { "OMX.google.goldfish.h264.decoder", "avcdec", "video_decoder.avc" },
-    { "OMX.android.goldfish.h264.decoder", "avcdec", "video_decoder.avc" },
+        {"OMX.google.goldfish.vp8.decoder", "vpxdec", "video_decoder.vp8"},
+        {"OMX.google.goldfish.vp9.decoder", "vpxdec", "video_decoder.vp9"},
+        {"OMX.google.goldfish.h264.decoder", "avcdec", "video_decoder.avc"},
+        {"OMX.android.goldfish.vp8.decoder", "vpxdec", "video_decoder.vp8"},
+        {"OMX.android.goldfish.vp9.decoder", "vpxdec", "video_decoder.vp9"},
+        {"OMX.android.goldfish.h264.decoder", "avcdec", "video_decoder.avc"},
 };
 
 static std::vector<GoldfishComponent> kActiveComponents;
diff --git a/system/codecs/omx/vpxdec/Android.mk b/system/codecs/omx/vpxdec/Android.mk
index 6374ac3..e7ec2d4 100644
--- a/system/codecs/omx/vpxdec/Android.mk
+++ b/system/codecs/omx/vpxdec/Android.mk
@@ -34,12 +34,23 @@
 	                      libhidlbase_impl_internal \
 	                      libbase
 
-LOCAL_SHARED_LIBRARIES :=       \
+LOCAL_HEADER_LIBRARIES += libui_headers \
+                          libnativewindow_headers \
+                          libhardware_headers \
+                          libarect_headers \
+                          libarect_headers_for_ndk
+
+LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
+
+LOCAL_SHARED_LIBRARIES +=       \
         libbinder               \
         libutils                \
         liblog                  \
         libcutils               \
+        libui                   \
         android.hardware.media.omx@1.0 \
+        android.hardware.graphics.allocator@3.0 \
+        android.hardware.graphics.mapper@3.0 \
         libstagefright_foundation
 
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
diff --git a/system/codecs/omx/vpxdec/GoldfishVPX.cpp b/system/codecs/omx/vpxdec/GoldfishVPX.cpp
index e10dec2..2e7043f 100644
--- a/system/codecs/omx/vpxdec/GoldfishVPX.cpp
+++ b/system/codecs/omx/vpxdec/GoldfishVPX.cpp
@@ -19,11 +19,29 @@
 #include <utils/misc.h>
 //#include "OMX_VideoExt.h"
 
+#define DEBUG 0
+#if DEBUG
+#define DDD(...) ALOGD(__VA_ARGS__)
+#else
+#define DDD(...) ((void)0)
+#endif
+
 #include "GoldfishVPX.h"
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaDefs.h>
 
+#include <OMX_VideoExt.h>
+#include <inttypes.h>
+
+#include <nativebase/nativebase.h>
+
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <hidl/LegacySupport.h>
+
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
 
 namespace android {
 
@@ -35,19 +53,26 @@
     { OMX_VIDEO_VP9Profile2HDR10Plus, OMX_VIDEO_VP9Level5 },
 };
 
-GoldfishVPX::GoldfishVPX(
-        const char *name,
-        const char *componentRole,
-        OMX_VIDEO_CODINGTYPE codingType,
-        const OMX_CALLBACKTYPE *callbacks,
-        OMX_PTR appData,
-        OMX_COMPONENTTYPE **component)
+GoldfishVPX::GoldfishVPX(const char* name,
+                         const char* componentRole,
+                         OMX_VIDEO_CODINGTYPE codingType,
+                         const OMX_CALLBACKTYPE* callbacks,
+                         OMX_PTR appData,
+                         OMX_COMPONENTTYPE** component,
+                         RenderMode renderMode)
     : GoldfishVideoDecoderOMXComponent(
-            name, componentRole, codingType,
-            codingType == OMX_VIDEO_CodingVP8 ? NULL : kVP9ProfileLevels,
-            codingType == OMX_VIDEO_CodingVP8 ?  0 : NELEM(kVP9ProfileLevels),
-            320 /* width */, 240 /* height */, callbacks, appData, component),
+              name,
+              componentRole,
+              codingType,
+              codingType == OMX_VIDEO_CodingVP8 ? NULL : kVP9ProfileLevels,
+              codingType == OMX_VIDEO_CodingVP8 ? 0 : NELEM(kVP9ProfileLevels),
+              320 /* width */,
+              240 /* height */,
+              callbacks,
+              appData,
+              component),
       mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9),
+      mRenderMode(renderMode),
       mEOSStatus(INPUT_DATA_AVAILABLE),
       mCtx(NULL),
       mFrameParallelMode(false),
@@ -55,17 +80,19 @@
       mImg(NULL) {
     // arbitrary from avc/hevc as vpx does not specify a min compression ratio
     const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4;
-    const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9;
-    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
-    initPorts(
-            kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */,
-            kNumBuffers, mime, kMinCompressionRatio);
-    ALOGE("calling constructor of GoldfishVPX");
-    CHECK_EQ(initDecoder(), (status_t)OK);
+    const char* mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8
+                                         : MEDIA_MIMETYPE_VIDEO_VP9;
+    const size_t kMaxOutputBufferSize = 3840 * 2160 * 3 / 2;  // 4k
+    initPorts(kNumBuffers,
+              kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */,
+              kNumBuffers, mime, kMinCompressionRatio);
+    ALOGI("calling constructor of GoldfishVPX");
+    // wait till later
+    // CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
 GoldfishVPX::~GoldfishVPX() {
-    ALOGE("calling destructor of GoldfishVPX");
+    ALOGI("calling destructor of GoldfishVPX");
     destroyDecoder();
 }
 
@@ -81,25 +108,33 @@
     mCtx = new vpx_codec_ctx_t;
     mCtx->vpversion = mMode == MODE_VP8 ? 8 : 9;
 
+    mCtx->version = mEnableAndroidNativeBuffers ? 200 : 100;
+
     int vpx_err = 0;
     if ((vpx_err = vpx_codec_dec_init(mCtx))) {
         ALOGE("vpx decoder failed to initialize. (%d)", vpx_err);
         return UNKNOWN_ERROR;
     }
 
+    ALOGI("calling init GoldfishVPX ctx %p", mCtx);
     return OK;
 }
 
 status_t GoldfishVPX::destroyDecoder() {
-    vpx_codec_destroy(mCtx);
-    delete mCtx;
-    mCtx = NULL;
+    if (mCtx) {
+        ALOGI("calling destroying GoldfishVPX ctx %p", mCtx);
+        vpx_codec_destroy(mCtx);
+        delete mCtx;
+        mCtx = NULL;
+    }
     return OK;
 }
 
-void GoldfishVPX::setup_ctx_parameters(vpx_codec_ctx_t* ctx) {
+void GoldfishVPX::setup_ctx_parameters(vpx_codec_ctx_t* ctx,
+                                       int hostColorBufferId) {
     ctx->width = mWidth;
     ctx->height = mHeight;
+    ctx->hostColorBufferId = hostColorBufferId;
     ctx->outputBufferWidth = outputBufferWidth();
     ctx->outputBufferHeight = outputBufferHeight();
     OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
@@ -111,6 +146,7 @@
     List<BufferInfo *> &outQueue = getPortQueue(1);
     BufferInfo *outInfo = NULL;
     OMX_BUFFERHEADERTYPE *outHeader = NULL;
+    DDD("%s %d", __func__, __LINE__);
 
     if (flushDecoder && mFrameParallelMode) {
         // Flush decoder by passing NULL data ptr and 0 size.
@@ -136,8 +172,11 @@
     }
 
     while (!outQueue.empty()) {
+        DDD("%s %d", __func__, __LINE__);
+        outInfo = *outQueue.begin();
+        outHeader = outInfo->mHeader;
         if (mImg == NULL) {
-            setup_ctx_parameters(mCtx);
+            setup_ctx_parameters(mCtx, getHostColorBufferId(outHeader));
             mImg = vpx_codec_get_frame(mCtx);
             if (mImg == NULL) {
                 break;
@@ -145,8 +184,6 @@
         }
         uint32_t width = mImg->d_w;
         uint32_t height = mImg->d_h;
-        outInfo = *outQueue.begin();
-        outHeader = outInfo->mHeader;
         CHECK(mImg->fmt == VPX_IMG_FMT_I420 || mImg->fmt == VPX_IMG_FMT_I42016);
         OMX_COLOR_FORMATTYPE outputColorFormat = OMX_COLOR_FormatYUV420Planar;
         int32_t bpp = 1;
@@ -168,11 +205,12 @@
             queueOutputFrameConfig(privInfo->mHdr10PlusInfo);
         }
 
-        if (outputBufferSafe(outHeader)) {
+        if (outputBufferSafe(outHeader) &&
+            getHostColorBufferId(outHeader) < 0) {
             uint8_t *dst = outHeader->pBuffer;
             memcpy(dst, mCtx->dst, outHeader->nFilledLen);
         } else {
-            outHeader->nFilledLen = 0;
+            // outHeader->nFilledLen = 0;
         }
 
         mImg = NULL;
@@ -202,6 +240,7 @@
 }
 
 bool GoldfishVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) {
+    DDD("%s %d", __func__, __LINE__);
     uint32_t width = outputBufferWidth();
     uint32_t height = outputBufferHeight();
     uint64_t nFilledLen = width;
@@ -221,10 +260,19 @@
 }
 
 void GoldfishVPX::onQueueFilled(OMX_U32 /* portIndex */) {
+    DDD("%s %d", __func__, __LINE__);
     if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
         return;
     }
 
+    if (mCtx == nullptr) {
+        if (OK != initDecoder()) {
+            ALOGE("Failed to initialize decoder");
+            notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+            return;
+        }
+    }
+
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
     bool EOSseen = false;
@@ -313,6 +361,7 @@
 }
 
 void GoldfishVPX::onPortFlushCompleted(OMX_U32 portIndex) {
+    DDD("%s %d", __func__, __LINE__);
     if (portIndex == kInputPortIndex) {
         bool portWillReset = false;
         if (!outputBuffers(
@@ -326,6 +375,7 @@
 }
 
 void GoldfishVPX::onReset() {
+    DDD("%s %d", __func__, __LINE__);
     bool portWillReset = false;
     if (!outputBuffers(
              true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) {
@@ -336,21 +386,141 @@
     mEOSStatus = INPUT_DATA_AVAILABLE;
 }
 
+int GoldfishVPX::getHostColorBufferId(void* header) {
+    DDD("%s %d", __func__, __LINE__);
+    if (mNWBuffers.find(header) == mNWBuffers.end()) {
+        DDD("cannot find color buffer for header %p", header);
+        return -1;
+    }
+    sp<ANativeWindowBuffer> nBuf = mNWBuffers[header];
+    cb_handle_t* handle = (cb_handle_t*)nBuf->handle;
+    DDD("found color buffer for header %p --> %d", header, handle->hostHandle);
+    return handle->hostHandle;
+}
+
+OMX_ERRORTYPE GoldfishVPX::internalGetParameter(OMX_INDEXTYPE index,
+                                                OMX_PTR params) {
+    const int32_t indexFull = index;
+    switch (indexFull) {
+        case kGetAndroidNativeBufferUsageIndex: {
+            DDD("calling kGetAndroidNativeBufferUsageIndex");
+            GetAndroidNativeBufferUsageParams* nativeBuffersUsage =
+                    (GetAndroidNativeBufferUsageParams*)params;
+            nativeBuffersUsage->nUsage =
+                    (unsigned int)(BufferUsage::GPU_DATA_BUFFER);
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return GoldfishVideoDecoderOMXComponent::internalGetParameter(
+                    index, params);
+    }
+}
+
+OMX_ERRORTYPE GoldfishVPX::internalSetParameter(OMX_INDEXTYPE index,
+                                                const OMX_PTR params) {
+    // Include extension index OMX_INDEXEXTTYPE.
+    const int32_t indexFull = index;
+
+    switch (indexFull) {
+        case kEnableAndroidNativeBuffersIndex: {
+            DDD("calling kEnableAndroidNativeBuffersIndex");
+            EnableAndroidNativeBuffersParams* enableNativeBuffers =
+                    (EnableAndroidNativeBuffersParams*)params;
+            if (enableNativeBuffers) {
+                mEnableAndroidNativeBuffers = enableNativeBuffers->enable;
+                if (mEnableAndroidNativeBuffers == false) {
+                    mNWBuffers.clear();
+                    DDD("disabled kEnableAndroidNativeBuffersIndex");
+                } else {
+                    DDD("enabled kEnableAndroidNativeBuffersIndex");
+                }
+            }
+            return OMX_ErrorNone;
+        }
+
+        case kUseAndroidNativeBufferIndex: {
+            if (mEnableAndroidNativeBuffers == false) {
+                ALOGE("Error: not enabled Android Native Buffers");
+                return OMX_ErrorBadParameter;
+            }
+            UseAndroidNativeBufferParams* use_buffer_params =
+                    (UseAndroidNativeBufferParams*)params;
+            if (use_buffer_params) {
+                sp<ANativeWindowBuffer> nBuf = use_buffer_params->nativeBuffer;
+                cb_handle_t* handle = (cb_handle_t*)nBuf->handle;
+                void* dst = NULL;
+                DDD("kUseAndroidNativeBufferIndex with handle %p host color "
+                    "handle %d "
+                    "calling usebuffer",
+                    handle, handle->hostHandle);
+                useBufferCallerLockedAlready(use_buffer_params->bufferHeader,
+                                             use_buffer_params->nPortIndex,
+                                             use_buffer_params->pAppPrivate,
+                                             handle->allocatedSize(),
+                                             (OMX_U8*)dst);
+                mNWBuffers[*(use_buffer_params->bufferHeader)] =
+                        use_buffer_params->nativeBuffer;
+                ;
+            }
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return GoldfishVideoDecoderOMXComponent::internalSetParameter(
+                    index, params);
+    }
+}
+
+OMX_ERRORTYPE GoldfishVPX::getExtensionIndex(const char* name,
+                                             OMX_INDEXTYPE* index) {
+    if (mRenderMode == RenderMode::RENDER_BY_HOST_GPU) {
+        if (!strcmp(name,
+                    "OMX.google.android.index.enableAndroidNativeBuffers")) {
+            DDD("calling getExtensionIndex for enable ANB");
+            *(int32_t*)index = kEnableAndroidNativeBuffersIndex;
+            return OMX_ErrorNone;
+        } else if (!strcmp(name,
+                           "OMX.google.android.index.useAndroidNativeBuffer")) {
+            *(int32_t*)index = kUseAndroidNativeBufferIndex;
+            return OMX_ErrorNone;
+        } else if (!strcmp(name,
+                           "OMX.google.android.index."
+                           "getAndroidNativeBufferUsage")) {
+            *(int32_t*)index = kGetAndroidNativeBufferUsageIndex;
+            return OMX_ErrorNone;
+        }
+    }
+    return GoldfishVideoDecoderOMXComponent::getExtensionIndex(name, index);
+}
+
 }  // namespace android
 
 android::GoldfishOMXComponent *createGoldfishOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
-    if (!strcmp(name, "OMX.google.goldfish.vp8.decoder")) {
+    DDD("%s %d", __func__, __LINE__);
+    // only support vp9 to use host hardware decoder, for now
+    if (!strncmp("OMX.android.goldfish.vp9.decoder", name, 32)) {
         return new android::GoldfishVPX(
-                name, "video_decoder.vp8", OMX_VIDEO_CodingVP8,
-                callbacks, appData, component);
-    } else if (!strcmp(name, "OMX.google.goldfish.vp9.decoder")) {
-        return new android::GoldfishVPX(
-                name, "video_decoder.vp9", OMX_VIDEO_CodingVP9,
-                callbacks, appData, component);
-    } else {
-        CHECK(!"Unknown component");
+                name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, callbacks,
+                appData, component, RenderMode::RENDER_BY_HOST_GPU);
     }
+    if (!strncmp("OMX.android.goldfish.vp8.decoder", name, 32)) {
+        return new android::GoldfishVPX(
+                name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, callbacks,
+                appData, component, RenderMode::RENDER_BY_HOST_GPU);
+    }
+    if (!strncmp("OMX.google.goldfish.vp9.decoder", name, 30)) {
+        return new android::GoldfishVPX(
+                name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, callbacks,
+                appData, component, RenderMode::RENDER_BY_GUEST_CPU);
+    }
+    if (!strncmp("OMX.google.goldfish.vp8.decoder", name, 30)) {
+        return new android::GoldfishVPX(
+                name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, callbacks,
+                appData, component, RenderMode::RENDER_BY_GUEST_CPU);
+    }
+    { CHECK(!"Unknown component"); }
     return NULL;
 }
diff --git a/system/codecs/omx/vpxdec/GoldfishVPX.h b/system/codecs/omx/vpxdec/GoldfishVPX.h
index 2ba8beb..cb9321f 100644
--- a/system/codecs/omx/vpxdec/GoldfishVPX.h
+++ b/system/codecs/omx/vpxdec/GoldfishVPX.h
@@ -21,17 +21,30 @@
 #include "GoldfishVideoDecoderOMXComponent.h"
 #include "goldfish_vpx_defs.h"
 
+#include <sys/time.h>
+
+#include <map>
+#include <vector>
+
+#include <ui/GraphicBuffer.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <gralloc_cb_bp.h>
+
 namespace android {
 
 struct ABuffer;
 
 struct GoldfishVPX : public GoldfishVideoDecoderOMXComponent {
-    GoldfishVPX(const char *name,
-            const char *componentRole,
-            OMX_VIDEO_CODINGTYPE codingType,
-            const OMX_CALLBACKTYPE *callbacks,
-            OMX_PTR appData,
-            OMX_COMPONENTTYPE **component);
+    GoldfishVPX(const char* name,
+                const char* componentRole,
+                OMX_VIDEO_CODINGTYPE codingType,
+                const OMX_CALLBACKTYPE* callbacks,
+                OMX_PTR appData,
+                OMX_COMPONENTTYPE** component,
+                RenderMode renderMode);
 
 protected:
     virtual ~GoldfishVPX();
@@ -42,6 +55,15 @@
     virtual bool supportDescribeHdrStaticInfo();
     virtual bool supportDescribeHdr10PlusInfo();
 
+    virtual OMX_ERRORTYPE internalGetParameter(OMX_INDEXTYPE index,
+                                               OMX_PTR params);
+
+    virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index,
+                                               const OMX_PTR params);
+
+    virtual OMX_ERRORTYPE getExtensionIndex(const char* name,
+                                            OMX_INDEXTYPE* index);
+
 private:
     enum {
         kNumBuffers = 10
@@ -52,6 +74,12 @@
         MODE_VP9
     } mMode;
 
+    RenderMode mRenderMode = RenderMode::RENDER_BY_GUEST_CPU;
+    bool mEnableAndroidNativeBuffers = false;
+    std::map<void*, sp<ANativeWindowBuffer>> mNWBuffers;
+
+    int getHostColorBufferId(void* header);
+
     enum {
         INPUT_DATA_AVAILABLE,  // VPX component is ready to decode data.
         INPUT_EOS_SEEN,        // VPX component saw EOS and is flushing On2 decoder.
@@ -73,7 +101,7 @@
     bool outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset);
     bool outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader);
 
-    void setup_ctx_parameters(vpx_codec_ctx_t*);
+    void setup_ctx_parameters(vpx_codec_ctx_t*, int hostColorBufferId = -1);
 
     DISALLOW_EVIL_CONSTRUCTORS(GoldfishVPX);
 };
diff --git a/system/codecs/omx/vpxdec/exports.lds b/system/codecs/omx/vpxdec/exports.lds
deleted file mode 100644
index e6674f2..0000000
--- a/system/codecs/omx/vpxdec/exports.lds
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    global:
-        _Z26createGoldfishOMXComponentPKcPK16OMX_CALLBACKTYPEPvPP17OMX_COMPONENTTYPE;
-    local: *;
-};
diff --git a/system/codecs/omx/vpxdec/goldfish_vpx_defs.h b/system/codecs/omx/vpxdec/goldfish_vpx_defs.h
index 1b1358c..25fecde 100644
--- a/system/codecs/omx/vpxdec/goldfish_vpx_defs.h
+++ b/system/codecs/omx/vpxdec/goldfish_vpx_defs.h
@@ -9,6 +9,11 @@
 
 typedef unsigned char uint8_t;
 
+enum class RenderMode {
+    RENDER_BY_HOST_GPU = 1,
+    RENDER_BY_GUEST_CPU = 2,
+};
+
 enum vpx_img_fmt_t {
   VPX_IMG_FMT_NONE,
   VPX_IMG_FMT_YV12 =
@@ -34,6 +39,11 @@
 
 struct vpx_codec_ctx_t {
     int vpversion; //8: vp8 or 9: vp9
+    int version;   // 100: return decoded frame to guest; 200: render on host
+    int hostColorBufferId;
+    uint64_t id;  // >= 1, unique
+    int memory_slot;
+    uint64_t address_offset = 0;
     size_t outputBufferWidth;
     size_t outputBufferHeight;
     size_t width;
@@ -41,11 +51,12 @@
     size_t bpp;
     uint8_t *data;
     uint8_t *dst;
+    vpx_image_t myImg;
 };
 
 int vpx_codec_destroy(vpx_codec_ctx_t*);
 int vpx_codec_dec_init(vpx_codec_ctx_t*);
-vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t*);
+vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t*, int hostColorBufferId = -1);
 int vpx_codec_flush(vpx_codec_ctx_t *ctx);
 int vpx_codec_decode(vpx_codec_ctx_t *ctx, const uint8_t *data,
                                  unsigned int data_sz, void *user_priv,
diff --git a/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp b/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
index 0771176..92dfcfa 100644
--- a/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
+++ b/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
@@ -14,27 +14,73 @@
 #include "goldfish_vpx_defs.h"
 #include "goldfish_media_utils.h"
 
-static vpx_image_t myImg;
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#define DEBUG 0
+#if DEBUG
+#define DDD(...) ALOGD(__VA_ARGS__)
+#else
+#define DDD(...) ((void)0)
+#endif
+
+// static vpx_image_t myImg;
+static uint64_t s_CtxId = 0;
+static std::mutex sCtxidMutex;
+
+static uint64_t applyForOneId() {
+    DDD("%s %d", __func__, __LINE__);
+    std::lock_guard<std::mutex> g{sCtxidMutex};
+    ++s_CtxId;
+    return s_CtxId;
+}
 
 static void sendVpxOperation(vpx_codec_ctx_t* ctx, MediaOperation op) {
+    DDD("%s %d", __func__, __LINE__);
+    if (ctx->memory_slot < 0) {
+        ALOGE("ERROR: Failed %s %d: there is no memory slot", __func__,
+              __LINE__);
+    }
     auto transport = GoldfishMediaTransport::getInstance();
-    transport->sendOperation(
-            ctx->vpversion == 8 ?
-                MediaCodecType::VP8Codec :
-                MediaCodecType::VP9Codec,
-            op);
+    transport->sendOperation(ctx->vpversion == 9 ? MediaCodecType::VP9Codec
+                                                 : MediaCodecType::VP8Codec,
+                             op, ctx->address_offset);
 }
 
 int vpx_codec_destroy(vpx_codec_ctx_t* ctx) {
+    DDD("%s %d", __func__, __LINE__);
+    auto transport = GoldfishMediaTransport::getInstance();
+    transport->writeParam(ctx->id, 0, ctx->address_offset);
     sendVpxOperation(ctx, MediaOperation::DestroyContext);
+    transport->returnMemorySlot(ctx->memory_slot);
+    ctx->memory_slot = -1;
     return 0;
 }
 
 int vpx_codec_dec_init(vpx_codec_ctx_t* ctx) {
+    DDD("%s %d", __func__, __LINE__);
     auto transport = GoldfishMediaTransport::getInstance();
+    int slot = transport->getMemorySlot();
+    if (slot < 0) {
+        ALOGE("ERROR: Failed %s %d: cannot get memory slot", __func__,
+              __LINE__);
+        return -1;
+    } else {
+        DDD("got slot %d", slot);
+    }
+    ctx->id = applyForOneId();
+    ctx->memory_slot = slot;
+    ctx->address_offset = static_cast<unsigned int>(slot) * 8 * (1 << 20);
+    DDD("got address offset 0x%x version %d", (int)(ctx->address_offset),
+        ctx->version);
+
     // data and dst are on the host side actually
-    ctx->data = transport->getInputAddr();
-    ctx->dst = transport->getOutputAddr();
+    ctx->data = transport->getInputAddr(ctx->address_offset);
+    ctx->dst = transport->getInputAddr(
+            ctx->address_offset);  // re-use input address
+    transport->writeParam(ctx->id, 0, ctx->address_offset);
+    transport->writeParam(ctx->version, 1, ctx->address_offset);
     sendVpxOperation(ctx, MediaOperation::InitContext);
     return 0;
 }
@@ -44,7 +90,9 @@
     return *pint;
 }
 
-static void getVpxFrame(uint8_t* ptr) {
+// vpx_image_t myImg;
+static void getVpxFrame(uint8_t* ptr, vpx_image_t& myImg) {
+    DDD("%s %d", __func__, __LINE__);
     uint8_t* imgptr = (ptr + 8);
     myImg.fmt = *(vpx_img_fmt_t*)imgptr;
     imgptr += 8;
@@ -53,31 +101,41 @@
     myImg.d_h = *(unsigned int *)imgptr;
     imgptr += 8;
     myImg.user_priv = (void*)(*(uint64_t*)imgptr);
+    DDD("fmt %d dw %d dh %d userpriv %p", (int)myImg.fmt, (int)myImg.d_w,
+        (int)myImg.d_h, myImg.user_priv);
 }
 
 //TODO: we might not need to do the putting all the time
-vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx) {
+vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx, int hostColorBufferId) {
+    DDD("%s %d %p", __func__, __LINE__);
     auto transport = GoldfishMediaTransport::getInstance();
 
-    transport->writeParam(ctx->outputBufferWidth, 0);
-    transport->writeParam(ctx->outputBufferHeight, 1);
-    transport->writeParam(ctx->width, 2);
-    transport->writeParam(ctx->height, 3);
-    transport->writeParam(ctx->bpp, 4);
-    transport->writeParam(transport->offsetOf((uint64_t)(ctx->dst)), 5);
+    transport->writeParam(ctx->id, 0, ctx->address_offset);
+    transport->writeParam(ctx->outputBufferWidth, 1, ctx->address_offset);
+    transport->writeParam(ctx->outputBufferHeight, 2, ctx->address_offset);
+    transport->writeParam(ctx->width, 3, ctx->address_offset);
+    transport->writeParam(ctx->height, 4, ctx->address_offset);
+    transport->writeParam(ctx->bpp, 5, ctx->address_offset);
+    transport->writeParam(ctx->hostColorBufferId, 6, ctx->address_offset);
+    transport->writeParam(
+            transport->offsetOf((uint64_t)(ctx->dst)) - ctx->address_offset, 7,
+            ctx->address_offset);
 
     sendVpxOperation(ctx, MediaOperation::GetImage);
 
-    auto* retptr = transport->getReturnAddr();
+    auto* retptr = transport->getReturnAddr(ctx->address_offset);
     int ret = getReturnCode(retptr);
     if (ret) {
         return nullptr;
     }
-    getVpxFrame(retptr);
-    return &myImg;
+    getVpxFrame(retptr, ctx->myImg);
+    return &(ctx->myImg);
 }
 
 int vpx_codec_flush(vpx_codec_ctx_t* ctx) {
+    DDD("%s %d", __func__, __LINE__);
+    auto transport = GoldfishMediaTransport::getInstance();
+    transport->writeParam(ctx->id, 0, ctx->address_offset);
     sendVpxOperation(ctx, MediaOperation::Flush);
     return 0;
 }
@@ -87,12 +145,17 @@
                      unsigned int data_sz,
                      void* user_priv,
                      long deadline) {
+    DDD("%s %d data size %d userpriv %p", __func__, __LINE__, (int)data_sz,
+        user_priv);
     auto transport = GoldfishMediaTransport::getInstance();
     memcpy(ctx->data, data, data_sz);
 
-    transport->writeParam(transport->offsetOf((uint64_t)(ctx->data)), 0);
-    transport->writeParam((__u64)data_sz, 1);
-    transport->writeParam((__u64)user_priv, 2);
+    transport->writeParam(ctx->id, 0, ctx->address_offset);
+    transport->writeParam(
+            transport->offsetOf((uint64_t)(ctx->data)) - ctx->address_offset, 1,
+            ctx->address_offset);
+    transport->writeParam((__u64)data_sz, 2, ctx->address_offset);
+    transport->writeParam((__u64)user_priv, 3, ctx->address_offset);
     sendVpxOperation(ctx, MediaOperation::DecodeImage);
     return 0;
 }
diff --git a/system/egl/Android.mk b/system/egl/Android.mk
index 58663e5..6e239b2 100644
--- a/system/egl/Android.mk
+++ b/system/egl/Android.mk
@@ -6,6 +6,12 @@
 $(call emugl-import,libOpenglSystemCommon)
 $(call emugl-set-shared-library-subpath,egl)
 
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-import,libqemupipe$(GOLDFISH_OPENGL_LIB_SUFFIX))
+else
+$(call emugl-export,STATIC_LIBRARIES,libqemupipe.ranchu)
+endif
+
 LOCAL_CFLAGS += -DLOG_TAG=\"EGL_emulation\" -DEGL_EGLEXT_PROTOTYPES -DWITH_GLES2
 LOCAL_CFLAGS += -Wno-gnu-designator
 
diff --git a/system/egl/CMakeLists.txt b/system/egl/CMakeLists.txt
index 25b4cdd..08db0c8 100644
--- a/system/egl/CMakeLists.txt
+++ b/system/egl/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/egl/Android.mk" "53f944775eac93c4fff6cb2b10ec932462422eb0e4ae0fb616f2f16bb0baf4af")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/egl/Android.mk" "597fba46fce0876a62ef3c0bc8f3a0264503214b62b0b0da092ee90fe60f09e1")
 set(EGL_emulation_src eglDisplay.cpp egl.cpp ClientAPIExts.cpp)
 android_add_library(TARGET EGL_emulation SHARED LICENSE Apache-2.0 SRC eglDisplay.cpp egl.cpp ClientAPIExts.cpp)
-target_include_directories(EGL_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(EGL_emulation PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(EGL_emulation PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"EGL_emulation\"" "-DEGL_EGLEXT_PROTOTYPES")
 target_compile_options(EGL_emulation PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-gnu-designator")
-target_link_libraries(EGL_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(EGL_emulation PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 5940b79..834207b 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -33,7 +33,8 @@
 #include "ClientAPIExts.h"
 #include "EGLImage.h"
 #include "ProcessPipe.h"
-#include "qemu_pipe.h"
+
+#include <qemu_pipe_bp.h>
 
 #include "GLEncoder.h"
 #ifdef WITH_GLES2
@@ -120,7 +121,7 @@
 #endif //LOG_EGL_ERRORS
 
 #define VALIDATE_CONFIG(cfg,ret) \
-    if(((intptr_t)(cfg)<0)||((intptr_t)(cfg)>s_display.getNumConfigs())) { \
+    if (!s_display.isValidConfig(cfg)) { \
         RETURN_ERROR(ret,EGL_BAD_CONFIG); \
     }
 
@@ -408,7 +409,7 @@
     setNativeHeight(nativeHeight);
 
     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
-    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
+    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)s_display.getIndexOfConfig(config),
             getWidth(), getHeight());
 
     if (!rcSurface) {
@@ -668,7 +669,7 @@
 {
     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
 
-    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
+    rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)s_display.getIndexOfConfig(config),
             getWidth(), getHeight());
     if (!rcSurface) {
         ALOGE("rcCreateWindowSurface returned 0");
@@ -945,7 +946,7 @@
 
     EGLint i;
     for (i = 0 ; i < numConfigs && i < config_size ; i++) {
-        *configs++ = (EGLConfig)(uintptr_t)i;
+        *configs++ = (EGLConfig)(uintptr_t)s_display.getConfigAtIndex(i);
     }
     *num_config = i;
     return EGL_TRUE;
@@ -1006,7 +1007,8 @@
     if (configs!=NULL) {
         EGLint i=0;
         for (i=0;i<(*num_config);i++) {
-             *((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
+            EGLConfig guestConfig = s_display.getConfigAtIndex(*((uint32_t*)tempConfigs+i));
+            configs[i] = guestConfig;
         }
     }
 
@@ -1614,7 +1616,7 @@
     if (majorVersion == 3 && minorVersion == 2) {
         rcMajorVersion = 4;
     }
-    uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, rcMajorVersion);
+    uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)s_display.getIndexOfConfig(config), rcShareCtx, rcMajorVersion);
     if (!rcContext) {
         ALOGE("rcCreateContext returned 0");
         setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
@@ -1713,7 +1715,6 @@
     //Now make the local bind
     if (context) {
 
-        ALOGD("%s: %p: ver %d %d (tinfo %p)", __FUNCTION__, context, context->majorVersion, context->minorVersion, tInfo);
         // This is a nontrivial context.
         // The thread cannot be gralloc-only anymore.
         hostCon->setGrallocOnly(false);
@@ -1730,6 +1731,9 @@
             context->getClientState();
 
         if (!hostCon->gl2Encoder()->isInitialized()) {
+            ALOGD("%s: %p: ver %d %d (tinfo %p) (first time)",
+                  __FUNCTION__,
+                  context, context->majorVersion, context->minorVersion, tInfo);
             s_display.gles2_iface()->init();
             hostCon->gl2Encoder()->setInitialized();
             ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
@@ -1833,6 +1837,9 @@
         }
         else {
             if (!hostCon->glEncoder()->isInitialized()) {
+                ALOGD("%s: %p: ver %d %d (tinfo %p) (first time)",
+                      __FUNCTION__,
+                      context, context->majorVersion, context->minorVersion, tInfo);
                 s_display.gles_iface()->init();
                 hostCon->glEncoder()->setInitialized();
                 ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
diff --git a/system/egl/eglDisplay.cpp b/system/egl/eglDisplay.cpp
index 2e18e11..b3f14da 100644
--- a/system/egl/eglDisplay.cpp
+++ b/system/egl/eglDisplay.cpp
@@ -171,7 +171,10 @@
 
         uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1);
         EGLint tmp_buf[nInts];
+        uint32_t configCount = nInts - m_numConfigAttribs;
+
         m_configs = new EGLint[nInts-m_numConfigAttribs];
+
         if (!m_configs) {
             pthread_mutex_unlock(&m_lock);
             return false;
@@ -204,7 +207,7 @@
 void eglDisplay::processConfigs()
 {
     for (intptr_t i=0; i<m_numConfigs; i++) {
-        EGLConfig config = (EGLConfig)i;
+        EGLConfig config = getConfigAtIndex(i);
         PixelFormat format;
         if (getConfigNativePixelFormat(config, &format)) {
             setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
@@ -443,13 +446,29 @@
         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
         return EGL_FALSE;
     }
-    *value = *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx);
+    *value = *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx);
     return EGL_TRUE;
 }
 
 #define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
 #define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
 
+EGLConfig eglDisplay::getConfigAtIndex(uint32_t index) const {
+    uintptr_t asPtr = (uintptr_t)index;
+    return (EGLConfig)(asPtr + 1);
+}
+
+uint32_t eglDisplay::getIndexOfConfig(EGLConfig config) const {
+    uintptr_t asInteger = (uintptr_t)config;
+    return (uint32_t)(asInteger - 1);
+}
+
+bool eglDisplay::isValidConfig(EGLConfig cfg) const {
+    uint32_t index = getIndexOfConfig(cfg);
+    intptr_t asInt = (intptr_t)index;
+    return !(asInt < 0 || asInt > m_numConfigs);
+}
+
 EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
 {
     if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) {
@@ -484,10 +503,10 @@
 void eglDisplay::dumpConfig(EGLConfig config)
 {
     EGLint value = 0;
-    DBG("^^^^^^^^^^ dumpConfig %d ^^^^^^^^^^^^^^^^^^", (int)config);
+    DBG("^^^^^^^^^^ dumpConfig %p ^^^^^^^^^^^^^^^^^^", config);
     for (int i=0; i<m_numConfigAttribs; i++) {
         getAttribValue(config, i, &value);
-        DBG("{%d}[%d] %d\n", (int)config, i, value);
+        DBG("Config %p: {%u}[%d] %d\n", config, getIndexOfConfig(config), i, value);
     }
 }
 
@@ -501,7 +520,7 @@
         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
         return EGL_FALSE;
     }
-    *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx) = value;
+    *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx) = value;
     return EGL_TRUE;
 }
 
diff --git a/system/egl/eglDisplay.h b/system/egl/eglDisplay.h
index 2394da1..951075d 100644
--- a/system/egl/eglDisplay.h
+++ b/system/egl/eglDisplay.h
@@ -56,6 +56,11 @@
     const EGLClient_glesInterface *gles2_iface() const { return m_gles2_iface; }
 
     int     getNumConfigs(){ return m_numConfigs; }
+
+    EGLConfig getConfigAtIndex(uint32_t index) const;
+    uint32_t getIndexOfConfig(EGLConfig config) const;
+    bool isValidConfig(EGLConfig cfg) const;
+
     EGLBoolean  getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value);
     EGLBoolean  setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value);
     EGLBoolean getConfigGLPixelFormat(EGLConfig config, GLenum * format);
diff --git a/system/egl/goldfish_sync.h b/system/egl/goldfish_sync.h
index 18e3083..bb0cf44 100644
--- a/system/egl/goldfish_sync.h
+++ b/system/egl/goldfish_sync.h
@@ -1,16 +1,16 @@
-/*
- * Copyright (C) 2016 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
 
 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_SYNC_H
 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_SYNC_H
diff --git a/system/enc_common/IOStream_common.cpp b/system/enc_common/IOStream_common.cpp
deleted file mode 100644
index 901ad1d..0000000
--- a/system/enc_common/IOStream_common.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "IOStream.h"
-
-#include "GL2Encoder.h"
-
-#include <GLES3/gl31.h>
-
-#include <vector>
-
-#include <assert.h>
-
-void IOStream::readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels) {
-    GL2Encoder *ctx = (GL2Encoder *)context;
-    assert (ctx->state() != NULL);
-
-    int startOffset = 0;
-    int pixelRowSize = 0;
-    int totalRowSize = 0;
-    int skipRows = 0;
-
-    ctx->state()->getPackingOffsets2D(width, height, format, type,
-                                      &startOffset,
-                                      &pixelRowSize,
-                                      &totalRowSize,
-                                      &skipRows);
-
-    size_t pixelDataSize =
-        ctx->state()->pixelDataSize(
-            width, height, 1, format, type, 1 /* is pack */);
-
-    if (startOffset == 0 &&
-        pixelRowSize == totalRowSize) {
-        // fast path
-        readback(pixels, pixelDataSize);
-    } else if (pixelRowSize == totalRowSize) {
-        // fast path but with skip in the beginning
-        std::vector<char> paddingToDiscard(startOffset, 0);
-        readback(&paddingToDiscard[0], startOffset);
-        readback((char*)pixels + startOffset, pixelDataSize - startOffset);
-    } else {
-        int totalReadback = 0;
-
-        if (startOffset > 0) {
-            std::vector<char> paddingToDiscard(startOffset, 0);
-            readback(&paddingToDiscard[0], startOffset);
-            totalReadback += startOffset;
-        }
-        // need to read back row by row
-        size_t paddingSize = totalRowSize - pixelRowSize;
-        std::vector<char> paddingToDiscard(paddingSize, 0);
-
-        char* start = (char*)pixels + startOffset;
-
-        for (int i = 0; i < height; i++) {
-            readback(start, pixelRowSize);
-            totalReadback += pixelRowSize;
-            readback(&paddingToDiscard[0], paddingSize);
-            totalReadback += paddingSize;
-            start += totalRowSize;
-        }
-    }
-}
diff --git a/system/gralloc/CMakeLists.txt b/system/gralloc/CMakeLists.txt
index cf65352..b972006 100644
--- a/system/gralloc/CMakeLists.txt
+++ b/system/gralloc/CMakeLists.txt
@@ -4,17 +4,17 @@
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/gralloc/Android.mk" "09618d9293855148fb310e67065028da8c7f6dcf936b02b5695292c82ed4724e")
 set(gralloc.goldfish_src gralloc_old.cpp)
 android_add_library(TARGET gralloc.goldfish SHARED LICENSE Apache-2.0 SRC gralloc_old.cpp)
-target_include_directories(gralloc.goldfish PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(gralloc.goldfish PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(gralloc.goldfish PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"gralloc_goldfish\"")
 target_compile_options(gralloc.goldfish PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-missing-field-initializers" "-Wno-gnu-designator")
-target_link_libraries(gralloc.goldfish PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log GLESv2_enc _renderControl_enc GLESv1_enc OpenglCodecCommon_host)
+target_link_libraries(gralloc.goldfish PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log GLESv2_enc _renderControl_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/gralloc/Android.mk" "09618d9293855148fb310e67065028da8c7f6dcf936b02b5695292c82ed4724e")
 set(gralloc.ranchu_src gralloc_old.cpp)
 android_add_library(TARGET gralloc.ranchu SHARED LICENSE Apache-2.0 SRC gralloc_old.cpp)
-target_include_directories(gralloc.ranchu PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(gralloc.ranchu PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(gralloc.ranchu PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"gralloc_ranchu\"")
 target_compile_options(gralloc.ranchu PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-missing-field-initializers" "-Wno-gnu-designator")
-target_link_libraries(gralloc.ranchu PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log GLESv2_enc _renderControl_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(gralloc.ranchu PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log GLESv2_enc _renderControl_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/gralloc/gralloc_30.cpp b/system/gralloc/gralloc_30.cpp
index 09f421c..b67f4c5 100644
--- a/system/gralloc/gralloc_30.cpp
+++ b/system/gralloc/gralloc_30.cpp
@@ -32,12 +32,12 @@
 #include <hardware/hardware.h>
 #include <hardware/gralloc.h>
 
-#include "../../shared/OpenglCodecCommon/gralloc_cb.h"
+#include <gralloc_cb_bp.h>
 #include "gralloc_common.h"
 #include "goldfish_address_space.h"
 #include "HostConnection.h"
 #include "FormatConversions.h"
-#include "qemu_pipe.h"
+#include <qemu_pipe_bp.h>
 
 #define CRASH(MSG) \
     do { \
@@ -783,7 +783,7 @@
 class goldfish_address_space_host_malloc_buffer_manager_t : public buffer_manager_t {
 public:
     goldfish_address_space_host_malloc_buffer_manager_t(goldfish_gralloc30_module_t* gr): m_gr(gr) {
-        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(false);
         CRASH_IF(!host_memory_allocator.is_opened(),
                  "GoldfishAddressSpaceHostMemoryAllocator failed to open");
 
@@ -804,7 +804,11 @@
                      int glFormat, int glType,
                      size_t bufferSize,
                      buffer_handle_t* pHandle) override {
-        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+        const HostConnectionSession conn = m_gr->getHostConnectionSession();
+        ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+
+        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
+            rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
         if (!host_memory_allocator.is_opened()) { RETURN_ERROR_CODE(-EIO); }
 
         GoldfishAddressSpaceBlock bufferBits;
@@ -819,9 +823,6 @@
             const GLenum allocFormat =
                 (HAL_PIXEL_FORMAT_RGBX_8888 == format) ? GL_RGB : glFormat;
 
-            const HostConnectionSession conn = m_gr->getHostConnectionSession();
-            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
-
             hostHandle = rcEnc->rcCreateColorBufferDMA(
                 rcEnc,
                 width, height,
diff --git a/system/gralloc/gralloc_old.cpp b/system/gralloc/gralloc_old.cpp
index 56e6c26..7af9dfe 100644
--- a/system/gralloc/gralloc_old.cpp
+++ b/system/gralloc/gralloc_old.cpp
@@ -23,12 +23,7 @@
 #include <sys/mman.h>
 #include <hardware/gralloc.h>
 
-#if PLATFORM_SDK_VERSION < 28
-#include "gralloc_cb.h"
-#else
-#include "../../shared/OpenglCodecCommon/gralloc_cb.h"
-#endif
-
+#include <gralloc_cb_bp.h>
 #include "gralloc_common.h"
 
 #include "goldfish_dma.h"
@@ -38,7 +33,7 @@
 #include "ProcessPipe.h"
 #include "ThreadInfo.h"
 #include "glUtils.h"
-#include "qemu_pipe.h"
+#include <qemu_pipe_bp.h>
 
 #if PLATFORM_SDK_VERSION < 26
 #include <cutils/log.h>
@@ -197,7 +192,11 @@
 #define INITIAL_DMA_REGION_SIZE 4096
 struct gralloc_dmaregion_t {
     gralloc_dmaregion_t(ExtendedRCEncoderContext *rcEnc)
-      : sz(INITIAL_DMA_REGION_SIZE), refcount(0), bigbufCount(0) {
+      : host_memory_allocator(
+            rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator),
+        sz(INITIAL_DMA_REGION_SIZE),
+        refcount(0),
+        bigbufCount(0) {
         memset(&goldfish_dma, 0, sizeof(goldfish_dma));
         pthread_mutex_init(&lock, NULL);
 
diff --git a/system/hals/Android.mk b/system/hals/Android.mk
index 912a362..3cdb4bf 100644
--- a/system/hals/Android.mk
+++ b/system/hals/Android.mk
@@ -34,9 +34,13 @@
     liblog \
     libutils
 
+LOCAL_STATIC_LIBRARIES += libqemupipe.ranchu libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX)
+LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
+
 LOCAL_C_INCLUDES += \
     device/generic/goldfish-opengl/system/include \
     device/generic/goldfish-opengl/system/OpenglSystemCommon \
+    device/generic/goldfish-opengl/shared/GoldfishAddressSpace/include \
     device/generic/goldfish-opengl/shared/OpenglCodecCommon \
     device/generic/goldfish-opengl/host/include/libOpenglRender \
     device/generic/goldfish-opengl/system/renderControl_enc \
@@ -45,7 +49,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := android.hardware.graphics.mapper@3.0-impl
+LOCAL_MODULE := android.hardware.graphics.mapper@3.0-impl-ranchu
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_VENDOR_MODULE := true
 LOCAL_SRC_FILES := mapper3.cpp
@@ -63,9 +67,13 @@
     libutils \
     libsync
 
+LOCAL_STATIC_LIBRARIES += libqemupipe.ranchu libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX)
+LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
+
 LOCAL_C_INCLUDES += \
     device/generic/goldfish-opengl/system/include \
     device/generic/goldfish-opengl/system/OpenglSystemCommon \
+    device/generic/goldfish-opengl/shared/GoldfishAddressSpace/include \
     device/generic/goldfish-opengl/shared/OpenglCodecCommon \
     device/generic/goldfish-opengl/host/include/libOpenglRender \
     device/generic/goldfish-opengl/system/renderControl_enc \
diff --git a/system/hals/allocator3.cpp b/system/hals/allocator3.cpp
index 8be88ff..8b433c2 100644
--- a/system/hals/allocator3.cpp
+++ b/system/hals/allocator3.cpp
@@ -17,6 +17,7 @@
 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
 #include <hidl/LegacySupport.h>
+#include <qemu_pipe_bp.h>
 
 #include "glUtils.h"
 #include "cb_handle_30.h"
@@ -24,7 +25,7 @@
 #include "types.h"
 #include "debug.h"
 
-#define OMX_COLOR_FormatYUV420Planar 19
+const int kOMX_COLOR_FormatYUV420Planar = 19;
 
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_vec;
@@ -192,8 +193,8 @@
 
         case PixelFormat::YCBCR_420_888:
             yuv_format = true;
-            // We are going to use RGB888 on the host
-            glFormat = GL_RGB;
+            // We are going to use RGBA 8888 on the host
+            glFormat = GL_RGBA;
             glType = GL_UNSIGNED_BYTE;
             emulatorFrameworkFormat = EmulatorFrameworkFormat::YUV_420_888;
             break;
@@ -294,7 +295,7 @@
                 }
             }
             RETURN_ERROR(Error3::UNSUPPORTED);
-        } else if ((int)frameworkFormat == OMX_COLOR_FormatYUV420Planar &&
+        } else if (static_cast<int>(frameworkFormat) == kOMX_COLOR_FormatYUV420Planar &&
                (usage & BufferUsage::GPU_DATA_BUFFER)) {
             ALOGW("gralloc_alloc: Requested OMX_COLOR_FormatYUV420Planar, given "
               "YCbCr_420_888, taking experimental path. "
@@ -329,7 +330,12 @@
                       const int32_t bytesPerPixel,
                       const int32_t stride,
                       cb_handle_30_t** cb) {
-        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+        const HostConnectionSession conn = getHostConnectionSession();
+        ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+        CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
+
+        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
+            rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
         if (!host_memory_allocator.is_opened()) {
             RETURN_ERROR(Error3::NO_RESOURCES);
         }
@@ -350,10 +356,6 @@
             const GLenum allocFormat =
                 (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
 
-            const HostConnectionSession conn = getHostConnectionSession();
-            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
-            CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
-
             hostHandle = rcEnc->rcCreateColorBufferDMA(
                 rcEnc,
                 width, height,
diff --git a/system/hals/cb_handle_30.h b/system/hals/cb_handle_30.h
index 11ce322..374008e 100644
--- a/system/hals/cb_handle_30.h
+++ b/system/hals/cb_handle_30.h
@@ -17,7 +17,7 @@
 #ifndef SYSTEM_HALS_CB_HANDLE_30_H
 #define SYSTEM_HALS_CB_HANDLE_30_H
 
-#include "gralloc_cb.h"
+#include <gralloc_cb_bp.h>
 #include "goldfish_address_space.h"
 
 const uint32_t CB_HANDLE_MAGIC_30 = CB_HANDLE_MAGIC_BASE | 0x2;
diff --git a/system/hals/mapper3.cpp b/system/hals/mapper3.cpp
index b48e497..3221350 100644
--- a/system/hals/mapper3.cpp
+++ b/system/hals/mapper3.cpp
@@ -23,6 +23,8 @@
 #include "FormatConversions.h"
 #include "debug.h"
 
+const int kOMX_COLOR_FormatYUV420Planar = 19;
+
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
@@ -77,7 +79,7 @@
 class GoldfishMapper : public IMapper3 {
 public:
     GoldfishMapper() : m_hostConn(HostConnection::createUnique()) {
-        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+        GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(false);
         CRASH_IF(!host_memory_allocator.is_opened(),
                  "GoldfishAddressSpaceHostMemoryAllocator failed to open");
 
@@ -86,6 +88,8 @@
                  "hostMalloc failed");
 
         m_physAddrToOffset = bufferBits.physAddr() - bufferBits.offset();
+
+        host_memory_allocator.hostFree(&bufferBits);
     }
 
     Return<void> importBuffer(const hidl_handle& hh,
@@ -575,6 +579,10 @@
             RETURN(usageSwRead);
 
         default:
+            if (static_cast<int>(descriptor.format) == kOMX_COLOR_FormatYUV420Planar) {
+                return (usage & BufferUsage::GPU_DATA_BUFFER) != 0;
+            }
+
             RETURN(false);
         }
     }
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk
index 698de73..24a8a58 100644
--- a/system/hwc2/Android.mk
+++ b/system/hwc2/Android.mk
@@ -32,6 +32,7 @@
 emulator_hwcomposer_cflags += \
     -DLOG_TAG=\"hwc2\" \
     -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
+    -DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
 
 emulator_hwcomposer_c_includes += \
     system/core/libsync \
@@ -45,15 +46,14 @@
 emulator_hwcomposer_relative_path := hw
 
 emulator_hwcomposer2_src_files := \
-    EmuHWC2.cpp \
-    MiniFence.cpp
+    EmuHWC2.cpp
 
 include $(CLEAR_VARS)
 
 LOCAL_VENDOR_MODULE := true
 LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
 LOCAL_SHARED_LIBRARIES += libOpenglSystemCommon lib_renderControl_enc
-LOCAL_SHARED_LIBRARIES += libcbmanager
+LOCAL_SHARED_LIBRARIES += libui
 LOCAL_SRC_FILES := $(emulator_hwcomposer2_src_files)
 LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
 LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
diff --git a/system/hwc2/EmuHWC2.cpp b/system/hwc2/EmuHWC2.cpp
index 14bb545..72399c7 100644
--- a/system/hwc2/EmuHWC2.cpp
+++ b/system/hwc2/EmuHWC2.cpp
@@ -27,6 +27,8 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
 
 #include "../egl/goldfish_sync.h"
 
@@ -390,17 +392,27 @@
 }
 
 const native_handle_t* EmuHWC2::allocateDisplayColorBuffer() {
-    typedef CbManager::BufferUsage BufferUsage;
+    const uint32_t layerCount = 1;
+    const uint64_t graphicBufferId = 0; // not used
 
-    return mCbManager.allocateBuffer(
-        mDisplayWidth,
-        mDisplayHeight,
-        CbManager::PixelFormat::RGBA_8888,
-        (BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_RENDER_TARGET));
+    buffer_handle_t h;
+    uint32_t stride;
+
+    if (GraphicBufferAllocator::get().allocate(
+        mDisplayWidth, mDisplayHeight,
+        PIXEL_FORMAT_RGBA_8888,
+        layerCount,
+        (GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_RENDER),
+        &h, &stride,
+        graphicBufferId, "EmuHWC2") == OK) {
+        return static_cast<const native_handle_t*>(h);
+    } else {
+        return nullptr;
+    }
 }
 
 void EmuHWC2::freeDisplayColorBuffer(const native_handle_t* h) {
-    mCbManager.freeBuffer(h);
+    GraphicBufferAllocator::get().free(h);
 }
 
 // Display functions
@@ -1313,7 +1325,7 @@
 }
 
 HWC2::Error EmuHWC2::Display::populateSecondaryConfigs(uint32_t width, uint32_t height,
-        uint32_t dpi) {
+        uint32_t dpi, uint32_t idx) {
     ALOGVV("%s DisplayId %u, width %u, height %u, dpi %u",
             __FUNCTION__, (uint32_t)mId, width, height, dpi);
     std::unique_lock<std::mutex> lock(mStateMutex);
@@ -1336,14 +1348,19 @@
     mActiveColorMode = HAL_COLOR_MODE_NATIVE;
     mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
 
-    uint32_t displayId = 0;
+    uint32_t displayId = hostDisplayIdStart + idx;
     DEFINE_AND_VALIDATE_HOST_CONNECTION
 
     hostCon->lock();
+    rcEnc->rcDestroyDisplay(rcEnc, displayId);
     rcEnc->rcCreateDisplay(rcEnc, &displayId);
     rcEnc->rcSetDisplayPose(rcEnc, displayId, -1, -1, width, height);
     hostCon->unlock();
 
+    if (displayId != hostDisplayIdStart + idx) {
+        ALOGE("Something wrong with host displayId allocation, want %d "
+              "allocated %d", hostDisplayIdStart + idx, displayId);
+    }
     mHostDisplayId = displayId;
     ALOGVV("%s: mHostDisplayId=%d", __FUNCTION__, mHostDisplayId);
 
@@ -1666,6 +1683,7 @@
         ALOGE("%s: invalid value for system property: %s", __FUNCTION__, EXTERANL_DISPLAY_PROP);
         return -1;
     }
+    uint32_t idx = 0;
     while (!values.empty()) {
         // uint64_t physicalId = values[0];
         uint32_t width = values[1];
@@ -1676,7 +1694,7 @@
 
         Error ret = Error::None;
         auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
-        ret = display->populateSecondaryConfigs(width, height, dpi);
+        ret = display->populateSecondaryConfigs(width, height, dpi, idx++);
         if (ret != Error::None) {
             return -2;
         }
diff --git a/system/hwc2/EmuHWC2.h b/system/hwc2/EmuHWC2.h
index 8cb71c1..07218b6 100644
--- a/system/hwc2/EmuHWC2.h
+++ b/system/hwc2/EmuHWC2.h
@@ -24,8 +24,10 @@
 #undef HWC2_USE_CPP11
 #include <utils/Thread.h>
 
+#include <android-base/unique_fd.h>
 #include <atomic>
 #include <map>
+#include <memory>
 #include <mutex>
 #include <numeric>
 #include <sstream>
@@ -36,8 +38,6 @@
 
 #include <cutils/native_handle.h>
 
-#include "cbmanager.h"
-#include "MiniFence.h"
 #include "HostConnection.h"
 
 namespace android {
@@ -126,17 +126,19 @@
     // layer. This class is a container for these two.
     class FencedBuffer {
         public:
-            FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+            FencedBuffer() : mBuffer(nullptr) {}
 
             void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
-            void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+            void setFence(int fenceFd) {
+                mFence = std::make_shared<base::unique_fd>(fenceFd);
+            }
 
             buffer_handle_t getBuffer() const { return mBuffer; }
-            int getFence() const { return mFence->dup(); }
+            int getFence() const { return mFence ? dup(mFence->get()) : -1; }
 
         private:
             buffer_handle_t mBuffer;
-            sp<MiniFence> mFence;
+            std::shared_ptr<base::unique_fd> mFence;
     };
 
     typedef struct compose_layer {
@@ -258,7 +260,7 @@
         // Read configs from PRIMARY Display
         int populatePrimaryConfigs(int width, int height, int dpiX, int dpiY);
         HWC2::Error populateSecondaryConfigs(uint32_t width, uint32_t height,
-                 uint32_t dpi);
+                 uint32_t dpi, uint32_t idx);
 
     private:
         void post(HostConnection *hostCon, ExtendedRCEncoderContext *rcEnc,
@@ -344,6 +346,7 @@
         EmuHWC2& mDevice;
         // Display ID generator.
         static std::atomic<hwc2_display_t> sNextId;
+        static const uint32_t hostDisplayIdStart = 6;
         const hwc2_display_t mId;
         // emulator side displayId
         uint32_t mHostDisplayId;
@@ -467,7 +470,6 @@
     const native_handle_t* allocateDisplayColorBuffer();
     void freeDisplayColorBuffer(const native_handle_t* h);
 
-    CbManager mCbManager;
     std::unordered_set<HWC2::Capability> mCapabilities;
 
     // These are potentially accessed from multiple threads, and are protected
diff --git a/system/hwc2/MiniFence.cpp b/system/hwc2/MiniFence.cpp
deleted file mode 100644
index ecfb063..0000000
--- a/system/hwc2/MiniFence.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#include "MiniFence.h"
-
-#include <unistd.h>
-
-namespace android {
-
-const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
-
-MiniFence::MiniFence() :
-    mFenceFd(-1) {
-}
-
-MiniFence::MiniFence(int fenceFd) :
-    mFenceFd(fenceFd) {
-}
-
-MiniFence::~MiniFence() {
-    if (mFenceFd != -1) {
-        close(mFenceFd);
-    }
-}
-
-int MiniFence::dup() const {
-    return ::dup(mFenceFd);
-}
-}
diff --git a/system/hwc2/MiniFence.h b/system/hwc2/MiniFence.h
deleted file mode 100644
index 31c9536..0000000
--- a/system/hwc2/MiniFence.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef EMU_HWC2_MINIFENCE_H
-#define EMU_HWC2_MINIFENCE_H
-
-#include <utils/RefBase.h>
-
-namespace android {
-
-/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
- * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
- */
-class MiniFence : public LightRefBase<MiniFence> {
-public:
-    static const sp<MiniFence> NO_FENCE;
-
-    // Construct a new MiniFence object with an invalid file descriptor.
-    MiniFence();
-
-    // Construct a new MiniFence object to manage a given fence file descriptor.
-    // When the new MiniFence object is destructed the file descriptor will be
-    // closed.
-    explicit MiniFence(int fenceFd);
-
-    // Not copyable or movable.
-    MiniFence(const MiniFence& rhs) = delete;
-    MiniFence& operator=(const MiniFence& rhs) = delete;
-    MiniFence(MiniFence&& rhs) = delete;
-    MiniFence& operator=(MiniFence&& rhs) = delete;
-
-    // Return a duplicate of the fence file descriptor. The caller is
-    // responsible for closing the returned file descriptor. On error, -1 will
-    // be returned and errno will indicate the problem.
-    int dup() const;
-
-private:
-    // Only allow instantiation using ref counting.
-    friend class LightRefBase<MiniFence>;
-    ~MiniFence();
-
-    int mFenceFd;
-
-};
-}
-#endif //EMU_HWC2_MINIFENCE_H
diff --git a/system/include/cbmanager.h b/system/include/cbmanager.h
deleted file mode 100644
index 4bddedb..0000000
--- a/system/include/cbmanager.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_CBMANAGER_H
-#define ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_CBMANAGER_H
-
-#include <cutils/native_handle.h>
-#include <log/log.h>
-
-#include <memory>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-#include "gralloc_cb.h"
-
-namespace android {
-
-class CbManager {
-public:
-    typedef hardware::graphics::common::V1_0::BufferUsage BufferUsage;
-    typedef hardware::graphics::common::V1_0::PixelFormat PixelFormat;
-    typedef hardware::graphics::mapper::V2_0::YCbCrLayout YCbCrLayout;
-    typedef hardware::hidl_bitfield<BufferUsage> BufferUsageBits;
-
-    CbManager();
-
-    class CbManagerImpl {
-    public:
-        virtual ~CbManagerImpl() {}
-        virtual native_handle_t* allocateBuffer(int width,
-                                                int height,
-                                                PixelFormat format,
-                                                BufferUsageBits usage) = 0;
-        virtual void freeBuffer(const native_handle_t* h) = 0;
-
-        virtual int lockBuffer(native_handle_t& handle,
-             BufferUsageBits usage,
-             int left, int top, int width, int height,
-             void** vaddr) = 0;
-
-        virtual int lockYCbCrBuffer(native_handle_t& handle,
-             BufferUsageBits usage,
-             int left, int top, int width, int height,
-             YCbCrLayout* ycbcr) = 0;
-
-        virtual int unlockBuffer(native_handle_t& handle) = 0;
-    };
-
-    native_handle_t* allocateBuffer(
-        int width, int height, PixelFormat format, BufferUsageBits usage) {
-        return mImpl->allocateBuffer(width, height, format, usage);
-    }
-
-    void freeBuffer(const native_handle_t* h) {
-        mImpl->freeBuffer(h);
-    }
-
-    int lockBuffer(native_handle_t& handle,
-             BufferUsageBits usage,
-             int left, int top, int width, int height,
-             void** vaddr) {
-        return mImpl->lockBuffer(handle, usage, left, top, width, height, vaddr);
-    }
-
-    int lockBuffer(buffer_handle_t h,
-             BufferUsageBits usage,
-             int left, int top, int width, int height,
-             void** vaddr) {
-        native_handle_t* cb = const_cast<native_handle_t*>(h);
-        if (cb) {
-            return lockBuffer(*cb, usage, left, top, width, height, vaddr);
-        } else {
-            return -1;
-        }
-    }
-
-
-    int lockYCbCrBuffer(native_handle_t& handle,
-                        BufferUsageBits usage,
-                        int left, int top, int width, int height,
-                        YCbCrLayout* ycbcr) {
-        return mImpl->lockYCbCrBuffer(handle, usage, left, top, width, height, ycbcr);
-    }
-
-    int lockYCbCrBuffer(buffer_handle_t h,
-                        BufferUsageBits usage,
-                        int left, int top, int width, int height,
-                        YCbCrLayout* ycbcr) {
-        native_handle_t* cb = const_cast<native_handle_t*>(h);
-        if (cb) {
-            return lockYCbCrBuffer(*cb, usage, left, top, width, height, ycbcr);
-        } else {
-            return -1;
-        }
-    }
-
-    int unlockBuffer(native_handle_t& handle) {
-        return mImpl->unlockBuffer(handle);
-    }
-
-    int unlockBuffer(buffer_handle_t h) {
-        native_handle_t* cb = const_cast<native_handle_t*>(h);
-        if (cb) {
-            return unlockBuffer(*cb);
-        } else {
-            return -1;
-        }
-    }
-
-    // Specific to goldfish, for obtaining offsets
-    // into host coherent memory
-    // (requires address space devce)
-    static uint64_t getOffset(const buffer_handle_t h) {
-        const cb_handle_t* cb = cb_handle_t::from(h);
-        if (!cb->isValid()) {
-            ALOGE("%s: FATAL: using incompatible native_handle_t for "
-                  "host coherent mapping offset",
-                  __func__);
-            abort();
-        }
-        return cb ? cb->getMmapedOffset() : -1;
-    }
-
-private:
-    std::unique_ptr<CbManagerImpl> mImpl;
-};
-
-}  // namespace android
-
-#endif  // ANDROID_GOLDFISH_OPENGL_SYSTEM_CBMANAGER_CBMANAGER_H
diff --git a/system/renderControl_enc/CMakeLists.txt b/system/renderControl_enc/CMakeLists.txt
index c874e25..8a42acb 100644
--- a/system/renderControl_enc/CMakeLists.txt
+++ b/system/renderControl_enc/CMakeLists.txt
@@ -4,7 +4,7 @@
 android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc/Android.mk" "780a007ac7a3d2255372ddf40e03aeb10e4c759343d2532f6ddf769f4df73810")
 set(_renderControl_enc_src renderControl_client_context.cpp renderControl_enc.cpp renderControl_entry.cpp)
 android_add_library(TARGET _renderControl_enc SHARED LICENSE Apache-2.0 SRC renderControl_client_context.cpp renderControl_enc.cpp renderControl_entry.cpp)
-target_include_directories(_renderControl_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
+target_include_directories(_renderControl_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
 target_compile_definitions(_renderControl_enc PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN")
 target_compile_options(_renderControl_enc PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-unused-function")
-target_link_libraries(_renderControl_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared)
\ No newline at end of file
+target_link_libraries(_renderControl_enc PRIVATE OpenglCodecCommon_host cutils utils log android-emu-shared PRIVATE qemupipe_host)
\ No newline at end of file
diff --git a/system/vulkan/Android.mk b/system/vulkan/Android.mk
index ebaa3c0..2bec494 100644
--- a/system/vulkan/Android.mk
+++ b/system/vulkan/Android.mk
@@ -17,7 +17,7 @@
 
 # Only import androidemu if not building for host.
 # if building for host, we already import android-emu.
-$(call emugl-import,libandroidemu)
+$(call emugl-export,SHARED_LIBRARIES,libandroidemu)
 
 LOCAL_HEADER_LIBRARIES += \
     hwvulkan_headers \
diff --git a/system/vulkan/CMakeLists.txt b/system/vulkan/CMakeLists.txt
index a71c07f..65bc00a 100644
--- a/system/vulkan/CMakeLists.txt
+++ b/system/vulkan/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan/Android.mk" "691427017f29de6b082ad25cb73b87443d4072a04b4316897bb92983674ad5bf")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan/Android.mk" "5cb873c72cc859fac3800961059c1b203ed1abb400ee643178c18e04961d49e8")
 set(vulkan.ranchu_src func_table.cpp goldfish_vulkan.cpp)
 android_add_library(TARGET vulkan.ranchu SHARED LICENSE Apache-2.0 SRC func_table.cpp goldfish_vulkan.cpp)
-target_include_directories(vulkan.ranchu PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/vulkan ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include)
+target_include_directories(vulkan.ranchu PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon/bionic-include ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/bionic/libc/platform ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/gralloc_cb/include ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/system/vulkan ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include)
 target_compile_definitions(vulkan.ranchu PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"goldfish_vulkan\"" "-DVK_USE_PLATFORM_ANDROID_KHR" "-DVK_NO_PROTOTYPES")
 target_compile_options(vulkan.ranchu PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-missing-field-initializers" "-fvisibility=hidden" "-fstrict-aliasing" "-Wno-unused-function")
-target_link_libraries(vulkan.ranchu PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host)
\ No newline at end of file
+target_link_libraries(vulkan.ranchu PRIVATE OpenglSystemCommon android-emu-shared vulkan_enc gui androidemu cutils utils log _renderControl_enc GLESv2_enc GLESv1_enc OpenglCodecCommon_host PRIVATE gralloc_cb_host GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 80f586f..721e7c5 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -845,7 +845,8 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorSetLayout");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateDescriptorSetLayout_VkResult_return = (VkResult)0;
-    vkCreateDescriptorSetLayout_VkResult_return = vkEnc->vkCreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+    auto resources = ResourceTracker::get();
+    vkCreateDescriptorSetLayout_VkResult_return = resources->on_vkCreateDescriptorSetLayout(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pSetLayout);
     return vkCreateDescriptorSetLayout_VkResult_return;
 }
 static void entry_vkDestroyDescriptorSetLayout(
@@ -866,7 +867,8 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorPool");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkCreateDescriptorPool_VkResult_return = (VkResult)0;
-    vkCreateDescriptorPool_VkResult_return = vkEnc->vkCreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
+    auto resources = ResourceTracker::get();
+    vkCreateDescriptorPool_VkResult_return = resources->on_vkCreateDescriptorPool(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pDescriptorPool);
     return vkCreateDescriptorPool_VkResult_return;
 }
 static void entry_vkDestroyDescriptorPool(
@@ -876,7 +878,8 @@
 {
     AEMU_SCOPED_TRACE("vkDestroyDescriptorPool");
     auto vkEnc = HostConnection::get()->vkEncoder();
-    vkEnc->vkDestroyDescriptorPool(device, descriptorPool, pAllocator);
+    auto resources = ResourceTracker::get();
+    resources->on_vkDestroyDescriptorPool(vkEnc, device, descriptorPool, pAllocator);
 }
 static VkResult entry_vkResetDescriptorPool(
     VkDevice device,
@@ -886,7 +889,8 @@
     AEMU_SCOPED_TRACE("vkResetDescriptorPool");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkResetDescriptorPool_VkResult_return = (VkResult)0;
-    vkResetDescriptorPool_VkResult_return = vkEnc->vkResetDescriptorPool(device, descriptorPool, flags);
+    auto resources = ResourceTracker::get();
+    vkResetDescriptorPool_VkResult_return = resources->on_vkResetDescriptorPool(vkEnc, VK_SUCCESS, device, descriptorPool, flags);
     return vkResetDescriptorPool_VkResult_return;
 }
 static VkResult entry_vkAllocateDescriptorSets(
@@ -897,7 +901,8 @@
     AEMU_SCOPED_TRACE("vkAllocateDescriptorSets");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkAllocateDescriptorSets_VkResult_return = (VkResult)0;
-    vkAllocateDescriptorSets_VkResult_return = vkEnc->vkAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+    auto resources = ResourceTracker::get();
+    vkAllocateDescriptorSets_VkResult_return = resources->on_vkAllocateDescriptorSets(vkEnc, VK_SUCCESS, device, pAllocateInfo, pDescriptorSets);
     return vkAllocateDescriptorSets_VkResult_return;
 }
 static VkResult entry_vkFreeDescriptorSets(
@@ -909,7 +914,8 @@
     AEMU_SCOPED_TRACE("vkFreeDescriptorSets");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkFreeDescriptorSets_VkResult_return = (VkResult)0;
-    vkFreeDescriptorSets_VkResult_return = vkEnc->vkFreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+    auto resources = ResourceTracker::get();
+    vkFreeDescriptorSets_VkResult_return = resources->on_vkFreeDescriptorSets(vkEnc, VK_SUCCESS, device, descriptorPool, descriptorSetCount, pDescriptorSets);
     return vkFreeDescriptorSets_VkResult_return;
 }
 static void entry_vkUpdateDescriptorSets(
@@ -921,7 +927,8 @@
 {
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets");
     auto vkEnc = HostConnection::get()->vkEncoder();
-    vkEnc->vkUpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+    auto resources = ResourceTracker::get();
+    resources->on_vkUpdateDescriptorSets(vkEnc, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
 }
 static VkResult entry_vkCreateFramebuffer(
     VkDevice device,
@@ -5249,6 +5256,35 @@
     return vkGetMemoryHostAddressInfoGOOGLE_VkResult_return;
 }
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+static VkResult entry_vkFreeMemorySyncGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    const VkAllocationCallbacks* pAllocator)
+{
+    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkFreeMemorySyncGOOGLE_VkResult_return = (VkResult)0;
+    vkFreeMemorySyncGOOGLE_VkResult_return = vkEnc->vkFreeMemorySyncGOOGLE(device, memory, pAllocator);
+    return vkFreeMemorySyncGOOGLE_VkResult_return;
+}
+static VkResult dynCheck_entry_vkFreeMemorySyncGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    const VkAllocationCallbacks* pAllocator)
+{
+    auto resources = ResourceTracker::get();
+    if (!resources->hasDeviceExtension(device, "VK_GOOGLE_free_memory_sync"))
+    {
+        sOnInvalidDynamicallyCheckedCall("vkFreeMemorySyncGOOGLE", "VK_GOOGLE_free_memory_sync");
+    }
+    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkFreeMemorySyncGOOGLE_VkResult_return = (VkResult)0;
+    vkFreeMemorySyncGOOGLE_VkResult_return = vkEnc->vkFreeMemorySyncGOOGLE(device, memory, pAllocator);
+    return vkFreeMemorySyncGOOGLE_VkResult_return;
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -6700,6 +6736,12 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+    if (!strcmp(name, "vkFreeMemorySyncGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -8248,6 +8290,12 @@
         return (void*)dynCheck_entry_vkGetMemoryHostAddressInfoGOOGLE;
     }
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+    if (!strcmp(name, "vkFreeMemorySyncGOOGLE"))
+    {
+        return (void*)dynCheck_entry_vkFreeMemorySyncGOOGLE;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -9866,6 +9914,13 @@
         return hasExt ? (void*)entry_vkGetMemoryHostAddressInfoGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+    if (!strcmp(name, "vkFreeMemorySyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_free_memory_sync");
+        return hasExt ? (void*)entry_vkFreeMemorySyncGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 91ffd65..c0d4224 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -288,6 +288,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name);
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name);
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name);
diff --git a/system/vulkan_enc/Android.mk b/system/vulkan_enc/Android.mk
index 984db7f..e49aac4 100644
--- a/system/vulkan_enc/Android.mk
+++ b/system/vulkan_enc/Android.mk
@@ -1,18 +1,15 @@
-
-# Autogenerated makefile
-# android/android-emugl/host/libs/libOpenglRender/vulkan-registry/xml/genvk.py -registry android/android-emugl/host/libs/libOpenglRender/vulkan-registry/xml/vk.xml cereal -o android/android-emugl/host/libs/libOpenglRender/vulkan/cereal
-# Please do not modify directly;
-# re-run android/scripts/generate-vulkan-sources.sh,
-# or directly from Python by defining:
-# VULKAN_REGISTRY_XML_DIR : Directory containing genvk.py and vk.xml
-# CEREAL_OUTPUT_DIR: Where to put the generated sources.
-# python3 $VULKAN_REGISTRY_XML_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
-
 LOCAL_PATH := $(call my-dir)
 
 $(call emugl-begin-shared-library,libvulkan_enc)
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH))
-$(call emugl-import,libOpenglCodecCommon$(GOLDFISH_OPENGL_LIB_SUFFIX) libandroidemu lib_renderControl_enc)
+$(call emugl-import,libOpenglCodecCommon$(GOLDFISH_OPENGL_LIB_SUFFIX) lib_renderControl_enc)
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-import,libandroidemu)
+$(call emugl-import,libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX))
+else
+$(call emugl-export,SHARED_LIBRARIES,libandroidemu)
+$(call emugl-export,STATIC_LIBRARIES,libGoldfishAddressSpace)
+endif
 
 # Vulkan include dir
 ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
@@ -55,12 +52,11 @@
     VulkanHandleMapping.cpp \
     ResourceTracker.cpp \
     VkEncoder.cpp \
-goldfish_vk_extension_structs_guest.cpp \
-goldfish_vk_marshaling_guest.cpp \
-goldfish_vk_deepcopy_guest.cpp \
-goldfish_vk_handlemap_guest.cpp \
-goldfish_vk_transform_guest.cpp \
-
+    goldfish_vk_extension_structs_guest.cpp \
+    goldfish_vk_marshaling_guest.cpp \
+    goldfish_vk_deepcopy_guest.cpp \
+    goldfish_vk_handlemap_guest.cpp \
+    goldfish_vk_transform_guest.cpp \
 
 ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
 LOCAL_CFLAGS += -D__ANDROID_API__=28
diff --git a/system/vulkan_enc/CMakeLists.txt b/system/vulkan_enc/CMakeLists.txt
index dec0c66..5b97015 100644
--- a/system/vulkan_enc/CMakeLists.txt
+++ b/system/vulkan_enc/CMakeLists.txt
@@ -1,10 +1,10 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "a4b1fb11cf3e68cc49f055258b6b590798eeecb2d3e6e565c78549a39a341911")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "103f3f10c8af73d3d5c4263c4faa5bb70ebdbfbc9ed6f068a338d57344e2aa45")
 set(vulkan_enc_src AndroidHardwareBuffer.cpp HostVisibleMemoryVirtualization.cpp Resources.cpp Validation.cpp VulkanStreamGuest.cpp VulkanHandleMapping.cpp ResourceTracker.cpp VkEncoder.cpp goldfish_vk_extension_structs_guest.cpp goldfish_vk_marshaling_guest.cpp goldfish_vk_deepcopy_guest.cpp goldfish_vk_handlemap_guest.cpp goldfish_vk_transform_guest.cpp)
 android_add_library(TARGET vulkan_enc SHARED LICENSE Apache-2.0 SRC AndroidHardwareBuffer.cpp HostVisibleMemoryVirtualization.cpp Resources.cpp Validation.cpp VulkanStreamGuest.cpp VulkanHandleMapping.cpp ResourceTracker.cpp VkEncoder.cpp goldfish_vk_extension_structs_guest.cpp goldfish_vk_marshaling_guest.cpp goldfish_vk_deepcopy_guest.cpp goldfish_vk_handlemap_guest.cpp goldfish_vk_transform_guest.cpp)
-target_include_directories(vulkan_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include/vulkan)
+target_include_directories(vulkan_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/shared/GoldfishAddressSpace/include ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include-types ${GOLDFISH_DEVICE_ROOT}/shared/qemupipe/include ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include/vulkan)
 target_compile_definitions(vulkan_enc PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"goldfish_vulkan\"" "-DVK_ANDROID_native_buffer" "-DVK_GOOGLE_address_space" "-DVK_USE_PLATFORM_ANDROID_KHR" "-DVK_NO_PROTOTYPES" "-D__ANDROID_API__=28")
 target_compile_options(vulkan_enc PRIVATE "-fvisibility=default" "-Wno-unused-parameter" "-Wno-missing-field-initializers" "-Werror" "-fstrict-aliasing")
-target_link_libraries(vulkan_enc PRIVATE gui _renderControl_enc androidemu cutils utils log OpenglCodecCommon_host android-emu-shared)
\ No newline at end of file
+target_link_libraries(vulkan_enc PRIVATE gui log android-emu-shared androidemu cutils utils _renderControl_enc OpenglCodecCommon_host PRIVATE GoldfishAddressSpace_host qemupipe_host)
\ No newline at end of file
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
index 2db7e6a..a5b02f8 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
@@ -162,7 +162,8 @@
             // Was the original memory type also a device local type? If so,
             // advertise both types in resulting type bits.
             info_out->memoryTypeBitsShouldAdvertiseBoth[i] =
-                type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+                type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ||
+                type.propertyFlags == 0;
 
             ++firstFreeTypeIndex;
 
@@ -204,16 +205,6 @@
     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,
@@ -234,7 +225,12 @@
     // because it's not just nonCoherentAtomSize granularity,
     // people will also use it for uniform buffers, images, etc.
     // that need some bigger alignment
-#define HIGHEST_BUFFER_OR_IMAGE_ALIGNMENT 1024
+// #define HIGHEST_BUFFER_OR_IMAGE_ALIGNMENT 1024
+// bug: 145153816
+// HACK: Make it 65k so yuv images are happy on vk cts 1.2.1
+// TODO: Use a munmap/mmap MAP_FIXED scheme to realign memories
+// if it's found that the buffer or image bind alignment will be violated
+#define HIGHEST_BUFFER_OR_IMAGE_ALIGNMENT 65536
 
     uint64_t neededPageSize = out->nonCoherentAtomSize;
     if (HIGHEST_BUFFER_OR_IMAGE_ALIGNMENT >
@@ -254,6 +250,7 @@
 }
 
 void destroyHostMemAlloc(
+    bool freeMemorySyncSupported,
     VkEncoder* enc,
     VkDevice device,
     HostMemAlloc* toDestroy) {
@@ -261,7 +258,12 @@
     if (toDestroy->initResult != VK_SUCCESS) return;
     if (!toDestroy->initialized) return;
 
-    enc->vkFreeMemory(device, toDestroy->memory, nullptr);
+    if (freeMemorySyncSupported) {
+        enc->vkFreeMemorySyncGOOGLE(device, toDestroy->memory, nullptr);
+    } else {
+        enc->vkFreeMemory(device, toDestroy->memory, nullptr);
+    }
+
     delete toDestroy->subAlloc;
 }
 
@@ -307,4 +309,15 @@
     return true;
 }
 
+bool isNoFlagsMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index) {
+    const auto& props =
+        info->virtualizationSupported ?
+        info->guestMemoryProperties :
+        info->hostMemoryProperties;
+    return props.memoryTypes[index].propertyFlags == 0;
+}
+
+
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.h b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
index 305dca2..e190a1e 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.h
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
@@ -72,10 +72,6 @@
     const HostVisibleMemoryVirtualizationInfo* info,
     uint32_t index);
 
-bool isNoFlagsMemoryTypeIndexForGuest(
-    const HostVisibleMemoryVirtualizationInfo* info,
-    uint32_t index);
-
 struct HostMemAlloc {
     bool initialized = false;
     VkResult initResult = VK_SUCCESS;
@@ -100,6 +96,7 @@
     HostMemAlloc* out);
 
 void destroyHostMemAlloc(
+    bool freeMemorySyncSupported,
     VkEncoder* enc,
     VkDevice device,
     HostMemAlloc* toDestroy);
@@ -123,4 +120,9 @@
 void subFreeHostMemory(SubAlloc* toFree);
 
 bool canSubAlloc(android::base::guest::SubAllocator* subAlloc, VkDeviceSize size);
+
+bool isNoFlagsMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index);
+
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 809732c..8bd4b20 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -115,9 +115,10 @@
 #include "vk_format_info.h"
 #include "vk_util.h"
 
+#include <set>
 #include <string>
 #include <unordered_map>
-#include <set>
+#include <unordered_set>
 
 #include <vndk/hardware_buffer.h>
 #include <log/log.h>
@@ -327,6 +328,20 @@
 #endif
     };
 
+    struct VkDescriptorPool_Info {
+        std::unordered_set<VkDescriptorSet> allocedSets;
+        VkDescriptorPoolCreateFlags createFlags;
+    };
+
+    struct VkDescriptorSet_Info {
+        VkDescriptorPool pool;
+        std::vector<bool> bindingIsImmutableSampler;
+    };
+
+    struct VkDescriptorSetLayout_Info {
+        std::vector<VkDescriptorSetLayoutBinding> bindings;
+    };
+
 #define HANDLE_REGISTER_IMPL_IMPL(type) \
     std::unordered_map<type, type##_Info> info_##type; \
     void register_##type(type obj) { \
@@ -468,9 +483,158 @@
         info_VkFence.erase(fence);
     }
 
-    // TODO: Upgrade to 1.1
-    static constexpr uint32_t kMaxApiVersion = VK_MAKE_VERSION(1, 1, 0);
-    static constexpr uint32_t kMinApiVersion = VK_MAKE_VERSION(1, 0, 0);
+    void unregister_VkDescriptorSet_locked(VkDescriptorSet set) {
+        auto it = info_VkDescriptorSet.find(set);
+        if (it == info_VkDescriptorSet.end()) return;
+
+        const auto& setInfo = it->second;
+
+        auto poolIt = info_VkDescriptorPool.find(setInfo.pool);
+
+        info_VkDescriptorSet.erase(set);
+
+        if (poolIt == info_VkDescriptorPool.end()) return;
+
+        auto& poolInfo = poolIt->second;
+        poolInfo.allocedSets.erase(set);
+    }
+
+    void unregister_VkDescriptorSet(VkDescriptorSet set) {
+        AutoLock lock(mLock);
+        unregister_VkDescriptorSet_locked(set);
+    }
+
+    void unregister_VkDescriptorSetLayout(VkDescriptorSetLayout setLayout) {
+        AutoLock lock(mLock);
+        info_VkDescriptorSetLayout.erase(setLayout);
+    }
+
+    void initDescriptorSetStateLocked(const VkDescriptorSetAllocateInfo* ci, const VkDescriptorSet* sets) {
+        auto it = info_VkDescriptorPool.find(ci->descriptorPool);
+        if (it == info_VkDescriptorPool.end()) return;
+
+        auto& info = it->second;
+        for (uint32_t i = 0; i < ci->descriptorSetCount; ++i) {
+            info.allocedSets.insert(sets[i]);
+
+            auto setIt = info_VkDescriptorSet.find(sets[i]);
+            if (setIt == info_VkDescriptorSet.end()) continue;
+
+            auto& setInfo = setIt->second;
+            setInfo.pool = ci->descriptorPool;
+
+            VkDescriptorSetLayout setLayout = ci->pSetLayouts[i];
+            auto layoutIt = info_VkDescriptorSetLayout.find(setLayout);
+            if (layoutIt == info_VkDescriptorSetLayout.end()) continue;
+
+            const auto& layoutInfo = layoutIt->second;
+            for (size_t i = 0; i < layoutInfo.bindings.size(); ++i) {
+                // Bindings can be sparsely defined
+                const auto& binding = layoutInfo.bindings[i];
+                uint32_t bindingIndex = binding.binding;
+                if (setInfo.bindingIsImmutableSampler.size() <= bindingIndex) {
+                    setInfo.bindingIsImmutableSampler.resize(bindingIndex + 1, false);
+                }
+                setInfo.bindingIsImmutableSampler[bindingIndex] =
+                    binding.descriptorCount > 0 &&
+                     (binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
+                      binding.descriptorType ==
+                          VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
+                    binding.pImmutableSamplers;
+            }
+        }
+    }
+
+    VkWriteDescriptorSet
+    createImmutableSamplersFilteredWriteDescriptorSetLocked(
+        const VkWriteDescriptorSet* descriptorWrite,
+        std::vector<VkDescriptorImageInfo>* imageInfoArray) {
+
+        VkWriteDescriptorSet res = *descriptorWrite;
+
+        if  (descriptorWrite->descriptorCount == 0) return res;
+
+        if  (descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER &&
+             descriptorWrite->descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) return res;
+
+        VkDescriptorSet set = descriptorWrite->dstSet;
+        auto descSetIt = info_VkDescriptorSet.find(set);
+        if (descSetIt == info_VkDescriptorSet.end()) {
+            ALOGE("%s: error: descriptor set 0x%llx not found\n", __func__,
+                  (unsigned long long)set);
+            return res;
+        }
+
+        const auto& descInfo = descSetIt->second;
+        uint32_t binding = descriptorWrite->dstBinding;
+
+        bool immutableSampler = descInfo.bindingIsImmutableSampler[binding];
+
+        if (!immutableSampler) return res;
+
+        for (uint32_t i = 0; i < descriptorWrite->descriptorCount; ++i) {
+            VkDescriptorImageInfo imageInfo = descriptorWrite->pImageInfo[i];
+            imageInfo.sampler = 0;
+            imageInfoArray->push_back(imageInfo);
+        }
+
+        res.pImageInfo = imageInfoArray->data();
+
+        return res;
+    }
+
+    // Also unregisters underlying descriptor sets
+    // and deletes their guest-side wrapped handles.
+    void clearDescriptorPoolLocked(VkDescriptorPool pool) {
+        auto it = info_VkDescriptorPool.find(pool);
+        if (it == info_VkDescriptorPool.end()) return;
+
+        std::vector<VkDescriptorSet> toClear;
+        for (auto set : it->second.allocedSets) {
+            toClear.push_back(set);
+        }
+
+        for (auto set : toClear) {
+            unregister_VkDescriptorSet_locked(set);
+            delete_goldfish_VkDescriptorSet(set);
+        }
+    }
+
+    void unregister_VkDescriptorPool(VkDescriptorPool pool) {
+        AutoLock lock(mLock);
+        clearDescriptorPoolLocked(pool);
+        info_VkDescriptorPool.erase(pool);
+    }
+
+    bool descriptorPoolSupportsIndividualFreeLocked(VkDescriptorPool pool) {
+        auto it = info_VkDescriptorPool.find(pool);
+        if (it == info_VkDescriptorPool.end()) return false;
+
+        const auto& info = it->second;
+
+        return VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT &
+            info.createFlags;
+    }
+
+    bool descriptorSetReallyAllocedFromPoolLocked(VkDescriptorSet set, VkDescriptorPool pool) {
+        auto it = info_VkDescriptorSet.find(set);
+        if (it == info_VkDescriptorSet.end()) return false;
+
+        const auto& info = it->second;
+
+        if (pool != info.pool) return false;
+
+        auto poolIt = info_VkDescriptorPool.find(info.pool);
+        if (poolIt == info_VkDescriptorPool.end()) return false;
+
+        const auto& poolInfo = poolIt->second;
+
+        if (poolInfo.allocedSets.find(set) == poolInfo.allocedSets.end()) return false;
+
+        return true;
+    }
+
+    static constexpr uint32_t kDefaultApiVersion = VK_MAKE_VERSION(1, 1, 0);
 
     void setInstanceInfo(VkInstance instance,
                          uint32_t enabledExtensionCount,
@@ -883,9 +1047,11 @@
             return VK_SUCCESS;
         } else {
             auto actualExtensionCount = (uint32_t)filteredExts.size();
-            auto toWrite = actualExtensionCount < *pPropertyCount ? actualExtensionCount : *pPropertyCount;
+            if (*pPropertyCount > actualExtensionCount) {
+              *pPropertyCount = actualExtensionCount;
+            }
 
-            for (uint32_t i = 0; i < toWrite; ++i) {
+            for (uint32_t i = 0; i < *pPropertyCount; ++i) {
                 pProperties[i] = filteredExts[i];
             }
 
@@ -1051,9 +1217,11 @@
             return VK_SUCCESS;
         } else {
             auto actualExtensionCount = (uint32_t)filteredExts.size();
-            auto toWrite = actualExtensionCount < *pPropertyCount ? actualExtensionCount : *pPropertyCount;
+            if (*pPropertyCount > actualExtensionCount) {
+              *pPropertyCount = actualExtensionCount;
+            }
 
-            for (uint32_t i = 0; i < toWrite; ++i) {
+            for (uint32_t i = 0; i < *pPropertyCount; ++i) {
                 pProperties[i] = filteredExts[i];
             }
 
@@ -1252,9 +1420,13 @@
 
         VkEncoder* enc = (VkEncoder*)context;
 
+        bool freeMemorySyncSupported =
+            mFeatureInfo->hasVulkanFreeMemorySync;
         for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
             for (auto& block : info.hostMemBlocks[i]) {
-                destroyHostMemAlloc(enc, device, &block);
+                destroyHostMemAlloc(
+                    freeMemorySyncSupported,
+                    enc, device, &block);
             }
         }
     }
@@ -1673,14 +1845,14 @@
                         (unsigned long long)hvaSizeId[2]);
                 mLock.lock();
 
-                struct drm_virtgpu_resource_create_v2 drm_rc_v2 = { 0 };
-                drm_rc_v2.args = (uint64_t)&hvaSizeId[2];
-                drm_rc_v2.args_size = sizeof(uint64_t);
-                drm_rc_v2.size = hvaSizeId[1];
-                drm_rc_v2.flags = VIRTGPU_RESOURCE_TYPE_HOST;
+                struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
+                drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST;
+                drm_rc_blob.blob_flags = VIRTGPU_BLOB_FLAG_MAPPABLE;
+                drm_rc_blob.blob_id = hvaSizeId[2];
+                drm_rc_blob.size = hvaSizeId[1];
 
                 int res = drmIoctl(
-                    mRendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_V2, &drm_rc_v2);
+                    mRendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
 
                 if (res) {
                     ALOGE("%s: Failed to resource create v2: sterror: %s errno: %d\n", __func__,
@@ -1689,7 +1861,7 @@
                 }
 
                 struct drm_virtgpu_map map_info = {
-                    .handle = drm_rc_v2.bo_handle,
+                    .handle = drm_rc_blob.bo_handle,
                 };
 
                 res = drmIoctl(mRendernodeFd, DRM_IOCTL_VIRTGPU_MAP, &map_info);
@@ -2229,8 +2401,6 @@
         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);
             }
@@ -2242,8 +2412,6 @@
         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)) {
@@ -2607,7 +2775,7 @@
         VkSamplerCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo);
         vk_struct_chain_iterator structChainIter = vk_make_chain_iterator(&localCreateInfo);
 
-#ifdef VK_USE_PLATFORM_ANDROID_KHR
+#if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(VK_USE_PLATFORM_FUCHSIA_KHR)
         VkSamplerYcbcrConversionInfo localVkSamplerYcbcrConversionInfo;
         const VkSamplerYcbcrConversionInfo* samplerYcbcrConversionInfo =
             vk_find_struct<VkSamplerYcbcrConversionInfo>(pCreateInfo);
@@ -2981,6 +3149,173 @@
 #endif
     }
 
+    VkResult on_vkCreateDescriptorPool(
+        void* context,
+        VkResult,
+        VkDevice device,
+        const VkDescriptorPoolCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorPool* pDescriptorPool) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        VkResult res = enc->vkCreateDescriptorPool(
+            device, pCreateInfo, pAllocator, pDescriptorPool);
+
+        if (res != VK_SUCCESS) return res;
+
+        AutoLock lock(mLock);
+        auto it = info_VkDescriptorPool.find(*pDescriptorPool);
+        if (it == info_VkDescriptorPool.end()) return res;
+
+        auto &info = it->second;
+        info.createFlags = pCreateInfo->flags;
+
+        return res;
+    }
+
+    void on_vkDestroyDescriptorPool(
+        void* context,
+        VkDevice device,
+        VkDescriptorPool descriptorPool,
+        const VkAllocationCallbacks* pAllocator) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        enc->vkDestroyDescriptorPool(device, descriptorPool, pAllocator);
+    }
+
+    VkResult on_vkResetDescriptorPool(
+        void* context,
+        VkResult,
+        VkDevice device,
+        VkDescriptorPool descriptorPool,
+        VkDescriptorPoolResetFlags flags) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        VkResult res = enc->vkResetDescriptorPool(device, descriptorPool, flags);
+
+        if (res != VK_SUCCESS) return res;
+
+        AutoLock lock(mLock);
+        clearDescriptorPoolLocked(descriptorPool);
+        return res;
+    }
+
+    VkResult on_vkAllocateDescriptorSets(
+        void* context,
+        VkResult,
+        VkDevice                                    device,
+        const VkDescriptorSetAllocateInfo*          pAllocateInfo,
+        VkDescriptorSet*                            pDescriptorSets) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        VkResult res = enc->vkAllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+
+        if (res != VK_SUCCESS) return res;
+
+        AutoLock lock(mLock);
+        initDescriptorSetStateLocked(pAllocateInfo, pDescriptorSets);
+        return res;
+    }
+
+    VkResult on_vkFreeDescriptorSets(
+        void* context,
+        VkResult,
+        VkDevice                                    device,
+        VkDescriptorPool                            descriptorPool,
+        uint32_t                                    descriptorSetCount,
+        const VkDescriptorSet*                      pDescriptorSets) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        // Bit of robustness so that we can double free descriptor sets
+        // and do other invalid usages
+        // https://github.com/KhronosGroup/Vulkan-Docs/issues/1070
+        // (people expect VK_SUCCESS to always be returned by vkFreeDescriptorSets)
+        std::vector<VkDescriptorSet> toActuallyFree;
+        {
+            AutoLock lock(mLock);
+
+            if (!descriptorPoolSupportsIndividualFreeLocked(descriptorPool))
+                return VK_SUCCESS;
+
+            for (uint32_t i = 0; i < descriptorSetCount; ++i) {
+                if (descriptorSetReallyAllocedFromPoolLocked(
+                        pDescriptorSets[i], descriptorPool)) {
+                    toActuallyFree.push_back(pDescriptorSets[i]);
+                }
+            }
+
+            if (toActuallyFree.empty()) return VK_SUCCESS;
+        }
+
+        return enc->vkFreeDescriptorSets(
+            device, descriptorPool,
+            (uint32_t)toActuallyFree.size(),
+            toActuallyFree.data());
+    }
+
+    VkResult on_vkCreateDescriptorSetLayout(
+        void* context,
+        VkResult,
+        VkDevice device,
+        const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorSetLayout* pSetLayout) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        VkResult res = enc->vkCreateDescriptorSetLayout(
+            device, pCreateInfo, pAllocator, pSetLayout);
+
+        if (res != VK_SUCCESS) return res;
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkDescriptorSetLayout.find(*pSetLayout);
+        if (it == info_VkDescriptorSetLayout.end()) return res;
+
+        auto& info = it->second;
+        for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i) {
+            info.bindings.push_back(pCreateInfo->pBindings[i]);
+        }
+
+        return res;
+    }
+
+    void on_vkUpdateDescriptorSets(
+        void* context,
+        VkDevice device,
+        uint32_t descriptorWriteCount,
+        const VkWriteDescriptorSet* pDescriptorWrites,
+        uint32_t descriptorCopyCount,
+        const VkCopyDescriptorSet* pDescriptorCopies) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+
+        std::vector<std::vector<VkDescriptorImageInfo>> imageInfosPerWrite(
+            descriptorWriteCount);
+
+        std::vector<VkWriteDescriptorSet> writesWithSuppressedSamplers;
+
+        {
+            AutoLock lock(mLock);
+            for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+                writesWithSuppressedSamplers.push_back(
+                    createImmutableSamplersFilteredWriteDescriptorSetLocked(
+                        pDescriptorWrites + i,
+                        imageInfosPerWrite.data() + i));
+            }
+        }
+
+        enc->vkUpdateDescriptorSets(
+            device, descriptorWriteCount, writesWithSuppressedSamplers.data(),
+            descriptorCopyCount, pDescriptorCopies);
+    }
+
     void on_vkDestroyImage(
         void* context,
         VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
@@ -4045,7 +4380,7 @@
 
     uint32_t getApiVersionFromInstance(VkInstance instance) const {
         AutoLock lock(mLock);
-        uint32_t api = kMinApiVersion;
+        uint32_t api = kDefaultApiVersion;
 
         auto it = info_VkInstance.find(instance);
         if (it == info_VkInstance.end()) return api;
@@ -4058,7 +4393,7 @@
     uint32_t getApiVersionFromDevice(VkDevice device) const {
         AutoLock lock(mLock);
 
-        uint32_t api = kMinApiVersion;
+        uint32_t api = kDefaultApiVersion;
 
         auto it = info_VkDevice.find(device);
         if (it == info_VkDevice.end()) return api;
@@ -4717,6 +5052,78 @@
         context, input_result, device, fenceCount, pFences, waitAll, timeout);
 }
 
+VkResult ResourceTracker::on_vkCreateDescriptorPool(
+    void* context,
+    VkResult input_result,
+    VkDevice device,
+    const VkDescriptorPoolCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDescriptorPool* pDescriptorPool) {
+    return mImpl->on_vkCreateDescriptorPool(
+        context, input_result, device, pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+void ResourceTracker::on_vkDestroyDescriptorPool(
+    void* context,
+    VkDevice device,
+    VkDescriptorPool descriptorPool,
+    const VkAllocationCallbacks* pAllocator) {
+    mImpl->on_vkDestroyDescriptorPool(context, device, descriptorPool, pAllocator);
+}
+
+VkResult ResourceTracker::on_vkResetDescriptorPool(
+    void* context,
+    VkResult input_result,
+    VkDevice device,
+    VkDescriptorPool descriptorPool,
+    VkDescriptorPoolResetFlags flags) {
+    return mImpl->on_vkResetDescriptorPool(
+        context, input_result, device, descriptorPool, flags);
+}
+
+VkResult ResourceTracker::on_vkAllocateDescriptorSets(
+    void* context,
+    VkResult input_result,
+    VkDevice                                    device,
+    const VkDescriptorSetAllocateInfo*          pAllocateInfo,
+    VkDescriptorSet*                            pDescriptorSets) {
+    return mImpl->on_vkAllocateDescriptorSets(
+        context, input_result, device, pAllocateInfo, pDescriptorSets);
+}
+
+VkResult ResourceTracker::on_vkFreeDescriptorSets(
+    void* context,
+    VkResult input_result,
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    uint32_t                                    descriptorSetCount,
+    const VkDescriptorSet*                      pDescriptorSets) {
+    return mImpl->on_vkFreeDescriptorSets(
+        context, input_result, device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+VkResult ResourceTracker::on_vkCreateDescriptorSetLayout(
+    void* context,
+    VkResult input_result,
+    VkDevice device,
+    const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDescriptorSetLayout* pSetLayout) {
+    return mImpl->on_vkCreateDescriptorSetLayout(
+        context, input_result, device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+void ResourceTracker::on_vkUpdateDescriptorSets(
+    void* context,
+    VkDevice device,
+    uint32_t descriptorWriteCount,
+    const VkWriteDescriptorSet* pDescriptorWrites,
+    uint32_t descriptorCopyCount,
+    const VkCopyDescriptorSet* pDescriptorCopies) {
+    return mImpl->on_vkUpdateDescriptorSets(
+        context, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
 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 791a2b2..9a72bdf 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -363,6 +363,58 @@
         VkBool32 waitAll,
         uint64_t timeout);
 
+    VkResult on_vkCreateDescriptorPool(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        const VkDescriptorPoolCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorPool* pDescriptorPool);
+
+    void on_vkDestroyDescriptorPool(
+        void* context,
+        VkDevice device,
+        VkDescriptorPool descriptorPool,
+        const VkAllocationCallbacks* pAllocator);
+
+    VkResult on_vkResetDescriptorPool(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        VkDescriptorPool descriptorPool,
+        VkDescriptorPoolResetFlags flags);
+
+    VkResult on_vkAllocateDescriptorSets(
+        void* context,
+        VkResult input_result,
+        VkDevice                                    device,
+        const VkDescriptorSetAllocateInfo*          pAllocateInfo,
+        VkDescriptorSet*                            pDescriptorSets);
+
+    VkResult on_vkFreeDescriptorSets(
+        void* context,
+        VkResult input_result,
+        VkDevice                                    device,
+        VkDescriptorPool                            descriptorPool,
+        uint32_t                                    descriptorSetCount,
+        const VkDescriptorSet*                      pDescriptorSets);
+
+    VkResult on_vkCreateDescriptorSetLayout(
+        void* context,
+        VkResult input_result,
+        VkDevice device,
+        const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkDescriptorSetLayout* pSetLayout);
+
+    void on_vkUpdateDescriptorSets(
+        void* context,
+        VkDevice device,
+        uint32_t descriptorWriteCount,
+        const VkWriteDescriptorSet* pDescriptorWrites,
+        uint32_t descriptorCopyCount,
+        const VkCopyDescriptorSet* pDescriptorCopies);
+
     VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
         void* context,
         VkResult input_result,
diff --git a/system/vulkan_enc/VirtioGpuNext.h b/system/vulkan_enc/VirtioGpuNext.h
index 4037973..7da7da2 100644
--- a/system/vulkan_enc/VirtioGpuNext.h
+++ b/system/vulkan_enc/VirtioGpuNext.h
@@ -18,43 +18,37 @@
 #include "drm.h"
 #endif
 
-#define DRM_VIRTGPU_RESOURCE_CREATE_V2 0x0a
+#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x0a
 
-struct drm_virtgpu_resource_create_v2 {
-#define VIRTGPU_RESOURCE_TYPE_MASK       0x0000f
-#define VIRTGPU_RESOURCE_TYPE_DEFAULT_V1 0x00001
-#define VIRTGPU_RESOURCE_TYPE_DEFAULT_V2 0x00002
-#define VIRTGPU_RESOURCE_TYPE_HOST       0x00003
-#define VIRTGPU_RESOURCE_TYPE_GUEST      0x00004
-/*
- * Error cases:
- * HOST_VISIBLE_BIT without VIRTGPU_RESOURCE_TYPE_HOST
- */
-#define VIRTGPU_RESOURCE_HOST_MASK            0x000f0
-#define VIRTGPU_RESOURCE_HOST_VISIBLE_BIT     0x00010
+#define VIRTGPU_PARAM_RESOURCE_BLOB 3 /* DRM_VIRTGPU_RESOURCE_CREATE_BLOB */
+#define VIRTGPU_PARAM_HOST_VISIBLE 4
 
-#define VIRTGPU_RESOURCE_GUEST_MASK                  0x00f00
-#define VIRTGPU_RESOURCE_GUEST_SHARED_BIT            0x00100
-#define VIRTGPU_RESOURCE_GUEST_EMULATED_COHERENT_BIT 0x00200
+struct drm_virtgpu_resource_create_blob {
+#define VIRTGPU_BLOB_MEM_GUEST              0x0001
+#define VIRTGPU_BLOB_MEM_HOST               0x0002
+#define VIRTGPU_BLOB_MEM_HOST_GUEST         0x0003
 
-#define VIRTGPU_RESOURCE_CACHE_MASK      0x0f000
-#define VIRTGPU_RESOURCE_CACHE_CACHED    0x01000
-#define VIRTGPU_RESOURCE_CACHE_UNCACHED  0x02000
-#define VIRTGPU_RESOURCE_CACHE_WC        0x03000
-/*
- * VIRTGPU_RESOURCE_EXPORTABLE_BIT - host resource *can* be exported as an fd.
- */
-#define VIRTGPU_RESOURCE_EXPORT_MASK    0xf0000
-#define VIRTGPU_RESOURCE_EXPORTABLE_BIT 0x10000
-	uint32_t flags;
-	uint32_t args_size;
-	uint64_t size;
-	uint32_t bo_handle;
-	uint32_t res_handle;
-	uint64_t args;
+#define VIRTGPU_BLOB_FLAG_MAPPABLE          0x0001
+#define VIRTGPU_BLOB_FLAG_SHAREABLE         0x0002
+#define VIRTGPU_BLOB_FLAG_CROSS_DEVICE      0x0004
+	/* zero is invalid blob_mem */
+    uint32_t blob_mem;
+    uint32_t blob_flags;
+    uint32_t bo_handle;
+    uint32_t res_handle;
+    uint64_t size;
+
+	/*
+	 * for 3D contexts with VIRTGPU_BLOB_MEM_HOSTGUEST and
+	 * VIRTGPU_BLOB_MEM_HOST otherwise, must be zero.
+	 */
+	uint32_t pad;
+    uint32_t cmd_size;
+    uint64_t cmd;
+    uint64_t blob_id;
 };
 
-#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_V2				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_V2,	\
-		struct drm_virtgpu_resource_create_v2)
 
+#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB              \
+        DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_BLOB,   \
+                        struct drm_virtgpu_resource_create_blob)
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index b5b6eea..8c00e0c 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -23433,5 +23433,79 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+VkResult VkEncoder::vkFreeMemorySyncGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    const VkAllocationCallbacks* pAllocator)
+{
+    AutoLock encoderLock(mImpl->lock);
+    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE encode");
+    mImpl->log("start vkFreeMemorySyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkDevice local_device;
+    VkDeviceMemory local_memory;
+    VkAllocationCallbacks* local_pAllocator;
+    local_device = device;
+    local_memory = memory;
+    local_pAllocator = nullptr;
+    if (pAllocator)
+    {
+        local_pAllocator = (VkAllocationCallbacks*)pool->alloc(sizeof(const VkAllocationCallbacks));
+        deepcopy_VkAllocationCallbacks(pool, pAllocator, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    local_pAllocator = nullptr;
+    mImpl->resources()->deviceMemoryTransform_tohost((VkDeviceMemory*)&local_memory, 1, (VkDeviceSize*)nullptr, 0, (VkDeviceSize*)nullptr, 0, (uint32_t*)nullptr, 0, (uint32_t*)nullptr, 0);
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1547;
+        countingStream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1547, 1);
+        countingStream->write((uint64_t*)&cgen_var_1547, 1 * 8);
+        uint64_t cgen_var_1548;
+        countingStream->handleMapping()->mapHandles_VkDeviceMemory_u64(&local_memory, &cgen_var_1548, 1);
+        countingStream->write((uint64_t*)&cgen_var_1548, 1 * 8);
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1549 = (uint64_t)(uintptr_t)local_pAllocator;
+        countingStream->putBe64(cgen_var_1549);
+        if (local_pAllocator)
+        {
+            marshal_VkAllocationCallbacks(countingStream, (VkAllocationCallbacks*)(local_pAllocator));
+        }
+    }
+    uint32_t packetSize_vkFreeMemorySyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkFreeMemorySyncGOOGLE = OP_vkFreeMemorySyncGOOGLE;
+    stream->write(&opcode_vkFreeMemorySyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkFreeMemorySyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1550;
+    stream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1550, 1);
+    stream->write((uint64_t*)&cgen_var_1550, 1 * 8);
+    uint64_t cgen_var_1551;
+    stream->handleMapping()->mapHandles_VkDeviceMemory_u64(&local_memory, &cgen_var_1551, 1);
+    stream->write((uint64_t*)&cgen_var_1551, 1 * 8);
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1552 = (uint64_t)(uintptr_t)local_pAllocator;
+    stream->putBe64(cgen_var_1552);
+    if (local_pAllocator)
+    {
+        marshal_VkAllocationCallbacks(stream, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE returnUnmarshal");
+    VkResult vkFreeMemorySyncGOOGLE_VkResult_return = (VkResult)0;
+    stream->read(&vkFreeMemorySyncGOOGLE_VkResult_return, sizeof(VkResult));
+    countingStream->clearPool();
+    stream->clearPool();
+    pool->freeAll();
+    resources->destroyMapping()->mapHandles_VkDeviceMemory((VkDeviceMemory*)&memory);
+    mImpl->log("finish vkFreeMemorySyncGOOGLE");;
+    return vkFreeMemorySyncGOOGLE_VkResult_return;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index 4cab74f..8f49f7d 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -1815,6 +1815,12 @@
         uint64_t* pSize,
         uint64_t* pHostmemId);
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+    VkResult vkFreeMemorySyncGOOGLE(
+    VkDevice device,
+        VkDeviceMemory memory,
+        const VkAllocationCallbacks* pAllocator);
+#endif
 
 private:
     class Impl;
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index b8bd801..54699aa 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -26,13 +26,22 @@
     f(VkCommandBuffer) \
     GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
 
+#ifdef VK_NVX_device_generated_commands
+
+#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f) \
+    f(VkObjectTableNVX) \
+    f(VkIndirectCommandsLayoutNVX) \
+
+#else
+
+#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f)
+
+#endif // VK_NVX_device_generated_commands
+
 #define GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkBufferView) \
     f(VkImageView) \
     f(VkShaderModule) \
-    f(VkDescriptorPool) \
-    f(VkDescriptorSetLayout) \
-    f(VkDescriptorSet) \
     f(VkSampler) \
     f(VkPipeline) \
     f(VkPipelineCache) \
@@ -47,11 +56,10 @@
     f(VkSwapchainKHR) \
     f(VkDisplayKHR) \
     f(VkDisplayModeKHR) \
-    f(VkObjectTableNVX) \
-    f(VkIndirectCommandsLayoutNVX) \
     f(VkValidationCacheEXT) \
     f(VkDebugReportCallbackEXT) \
     f(VkDebugUtilsMessengerEXT) \
+    __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f)
 
 #define GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkDeviceMemory) \
@@ -60,6 +68,9 @@
     f(VkSemaphore) \
     f(VkDescriptorUpdateTemplate) \
     f(VkFence) \
+    f(VkDescriptorPool) \
+    f(VkDescriptorSet) \
+    f(VkDescriptorSetLayout) \
     GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
 
 #define GOLDFISH_VK_LIST_HANDLE_TYPES(f) \
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
index 917ca59..e2d3294 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6388,6 +6388,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 void deepcopy_extension_struct(
     Pool* pool,
     const void* structExtension,
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
index b1ffaa6..1164e1c 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2030,5 +2030,7 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
index 08bba9f..e4b1ca7 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -286,6 +286,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 uint32_t goldfish_vk_struct_type(
     const void* structExtension)
 {
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
index 4fa4e3c..5a3fc66 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -303,5 +303,7 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
index 56adc3a..8e66554 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4752,6 +4752,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 void handlemap_extension_struct(
     VulkanHandleMapping* handlemap,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.h b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
index 8785741..0dcedcb 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1683,5 +1683,7 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
index 24b8112..371e92e 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -13615,6 +13615,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
@@ -16396,6 +16398,12 @@
             return "OP_vkGetMemoryHostAddressInfoGOOGLE";
         }
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+        case OP_vkFreeMemorySyncGOOGLE:
+        {
+            return "OP_vkFreeMemorySyncGOOGLE";
+        }
+#endif
         default:
         {
             return "OP_UNKNOWN_API_CALL";
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.h b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
index da9e961..993c890 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3397,6 +3397,9 @@
 #ifdef VK_GOOGLE_address_space_info
 #define OP_vkGetMemoryHostAddressInfoGOOGLE 20327
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#define OP_vkFreeMemorySyncGOOGLE 20328
+#endif
 const char* api_opcode_to_string(
     const uint32_t opcode);
 
diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h
index dd0c155..9e673c0 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -119,6 +119,10 @@
 
 typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostAddressInfoGOOGLE)(VkDevice device, VkDeviceMemory memory, uint64_t* pAddress, uint64_t* pSize);
 
+#define VK_GOOGLE_free_memory_sync 1
+
+typedef VkResult (VKAPI_PTR *PFN_vkFreeMemorySyncGOOGLE)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocationCallbacks);
+
 #define VK_ANDROID_external_memory_android_hardware_buffer 1
 struct AHardwareBuffer;
 struct VkAndroidHardwareBufferPropertiesANDROID;
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.cpp b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
index 9e7fbf5..550313f 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -8949,6 +8949,8 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 void transform_tohost_extension_struct(
     ResourceTracker* resourceTracker,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.h b/system/vulkan_enc/goldfish_vk_transform_guest.h
index 6511666..d0b610b 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3071,5 +3071,7 @@
 #endif
 #ifdef VK_GOOGLE_address_space_info
 #endif
+#ifdef VK_GOOGLE_free_memory_sync
+#endif
 
 } // namespace goldfish_vk