Merge changes from topic "gfxstream-build-libnames" into main

* changes:
  Format Android.bp files
  Normalize some Gfxstream library names
diff --git a/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h b/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
index 081befc..9e8d280 100644
--- a/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
+++ b/host/include/gfxstream/virtio-gpu-gfxstream-renderer.h
@@ -86,22 +86,23 @@
     uint32_t handle_type;
 };
 
-// Log level of gfxstream
-#ifndef STREAM_RENDERER_LOG_LEVEL
-#define STREAM_RENDERER_LOG_LEVEL 1
-#endif
-
 // @user_data: custom user data passed during `stream_renderer_init`
 // @type: one of STREAM_RENDERER_DEBUG_*
 // @string: null-terminated C-string
 #define STREAM_RENDERER_DEBUG_ERROR 0x1
 #define STREAM_RENDERER_DEBUG_WARN 0x2
 #define STREAM_RENDERER_DEBUG_INFO 0x3
+#define STREAM_RENDERER_DEBUG_DEBUG 0x4
 struct stream_renderer_debug {
     uint32_t debug_type;
     const char* message;
 };
 
+// Log level of gfxstream
+#ifndef STREAM_RENDERER_LOG_LEVEL
+#define STREAM_RENDERER_LOG_LEVEL STREAM_RENDERER_DEBUG_INFO
+#endif
+
 // Callback for writing a fence.
 typedef void (*stream_renderer_fence_callback)(void* user_data,
                                                struct stream_renderer_fence* fence_data);
diff --git a/host/virtio-gpu-gfxstream-renderer.cpp b/host/virtio-gpu-gfxstream-renderer.cpp
index 080238a..fabe6cb 100644
--- a/host/virtio-gpu-gfxstream-renderer.cpp
+++ b/host/virtio-gpu-gfxstream-renderer.cpp
@@ -72,7 +72,7 @@
 void* globalUserData = nullptr;
 stream_renderer_debug_callback globalDebugCallback = nullptr;
 
-void stream_renderer_debug(uint32_t type, const char* format, ...) {
+void stream_renderer_log(uint32_t type, const char* format, ...) {
     char buf[MAX_DEBUG_BUFFER_SIZE];
     va_list args;
     va_start(args, format);
@@ -90,26 +90,46 @@
     }
 }
 
