Support AHARDWAREBUFFER_FORMAT_BLOB buffers

by mapping BLOBs to `Buffer`s instead of `ColorBuffer`s and by
adding the needed plumbing for reads and updates.

Note: this is not a fully complete solution as technically a
guest not running with ANGLE could still have native Vulkan
users which import the BLOB AHBs. This has not yet been observed
so this might be okay for now.

Bug: b/234513607
Test: launch_cvd --gpu_mode=gfxstream (with WIP ANGLE)
Test: cts -m CtsNativeHardwareTestCases
Test: ANGLE's `ExternalBufferTestES31.*/ES3_1_Vulkan` tests
Change-Id: I782559e5a57cadc9568d46b2e0949924a6493810
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index 4035271..9788941 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -1431,6 +1431,7 @@
 
 static VkFormat glFormat2VkFormat(GLint internalformat) {
     switch (internalformat) {
+        case GL_R8:
         case GL_LUMINANCE:
             return VK_FORMAT_R8_UNORM;
         case GL_RGB:
@@ -1457,8 +1458,9 @@
         case GL_BGRA_EXT:
         case GL_BGRA8_EXT:
             return VK_FORMAT_B8G8R8A8_UNORM;
-            ;
         default:
+            VK_COMMON_ERROR("Unhandled format %d, falling back to VK_FORMAT_R8G8B8A8_UNORM",
+                            internalformat);
             return VK_FORMAT_R8G8B8A8_UNORM;
     }
 };
@@ -2537,6 +2539,177 @@
     return infoPtr->memory.exportedHandle;
 }
 
+bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes) {
+    if (!sVkEmulation || !sVkEmulation->live) {
+        VK_COMMON_ERROR("VkEmulation not available.");
+        return false;
+    }
+
+    auto vk = sVkEmulation->dvk;
+
+    AutoLock lock(sVkEmulationLock);
+
+    auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
+    if (!bufferInfo) {
+        VK_COMMON_ERROR("Failed to read from Buffer:%d, not found.", bufferHandle);
+        return false;
+    }
+
+    const auto& stagingBufferInfo = sVkEmulation->staging;
+    if (size > stagingBufferInfo.size) {
+        VK_COMMON_ERROR("Failed to read from Buffer:%d, staging buffer too small.", bufferHandle);
+        return false;
+    }
+
+    const VkCommandBufferBeginInfo beginInfo = {
+        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+        .pNext = nullptr,
+        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+    };
+
+    VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
+
+    VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
+
+    const VkBufferCopy bufferCopy = {
+        .srcOffset = offset,
+        .dstOffset = 0,
+        .size = size,
+    };
+    vk->vkCmdCopyBuffer(commandBuffer, bufferInfo->buffer, stagingBufferInfo.buffer, 1,
+                        &bufferCopy);
+
+    VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
+
+    const VkSubmitInfo submitInfo = {
+        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+        .pNext = nullptr,
+        .waitSemaphoreCount = 0,
+        .pWaitSemaphores = nullptr,
+        .pWaitDstStageMask = nullptr,
+        .commandBufferCount = 1,
+        .pCommandBuffers = &commandBuffer,
+        .signalSemaphoreCount = 0,
+        .pSignalSemaphores = nullptr,
+    };
+
+    {
+        android::base::AutoLock lock(*sVkEmulation->queueLock);
+        VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
+                                   sVkEmulation->commandBufferFence));
+    }
+
+    static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
+
+    VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
+                                 VK_TRUE, ANB_MAX_WAIT_NS));
+
+    VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
+
+    const VkMappedMemoryRange toInvalidate = {
+        .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+        .pNext = nullptr,
+        .memory = stagingBufferInfo.memory.memory,
+        .offset = 0,
+        .size = size,
+    };
+
+    VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
+
+    const void* srcPtr = reinterpret_cast<const void*>(
+        reinterpret_cast<const char*>(stagingBufferInfo.memory.mappedPtr));
+    void* dstPtr = outBytes;
+    void* dstPtrOffset = reinterpret_cast<void*>(reinterpret_cast<char*>(dstPtr) + offset);
+    std::memcpy(dstPtrOffset, srcPtr, size);
+
+    return true;
+}
+
+bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* bytes) {
+    if (!sVkEmulation || !sVkEmulation->live) {
+        VK_COMMON_ERROR("VkEmulation not available.");
+        return false;
+    }
+
+    auto vk = sVkEmulation->dvk;
+
+    AutoLock lock(sVkEmulationLock);
+
+    auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
+    if (!bufferInfo) {
+        VK_COMMON_ERROR("Failed to update Buffer:%d, not found.", bufferHandle);
+        return false;
+    }
+
+    const auto& stagingBufferInfo = sVkEmulation->staging;
+    if (size > stagingBufferInfo.size) {
+        VK_COMMON_ERROR("Failed to update Buffer:%d, staging buffer too small.", bufferHandle);
+        return false;
+    }
+
+    const void* srcPtr = bytes;
+    const void* srcPtrOffset =
+        reinterpret_cast<const void*>(reinterpret_cast<const char*>(srcPtr) + offset);
+    void* dstPtr = stagingBufferInfo.memory.mappedPtr;
+    std::memcpy(dstPtr, srcPtrOffset, size);
+
+    const VkMappedMemoryRange toFlush = {
+        .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+        .pNext = nullptr,
+        .memory = stagingBufferInfo.memory.memory,
+        .offset = 0,
+        .size = size,
+    };
+    VK_CHECK(vk->vkFlushMappedMemoryRanges(sVkEmulation->device, 1, &toFlush));
+
+    const VkCommandBufferBeginInfo beginInfo = {
+        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+        .pNext = nullptr,
+        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+    };
+
+    VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
+
+    VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
+
+    const VkBufferCopy bufferCopy = {
+        .srcOffset = 0,
+        .dstOffset = offset,
+        .size = size,
+    };
+    vk->vkCmdCopyBuffer(commandBuffer, stagingBufferInfo.buffer, bufferInfo->buffer, 1,
+                        &bufferCopy);
+
+    VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
+
+    const VkSubmitInfo submitInfo = {
+        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+        .pNext = nullptr,
+        .waitSemaphoreCount = 0,
+        .pWaitSemaphores = nullptr,
+        .pWaitDstStageMask = nullptr,
+        .commandBufferCount = 1,
+        .pCommandBuffers = &commandBuffer,
+        .signalSemaphoreCount = 0,
+        .pSignalSemaphores = nullptr,
+    };
+
+    {
+        android::base::AutoLock lock(*sVkEmulation->queueLock);
+        VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
+                                   sVkEmulation->commandBufferFence));
+    }
+
+    static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
+
+    VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
+                                 VK_TRUE, ANB_MAX_WAIT_NS));
+
+    VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
+
+    return true;
+}
+
 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost(
     VkExternalMemoryHandleTypeFlags bits) {
     VkExternalMemoryHandleTypeFlags res = bits;