-#if STREAM_RENDERER_LOG_LEVEL >= 1
-#define stream_renderer_error(format, ...)                                                         \
-    do {                                                                                           \
-        stream_renderer_debug(STREAM_RENDERER_DEBUG_ERROR, "[%s(%d)] %s " format,                  \
-                              __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);             \
+#if STREAM_RENDERER_LOG_LEVEL >= STREAM_RENDERER_DEBUG_ERROR
+#define stream_renderer_error(format, ...)                                                \
+    do {                                                                                  \
+        stream_renderer_log(STREAM_RENDERER_DEBUG_ERROR, "[%s(%d)] %s " format, __FILE__, \
+                            __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);                \
     } while (0)
 #else
 #define stream_renderer_error(format, ...)
 #endif
 
-#if STREAM_RENDERER_LOG_LEVEL >= 3
-#define stream_renderer_info(format, ...)                                                         \
-    do {                                                                                          \
-        stream_renderer_debug(STREAM_RENDERER_DEBUG_INFO, "[%s(%d)] %s " format,                  \
-                              __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);            \
+#if STREAM_RENDERER_LOG_LEVEL >= STREAM_RENDERER_DEBUG_WARN
+#define stream_renderer_warn(format, ...)                                                          \
+    do {                                                                                           \
+        stream_renderer_log(STREAM_RENDERER_DEBUG_WARN, "[%s(%d)] %s " format, __FILE__, __LINE__, \
+                            __PRETTY_FUNCTION__, ##__VA_ARGS__);                                   \
+    } while (0)
+#else
+#define stream_renderer_warn(format, ...)
+#endif
+
+#if STREAM_RENDERER_LOG_LEVEL >= STREAM_RENDERER_DEBUG_INFO
+#define stream_renderer_info(format, ...)                                                          \
+    do {                                                                                           \
+        stream_renderer_log(STREAM_RENDERER_DEBUG_INFO, "[%s(%d)] %s " format, __FILE__, __LINE__, \
+                            __FUNCTION__, ##__VA_ARGS__);                                          \
     } while (0)
 #else
 #define stream_renderer_info(format, ...)
 #endif
 
+#if STREAM_RENDERER_LOG_LEVEL >= STREAM_RENDERER_DEBUG_DEBUG
+#define stream_renderer_debug(format, ...)                                                \
+    do {                                                                                  \
+        stream_renderer_log(STREAM_RENDERER_DEBUG_DEBUG, "[%s(%d)] %s " format, __FILE__, \
+                            __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);                \
+    } while (0)
+#else
+#define stream_renderer_debug(format, ...)
+#endif
+
 // Virtio Goldfish Pipe: Overview-----------------------------------------------
 //
 // Virtio Goldfish Pipe is meant for running goldfish pipe services with a
@@ -489,9 +509,9 @@
 
 static int sync_iov(PipeResEntry* res, uint64_t offset, const stream_renderer_box* box,
                     IovSyncDir dir) {
-    stream_renderer_info("offset: 0x%llx box: %u %u %u %u size %u x %u iovs %u linearSize %zu",
-                         (unsigned long long)offset, box->x, box->y, box->w, box->h,
-                         res->args.width, res->args.height, res->numIovs, res->linearSize);
+    stream_renderer_debug("offset: 0x%llx box: %u %u %u %u size %u x %u iovs %u linearSize %zu",
+                          (unsigned long long)offset, box->x, box->y, box->w, box->h,
+                          res->args.width, res->args.height, res->numIovs, res->linearSize);
 
     if (box->x > res->args.width || box->y > res->args.height) {
         stream_renderer_error("Box out of range of resource");
@@ -576,7 +596,7 @@
     PipeVirglRenderer() = default;
 
     int init(void* cookie, int flags, stream_renderer_fence_callback fence_callback) {
-        stream_renderer_info("cookie: %p", cookie);
+        stream_renderer_debug("cookie: %p", cookie);
         mCookie = cookie;
         mFenceCallback = fence_callback;
         mVirtioGpuOps = android_getVirtioGpuOps();
@@ -600,7 +620,7 @@
     }
 
     int resetPipe(GoldfishHwPipe* hwPipe, GoldfishHostPipe* hostPipe) {
-        stream_renderer_info("Want to reset hwpipe %p to hostpipe %p", hwPipe, hostPipe);
+        stream_renderer_debug("Want to reset hwpipe %p to hostpipe %p", hwPipe, hostPipe);
         VirtioGpuCtxId asCtxId = (VirtioGpuCtxId)(uintptr_t)hwPipe;
         auto it = mContexts.find(asCtxId);
         if (it == mContexts.end()) {
@@ -609,9 +629,9 @@
         }
 
         auto& entry = it->second;
-        stream_renderer_info("ctxid: %u prev hostpipe: %p", asCtxId, entry.hostPipe);
+        stream_renderer_debug("ctxid: %u prev hostpipe: %p", asCtxId, entry.hostPipe);
         entry.hostPipe = hostPipe;
-        stream_renderer_info("ctxid: %u next hostpipe: %p", asCtxId, entry.hostPipe);
+        stream_renderer_debug("ctxid: %u next hostpipe: %p", asCtxId, entry.hostPipe);
 
         // Also update any resources associated with it
         auto resourcesIt = mContextResources.find(asCtxId);
@@ -640,13 +660,13 @@
                       uint32_t context_init) {
         std::string contextName(name, nlen);
 
-        stream_renderer_info("ctxid: %u len: %u name: %s", ctx_id, nlen, contextName.c_str());
+        stream_renderer_debug("ctxid: %u len: %u name: %s", ctx_id, nlen, contextName.c_str());
         auto ops = ensureAndGetServiceOps();
         auto hostPipe = ops->guest_open_with_flags(reinterpret_cast<GoldfishHwPipe*>(ctx_id),
                                                    0x1 /* is virtio */);
 
         if (!hostPipe) {
-            stream_renderer_error("failed to create hw pipe!\n");
+            stream_renderer_error("failed to create hw pipe!");
             return -EINVAL;
         }
         std::unordered_map<uint32_t, uint32_t> map;
@@ -662,18 +682,18 @@
             map,                     // resourceId --> ASG handle map
         };
 
-        stream_renderer_info("initial host pipe for ctxid %u: %p", ctx_id, hostPipe);
+        stream_renderer_debug("initial host pipe for ctxid %u: %p", ctx_id, hostPipe);
         mContexts[ctx_id] = res;
         android_onGuestGraphicsProcessCreate(ctx_id);
         return 0;
     }
 
     int destroyContext(VirtioGpuCtxId handle) {
-        stream_renderer_info("ctxid: %u", handle);
+        stream_renderer_debug("ctxid: %u", handle);
 
         auto it = mContexts.find(handle);
         if (it == mContexts.end()) {
-            stream_renderer_error("could not find context handle %u\n", handle);
+            stream_renderer_error("could not find context handle %u", handle);
             return -EINVAL;
         }
 
@@ -800,16 +820,16 @@
         void* buffer = reinterpret_cast<void*>(cmd->cmd);
 
         VirtioGpuRing ring = VirtioGpuRingGlobal{};
-        stream_renderer_info("ctx: % u, ring: %s buffer: %p dwords: %d", cmd->ctx_id,
-                             to_string(ring).c_str(), buffer, cmd->cmd_size);
+        stream_renderer_debug("ctx: % u, ring: %s buffer: %p dwords: %d", cmd->ctx_id,
+                              to_string(ring).c_str(), buffer, cmd->cmd_size);
 
         if (!buffer) {
-            stream_renderer_error("error: buffer null\n");
+            stream_renderer_error("error: buffer null");
             return -EINVAL;
         }
 
         if (cmd->cmd_size < 4) {
-            stream_renderer_error("error: not enough bytes (got %d)\n", cmd->cmd_size);
+            stream_renderer_error("error: not enough bytes (got %d)", cmd->cmd_size);
             return -EINVAL;
         }
 
@@ -828,7 +848,7 @@
                 uint64_t sync_handle =
                     convert32to64(exportSync.syncHandleLo, exportSync.syncHandleHi);
 
-                stream_renderer_info("wait for gpu ring %s", to_string(ring).c_str());
+                stream_renderer_debug("wait for gpu ring %s", to_string(ring).c_str());
                 auto taskId = mVirtioGpuTimelines->enqueueTask(ring);
                 mVirtioGpuOps->async_wait_for_gpu_with_cb(sync_handle, [this, taskId] {
                     mVirtioGpuTimelines->notifyTaskCompletion(taskId);
@@ -854,7 +874,7 @@
                 uint64_t fence_handle =
                     convert32to64(exportSyncVK.fenceHandleLo, exportSyncVK.fenceHandleHi);
 
-                stream_renderer_info("wait for gpu ring %s", to_string(ring).c_str());
+                stream_renderer_debug("wait for gpu ring %s", to_string(ring).c_str());
                 auto taskId = mVirtioGpuTimelines->enqueueTask(ring);
                 mVirtioGpuOps->async_wait_for_gpu_vulkan_with_cb(
                     device_handle, fence_handle,
@@ -876,8 +896,8 @@
                 uint64_t image_handle =
                     convert32to64(exportQSRI.imageHandleLo, exportQSRI.imageHandleHi);
 
-                stream_renderer_info("wait for gpu vk qsri ring %u image 0x%llx",
-                                     to_string(ring).c_str(), (unsigned long long)image_handle);
+                stream_renderer_debug("wait for gpu vk qsri ring %u image 0x%llx",
+                                      to_string(ring).c_str(), (unsigned long long)image_handle);
                 auto taskId = mVirtioGpuTimelines->enqueueTask(ring);
                 mVirtioGpuOps->async_wait_for_gpu_vulkan_qsri_with_cb(image_handle, [this, taskId] {
                     mVirtioGpuTimelines->notifyTaskCompletion(taskId);
@@ -896,8 +916,8 @@
     }
 
     int createFence(uint64_t fence_id, const VirtioGpuRing& ring) {
-        stream_renderer_info("fenceid: %llu ring: %s", (unsigned long long)fence_id,
-                             to_string(ring).c_str());
+        stream_renderer_debug("fenceid: %llu ring: %s", (unsigned long long)fence_id,
+                              to_string(ring).c_str());
 
         struct {
             FenceCompletionCallback operator()(const VirtioGpuRingGlobal&) {
@@ -1005,8 +1025,8 @@
 
     void handleCreateResourceColorBuffer(struct stream_renderer_resource_create_args* args) {
         // corresponds to allocation of gralloc buffer in minigbm
-        stream_renderer_info("w h %u %u resid %u -> CreateColorBufferWithHandle", args->width,
-                             args->height, args->handle);
+        stream_renderer_debug("w h %u %u resid %u -> CreateColorBufferWithHandle", args->width,
+                              args->height, args->handle);
 
         const uint32_t glformat = virgl_format_to_gl(args->format);
         const uint32_t fwkformat = virgl_format_to_fwk_format(args->format);
@@ -1018,7 +1038,7 @@
 
     int createResource(struct stream_renderer_resource_create_args* args, struct iovec* iov,
                        uint32_t num_iovs) {
-        stream_renderer_info("handle: %u. num iovs: %u", args->handle, num_iovs);
+        stream_renderer_debug("handle: %u. num iovs: %u", args->handle, num_iovs);
 
         const auto resType = getResourceType(*args);
         switch (resType) {
@@ -1048,7 +1068,7 @@
     }
 
     void unrefResource(uint32_t toUnrefId) {
-        stream_renderer_info("handle: %u", toUnrefId);
+        stream_renderer_debug("handle: %u", toUnrefId);
 
         auto it = mResources.find(toUnrefId);
         if (it == mResources.end()) return;
@@ -1097,16 +1117,16 @@
     }
 
     int attachIov(int resId, iovec* iov, int num_iovs) {
-        stream_renderer_info("resid: %d numiovs: %d", resId, num_iovs);
+        stream_renderer_debug("resid: %d numiovs: %d", resId, num_iovs);
 
         auto it = mResources.find(resId);
         if (it == mResources.end()) return ENOENT;
 
         auto& entry = it->second;
-        stream_renderer_info("res linear: %p", entry.linear);
+        stream_renderer_debug("res linear: %p", entry.linear);
         if (!entry.linear) allocResource(entry, iov, num_iovs);
 
-        stream_renderer_info("done");
+        stream_renderer_debug("done");
         return 0;
     }
 
@@ -1118,9 +1138,9 @@
 
         if (num_iovs) {
             *num_iovs = entry.numIovs;
-            stream_renderer_info("resid: %d numIovs: %d", resId, *num_iovs);
+            stream_renderer_debug("resid: %d numIovs: %d", resId, *num_iovs);
         } else {
-            stream_renderer_info("resid: %d numIovs: 0", resId);
+            stream_renderer_debug("resid: %d numIovs: 0", resId);
         }
 
         entry.numIovs = 0;
@@ -1133,7 +1153,7 @@
         }
 
         allocResource(entry, entry.iov, entry.numIovs);
-        stream_renderer_info("done");
+        stream_renderer_debug("done");
     }
 
     int handleTransferReadPipe(PipeResEntry* res, uint64_t offset, stream_renderer_box* box) {
@@ -1179,12 +1199,12 @@
         // Do the pipe service op here, if there is an associated hostpipe.
         auto hostPipe = res->hostPipe;
         if (!hostPipe) {
-            stream_renderer_info("No hostPipe");
+            stream_renderer_error("No hostPipe");
             return -EINVAL;
         }
 
-        stream_renderer_info("resid: %d offset: 0x%llx hostpipe: %p", res->args.handle,
-                             (unsigned long long)offset, hostPipe);
+        stream_renderer_debug("resid: %d offset: 0x%llx hostpipe: %p", res->args.handle,
+                              (unsigned long long)offset, hostPipe);
 
         auto ops = ensureAndGetServiceOps();
 
@@ -1435,7 +1455,7 @@
     }
 
     void attachResource(uint32_t ctxId, uint32_t resId) {
-        stream_renderer_info("ctxid: %u resid: %u", ctxId, resId);
+        stream_renderer_debug("ctxid: %u resid: %u", ctxId, resId);
 
         auto resourcesIt = mContextResources.find(ctxId);
 
@@ -1469,18 +1489,18 @@
 
         if (ctxEntryIt == mContexts.end() || resEntryIt == mResources.end()) return;
 
-        stream_renderer_info("hostPipe: %p", ctxEntryIt->second.hostPipe);
+        stream_renderer_debug("hostPipe: %p", ctxEntryIt->second.hostPipe);
         resEntryIt->second.hostPipe = ctxEntryIt->second.hostPipe;
         resEntryIt->second.ctxId = ctxId;
     }
 
     void detachResource(uint32_t ctxId, uint32_t toUnrefId) {
-        stream_renderer_info("ctxid: %u resid: %u", ctxId, toUnrefId);
+        stream_renderer_debug("ctxid: %u resid: %u", ctxId, toUnrefId);
         detachResourceLocked(ctxId, toUnrefId);
     }
 
     int getResourceInfo(uint32_t resId, struct stream_renderer_resource_info* info) {
-        stream_renderer_info("resid: %u", resId);
+        stream_renderer_debug("resid: %u", resId);
         if (!info) return EINVAL;
 
         auto it = mResources.find(resId);
@@ -1566,8 +1586,8 @@
     int createBlob(uint32_t ctx_id, uint32_t res_handle,
                    const struct stream_renderer_create_blob* create_blob,
                    const struct stream_renderer_handle* handle) {
-        stream_renderer_info("ctx:%u res:%u blob-id:%u blob-size:%u",
-                             ctx_id, res_handle, create_blob->blob_id, create_blob->size);
+        stream_renderer_debug("ctx:%u res:%u blob-id:%u blob-size:%u", ctx_id, res_handle,
+                              create_blob->blob_id, create_blob->size);
 
         PipeResEntry e;
         struct stream_renderer_resource_create_args args = {0};
@@ -1763,17 +1783,17 @@
 #endif  // CONFIG_AEMU
    private:
     void allocResource(PipeResEntry& entry, iovec* iov, int num_iovs) {
-        stream_renderer_info("entry linear: %p", entry.linear);
+        stream_renderer_debug("entry linear: %p", entry.linear);
         if (entry.linear) free(entry.linear);
 
         size_t linearSize = 0;
         for (uint32_t i = 0; i < num_iovs; ++i) {
-            stream_renderer_info("iov base: %p", iov[i].iov_base);
+            stream_renderer_debug("iov base: %p", iov[i].iov_base);
             linearSize += iov[i].iov_len;
-            stream_renderer_info("has iov of %zu. linearSize current: %zu", iov[i].iov_len,
-                                 linearSize);
+            stream_renderer_debug("has iov of %zu. linearSize current: %zu", iov[i].iov_len,
+                                  linearSize);
         }
-        stream_renderer_info("final linearSize: %zu", linearSize);
+        stream_renderer_debug("final linearSize: %zu", linearSize);
 
         void* linear = nullptr;
 
@@ -1787,7 +1807,7 @@
     }
 
     void detachResourceLocked(uint32_t ctxId, uint32_t toUnrefId) {
-        stream_renderer_info("ctxid: %u resid: %u", ctxId, toUnrefId);
+        stream_renderer_debug("ctxid: %u resid: %u", ctxId, toUnrefId);
 
         auto it = mContextResources.find(ctxId);
         if (it == mContextResources.end()) return;
@@ -2139,8 +2159,8 @@
 
 static int stream_renderer_opengles_init(uint32_t display_width, uint32_t display_height,
                                          int renderer_flags, const std::string& renderer_features) {
-    stream_renderer_info("start. display dimensions: width %u height %u, renderer flags: 0x%x",
-                         display_width, display_height, renderer_flags);
+    stream_renderer_debug("start. display dimensions: width %u height %u, renderer flags: 0x%x",
+                          display_width, display_height, renderer_flags);
 
     // Flags processing
 
@@ -2188,12 +2208,12 @@
 
     if (useSystemBlob) {
         if (!useExternalBlob) {
-            stream_renderer_info("USE_EXTERNAL_BLOB must be on with USE_SYSTEM_BLOB");
+            stream_renderer_error("USE_EXTERNAL_BLOB must be on with USE_SYSTEM_BLOB");
             return -EINVAL;
         }
 
 #ifndef _WIN32
-        stream_renderer_info("Warning: USE_SYSTEM_BLOB has only been tested on Windows");
+        stream_renderer_warn("Warning: USE_SYSTEM_BLOB has only been tested on Windows");
 #endif
     }
 
@@ -2304,7 +2324,7 @@
 
     android_getOpenglesHardwareStrings(&vendor, &renderer, &version);
 
-    stream_renderer_info("GL strings; [%s] [%s] [%s].\n", vendor, renderer, version);
+    stream_renderer_info("GL strings; [%s] [%s] [%s].", vendor, renderer, version);
 
     auto openglesRenderer = android_getOpenglesRenderer();
 
@@ -2377,7 +2397,7 @@
     bool skip_opengles = false;
 
     // Iterate all parameters that we support.
-    stream_renderer_info("Reading stream renderer parameters:");
+    stream_renderer_debug("Reading stream renderer parameters:");
     for (uint64_t i = 0; i < num_params; ++i) {
         stream_renderer_param& param = stream_renderer_params[i];
 
@@ -2385,11 +2405,11 @@
         // adding new prints.
         if (printed_param_values.find(param.key) != printed_param_values.end() ||
             param.value <= 4096) {
-            stream_renderer_info("%s - %llu", get_param_string(param.key).c_str(),
-                                 static_cast<unsigned long long>(param.value));
+            stream_renderer_debug("%s - %llu", get_param_string(param.key).c_str(),
+                                  static_cast<unsigned long long>(param.value));
         } else {
             // If not full value, print that it was passed.
-            stream_renderer_info("%s", get_param_string(param.key).c_str());
+            stream_renderer_debug("%s", get_param_string(param.key).c_str());
         }
 
         // Removing every param we process will leave required_params empty if all provided.
@@ -2477,7 +2497,7 @@
             }
         }
     }
-    stream_renderer_info("Finished reading parameters");
+    stream_renderer_debug("Finished reading parameters");
 
     // Some required params not found.
     if (required_params.size() > 0) {
@@ -2528,7 +2548,7 @@
     sRenderer()->init(renderer_cookie, renderer_flags, fence_callback);
     gfxstream::FrameBuffer::waitUntilInitialized();
 
-    stream_renderer_info("Started renderer");
+    stream_renderer_info("Gfxstream initialized successfully!");
     return 0;
 }
 
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 28298ad..2536720 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -3868,6 +3868,7 @@
 
         VkImportMemoryHostPointerInfoEXT importHostInfo;
         std::optional<SharedMemory> sharedMemory = std::nullopt;
+        std::shared_ptr<PrivateMemory> privateMemory = {};
 
         // TODO(b/261222354): Make sure the feature exists when initializing sVkEmulation.
         if (hostVisible && feature_is_enabled(kFeature_SystemBlob)) {
@@ -3902,6 +3903,22 @@
             vk_append_struct(&structChainIter, &importHostInfo);
         }
 
+        VkImportMemoryHostPointerInfoEXT importHostInfoPrivate{};
+        if (hostVisible && feature_is_enabled(kFeature_VulkanAllocateHostMemory) &&
+            localAllocInfo.pNext == nullptr) {
+            VkDeviceSize alignedSize = __ALIGN(localAllocInfo.allocationSize, kPageSizeforBlob);
+            localAllocInfo.allocationSize = alignedSize;
+            privateMemory =
+                std::make_shared<PrivateMemory>(kPageSizeforBlob, localAllocInfo.allocationSize);
+            mappedPtr = privateMemory->getAddr();
+            importHostInfoPrivate = {
+                .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
+                .pNext = NULL,
+                .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
+                .pHostPointer = mappedPtr};
+            vk_append_struct(&structChainIter, &importHostInfoPrivate);
+        }
+
         VkResult result = vk->vkAllocateMemory(device, &localAllocInfo, pAllocator, pMemory);
 
         if (result != VK_SUCCESS) {
@@ -3992,6 +4009,8 @@
             // Always assign the shared memory into memoryInfo. If it was used, then it will have
             // ownership transferred.
             memoryInfo.sharedMemory = std::exchange(sharedMemory, std::nullopt);
+
+            memoryInfo.privateMemory = privateMemory;
         }
 
         *pMemory = new_boxed_non_dispatchable_VkDeviceMemory(*pMemory);
diff --git a/host/vulkan/VkDecoderInternalStructs.h b/host/vulkan/VkDecoderInternalStructs.h
index 6a90923..bf1e55f 100644
--- a/host/vulkan/VkDecoderInternalStructs.h
+++ b/host/vulkan/VkDecoderInternalStructs.h
@@ -16,6 +16,11 @@
 
 #include <vulkan/vulkan.h>
 
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+#include <stdlib.h>
 #include <set>
 #include <string>
 
@@ -100,6 +105,32 @@
     int mMaxSize;
 };
 
+class PrivateMemory {
+public:
+    PrivateMemory(size_t alignment, size_t size) {
+#ifdef _WIN32
+        mAddr = _aligned_malloc(size, alignment);
+#else
+        mAddr = aligned_alloc(alignment, size);
+#endif
+    }
+    ~PrivateMemory() {
+        if (mAddr) {
+#ifdef _WIN32
+            _aligned_free(mAddr);
+#else
+            free(mAddr);
+#endif
+            mAddr = nullptr;
+        }
+    }
+    void* getAddr() {
+        return mAddr;
+    }
+private:
+    void* mAddr{nullptr};
+};
+
 // We always map the whole size on host.
 // This makes it much easier to implement
 // the memory map API.
@@ -126,6 +157,7 @@
     // Set if the memory is backed by shared memory.
     std::optional<android::base::SharedMemory> sharedMemory;
 
+    std::shared_ptr<PrivateMemory> privateMemory;
     // virtio-gpu blobs
     uint64_t blobId = 0;
 
@@ -307,4 +339,4 @@
     VkDevice device;
 };
 }  // namespace vk
-}  // namespace gfxstream
\ No newline at end of file
+}  // namespace gfxstream