Introduce GFXSTREAM_ABORT instead of normal abort.

This CL moves most of our abort() callsites to use the new
GFXSTREAM_ABORT macro, which will allow us to track metrics
about when and where we abort.

Generated code is not yet changed, and test and third-party
code is not affected.

Bug: 204125485
Test: Compile, run emulator.

Change-Id: I909d79a35121f24a60e3b4db2745af5ceeee369c
diff --git a/base/Android.bp b/base/Android.bp
index d830c1f..4bce39a 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -27,6 +27,7 @@
         "StdioStream.cpp",
         "MemoryTracker.cpp",
         "MessageChannel.cpp",
+        "MetricsNoOp.cpp",
         "PathUtils.cpp",
         "ring_buffer.cpp",
         "SharedLibrary.cpp",
diff --git a/base/Metrics.h b/base/Metrics.h
index e6ea9c2..faa175e 100644
--- a/base/Metrics.h
+++ b/base/Metrics.h
@@ -25,8 +25,10 @@
 // Events that can be logged.
 struct MetricEventFreeze {};
 struct MetricEventUnFreeze { int64_t frozen_ms; };
+struct GfxstreamVkAbort { int64_t abort_reason; };
 
-using MetricEventType = std::variant<std::monostate, MetricEventFreeze, MetricEventUnFreeze>;
+using MetricEventType =
+    std::variant<std::monostate, MetricEventFreeze, MetricEventUnFreeze, GfxstreamVkAbort>;
 
 class MetricsLogger {
 public:
diff --git a/base/StringUtils.cpp b/base/StringUtils.cpp
index ce835b6..6ee2973 100644
--- a/base/StringUtils.cpp
+++ b/base/StringUtils.cpp
@@ -25,6 +25,8 @@
 #include <string>
 #include <vector>
 
+#include "host-common/GfxstreamFatalError.h"
+
 #ifdef _WIN32
 const void* memmem(const void* haystack, size_t haystackLen,
                    const void* needle, size_t needleLen) {
@@ -126,7 +128,7 @@
 
 #define CHECK_NE(a, b) \
     if ((a) == (b))    \
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
 
 std::vector<std::string> Split(const std::string& s,
                                const std::string& delimiters) {
diff --git a/host-common/AndroidPipe.cpp b/host-common/AndroidPipe.cpp
index 96aa5ca..aae4b0e 100644
--- a/host-common/AndroidPipe.cpp
+++ b/host-common/AndroidPipe.cpp
@@ -21,6 +21,7 @@
 #include "base/Lock.h"
 #include "android_pipe_device.h"
 #include "android_pipe_host.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "DeviceContextRunner.h"
 #include "VmLock.h"
 
@@ -440,9 +441,9 @@
     const int pendingFlags = stream->getBe32();
     if (pendingFlags && pipe && !*pForceClose) {
         if (!hwPipe) {
-            fprintf(stderr, "fatal: AndroidPipe::%s [%s]: hwPipe is NULL (flags = 0x%x)\n",
-                    __func__, pipe->name(), unsigned(pendingFlags));
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "fatal: AndroidPipe [" << pipe->name() << "] hwPipe is NULL(flags = 0x"
+                << std::hex << unsigned(pendingFlags) << " )";
         }
         sGlobals()->pipeWaker.signalWake(hwPipe, pendingFlags);
         DD("%s: singalled wake flags %d for pipe hwpipe=%p", __func__,
@@ -498,9 +499,9 @@
     // i.e., pipe not using normal pipe device
     if (mFlags) return;
     if (!mHwPipe) {
-        fprintf(stderr, "AndroidPipe::%s [%s]: hwPipe is NULL (flags = 0x%x)\n",
-                __func__, name(), (unsigned)wakeFlags);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "AndroidPipe [" << name() << "]: hwPipe is NULL (flags = 0x" << std::hex
+            << unsigned(wakeFlags) << ")";
     }
     sGlobals()->pipeWaker.signalWake(mHwPipe, wakeFlags);
 }
@@ -509,8 +510,8 @@
     // i.e., pipe not using normal pipe device
     if (mFlags) return;
     if (!mHwPipe) {
-        fprintf(stderr, "AndroidPipe::%s [%s]: hwPipe is NULL\n", __func__, name());
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "AndroidPipe [" << name() << "]: hwPipe is NULL";
     }
     sGlobals()->pipeWaker.closeFromHost(mHwPipe);
 }
@@ -520,8 +521,8 @@
     if (mFlags) return;
 
     if (!mHwPipe) {
-        fprintf(stderr, "AndroidPipe::%s [%s]: hwPipe is NULL\n", __func__, name());
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "AndroidPipe [" << name() << "]: hwPipe is NULL";
     }
     sGlobals()->pipeWaker.abortPending(mHwPipe);
 }
@@ -814,10 +815,9 @@
         void* hwPipe = (*cb.first)(id);
         if (hwPipe) {
             if (hwPipeFound) {
-                fprintf(stderr, "%s: Pipe id (%d) is not unique, at least two "
-                        "pipes are found: `%s` and `%s`\n",
-                        __func__, id, tagFound, cb.second);
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                    << "Pipe id (" << id << ") is not unique, at least two pipes are found: `"
+                    << tagFound << "` and `" << cb.second << "`";
             } else {
                 hwPipeFound = hwPipe;
                 tagFound = cb.second;
diff --git a/host-common/GfxstreamFatalError.h b/host-common/GfxstreamFatalError.h
new file mode 100644
index 0000000..4449dbb
--- /dev/null
+++ b/host-common/GfxstreamFatalError.h
@@ -0,0 +1,66 @@
+// Copyright 2021 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 <cstdint>
+#include <ostream>
+#include <sstream>
+#include <vulkan/vulkan.h>
+
+#include "base/Metrics.h"
+#include "host-common/logging.h"
+
+enum GfxstreamAbortReason : int64_t { VK_RESULT, ABORT_REASON_OTHER = -0x1'0000'0000 };
+
+struct FatalError {
+    GfxstreamAbortReason abort_reason;
+    VkResult vk_result;
+
+    FatalError(GfxstreamAbortReason ab_reason) : abort_reason(ab_reason) {}
+    FatalError(VkResult vk_result) : abort_reason(VK_RESULT), vk_result(vk_result) {}
+
+    inline uint64_t getAbortCode() const {
+        return abort_reason == VK_RESULT ? vk_result : abort_reason;
+    }
+};
+
+class AbortMessage {
+   public:
+       AbortMessage(const char *file, const char *function, int line, FatalError reason)
+        : mFile(file), mFunction(function), mLine(line), mReason(reason) {}
+
+     [[noreturn]] ~AbortMessage() {
+           int64_t abortCode = mReason.getAbortCode();
+           fprintf(stderr, "FATAL: %s:%d:%s: (error code: %" PRIi64 ")", mFile, mLine, mFunction,
+                   abortCode);
+           if (!mOss.str().empty()) {
+               fprintf(stderr, ": %s", mOss.str().c_str());
+           }
+           fprintf(stderr, "\n");
+           fflush(stderr);
+           android::base::CreateMetricsLogger()->logMetricEvent(
+               android::base::GfxstreamVkAbort{abortCode});
+           GFXSTREAM_FATAL();
+       }
+
+       std::ostream &stream() { return mOss; }
+    private:
+       const char *mFile, *mFunction;
+       int mLine;
+       FatalError mReason;
+       std::ostringstream mOss;
+};
+
+#define GFXSTREAM_ABORT(reason) AbortMessage(__FILE__, __func__, __LINE__, reason).stream()
diff --git a/host-common/address_space_graphics.cpp b/host-common/address_space_graphics.cpp
index f8315c7..ad59f9e 100644
--- a/host-common/address_space_graphics.cpp
+++ b/host-common/address_space_graphics.cpp
@@ -18,6 +18,7 @@
 #include "host-common/address_space_device.h"
 #include "host-common/vm_operations.h"
 #include "host-common/crash_reporter.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/globals.h"
 #include "base/AlignedBuf.h"
 #include "base/SubAllocator.h"
@@ -347,7 +348,7 @@
                 fillAllocFromLoad(mCombinedBlocks[alloc.blockIndex], alloc);
                 break;
             default:
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
                 break;
         }
     }
diff --git a/host-common/logging.h b/host-common/logging.h
index 2701b8c..ca9d876 100644
--- a/host-common/logging.h
+++ b/host-common/logging.h
@@ -23,4 +23,9 @@
     do {                                    \
         GFXSTREAM_LOG(stderr, __VA_ARGS__); \
         fflush(stderr);                     \
-    } while (0)
\ No newline at end of file
+    } while (0)
+
+#ifndef GFXSTREAM_FATAL
+#define GFXSTREAM_FATAL() abort();
+#endif
+
diff --git a/host-common/opengles.cpp b/host-common/opengles.cpp
index eb52360..e725250 100644
--- a/host-common/opengles.cpp
+++ b/host-common/opengles.cpp
@@ -23,6 +23,7 @@
 #include "host-common/address_space_device.h"
 #include "host-common/address_space_graphics.h"
 #include "host-common/address_space_graphics_types.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/GoldfishDma.h"
 #include "host-common/RefcountPipe.h"
 #include "host-common/FeatureControl.h"
@@ -48,12 +49,12 @@
 //     VERBOSE_PRINT(init,__VA_ARGS__); \
 //     android_opengl_logger_write(__VA_ARGS__); \
 // } while(0);
-// 
+//
 // #define DD(...) do { \
 //     VERBOSE_PRINT(gles,__VA_ARGS__); \
 //     android_opengl_logger_write(__VA_ARGS__); \
 // } while(0);
-// 
+//
 // #define E(fmt,...) do { \
 //     derror(fmt, ##__VA_ARGS__); \
 //     android_opengl_logger_write(fmt "\n", ##__VA_ARGS__); \
@@ -109,36 +110,36 @@
 
     return 0;
 }
-// 
+//
 //     char* error = NULL;
-// 
+//
 //     if (sRenderLib != NULL)
 //         return 0;
-// 
+//
 //     D("Initializing hardware OpenGLES emulation support");
-// 
+//
 //     SharedLibrary* rendererSo =
 //         SharedLibrary::open(RENDERER_LIB_NAME);
 //     if (rendererSo == NULL) {
 //         E("Could not load OpenGLES emulation library [%s]: %s",
 //                RENDERER_LIB_NAME, error);
-// 
+//
 //         E("Retrying in program directory/lib64...");
-// 
+//
 //         auto progDir = System::get()->getProgramDirectory();
-// 
+//
 //         auto retryLibPath =
 //             pj(progDir, "lib64", RENDERER_LIB_NAME);
-// 
+//
 //         rendererSo = adynamicLibrary_open(retryLibPath.c_str(), &error);
-// 
+//
 //         if (rendererSo == nullptr) {
 //             E("Could not load OpenGLES emulation library [%s]: %s (2nd try)",
 //                    retryLibPath.c_str(), error);
 //             return -1;
 //         }
 //     }
-// 
+//
 //     /* Resolve the functions */
 //     if (initOpenglesEmulationFuncs(rendererSo) < 0) {
 //         E("OpenGLES emulation library mismatch. Be sure to use the correct version!");
@@ -146,33 +147,33 @@
 //             "OpenGLES emulation library mismatch. Be sure to use the correct version!");
 //         goto BAD_EXIT;
 //     }
-// 
+//
 //     sRenderLib = initLibrary();
 //     if (!sRenderLib) {
 //         E("OpenGLES initialization failed!");
 //         crashhandler_append_message_format("OpenGLES initialization failed!");
 //         goto BAD_EXIT;
 //     }
-// 
+//
 //     sRendererUsesSubWindow = true;
 //     if (const char* env = getenv("ANDROID_GL_SOFTWARE_RENDERER")) {
 //         if (env[0] != '\0' && env[0] != '0') {
 //             sRendererUsesSubWindow = false;
 //         }
 //     }
-// 
+//
 //     sEgl2egl = false;
 //     if (const char* env = getenv("ANDROID_EGL_ON_EGL")) {
 //         if (env[0] != '\0' && env[0] == '1') {
 //             sEgl2egl = true;
 //         }
 //     }
-// 
+//
 //     sEgl = (const EGLDispatch *)sRenderLib->getEGLDispatch();
 //     sGlesv2 = (const GLESv2Dispatch *)sRenderLib->getGLESv2Dispatch();
-// 
+//
 //     return 0;
-// 
+//
 // BAD_EXIT:
 //     E("OpenGLES emulation library could not be initialized!");
 //     adynamicLibrary_close(rendererSo);
@@ -191,8 +192,8 @@
 }
 
 int android_initOpenglesEmulation() {
-    fprintf(stderr, "%s: Not meant to call android_initOpenglesEmulation in the new build\n", __func__);
-    abort();
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+        << "Not meant to call android_initOpenglesEmulation in the new build.";
 }
 
 int
diff --git a/stream-servers/ChannelStream.cpp b/stream-servers/ChannelStream.cpp
index 2cee81f..7e9bfcf 100644
--- a/stream-servers/ChannelStream.cpp
+++ b/stream-servers/ChannelStream.cpp
@@ -18,6 +18,7 @@
 #define EMUGL_DEBUG_LEVEL  0
 #include "host-common/debug.h"
 #include "host-common/dma_device.h"
+#include "host-common/GfxstreamFatalError.h"
 
 #include <assert.h>
 #include <memory.h>
@@ -106,8 +107,8 @@
 }
 
 const unsigned char *ChannelStream::readFully( void *buf, size_t len) {
-    fprintf(stderr, "%s: FATAL: not intended for use with ChannelStream\n", __func__);
-    abort();
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+        << "not intended for use with ChannelStream";
 }
 
 void ChannelStream::onSave(android::base::Stream* stream) {
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index eefe1a1..f4aeda5 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -440,6 +440,7 @@
     assert(m_yuv_converter.get());
 #endif
 
+
     m_yuv_converter->readPixels((uint8_t*)pixels, pixels_size);
 
     return;
diff --git a/stream-servers/CompositorVk.cpp b/stream-servers/CompositorVk.cpp
index 822c146..4397a49 100644
--- a/stream-servers/CompositorVk.cpp
+++ b/stream-servers/CompositorVk.cpp
@@ -567,9 +567,9 @@
     for (size_t i = 0; i < currentComposition.m_composeLayers.size(); ++i) {
         const auto &layer = currentComposition.m_composeLayers[i];
         if (m_vkSampler != layer->m_vkSampler) {
-            COMPOSITOR_VK_ERROR("Unsupported sampler(%#" PRIxPTR ").",
-                                reinterpret_cast<uintptr_t>(layer->m_vkSampler));
-            std::abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "Unsupported sampler(" << reinterpret_cast<uintptr_t>(layer->m_vkSampler)
+                << ").";
         }
         imageInfos[i] =
             VkDescriptorImageInfo({.sampler = VK_NULL_HANDLE,
diff --git a/stream-servers/DisplayVk.cpp b/stream-servers/DisplayVk.cpp
index 4657a46..060c987 100644
--- a/stream-servers/DisplayVk.cpp
+++ b/stream-servers/DisplayVk.cpp
@@ -5,6 +5,7 @@
 #include <glm/glm.hpp>
 #include <glm/gtx/matrix_transform_2d.hpp>
 
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/logging.h"
 #include "vulkan/VkCommonOperations.h"
 #include "vulkan/VkFormatUtils.h"
@@ -117,9 +118,8 @@
 
     if (!SwapChainStateVk::validateQueueFamilyProperties(m_vk, m_vkPhysicalDevice, surface,
                                                          m_swapChainQueueFamilyIndex)) {
-        DISPLAY_VK_ERROR(
-            "DisplayVk can't create VkSwapchainKHR with given VkDevice and VkSurfaceKHR.");
-        ::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "DisplayVk can't create VkSwapchainKHR with given VkDevice and VkSurfaceKHR.";
     }
     auto swapChainCi = SwapChainStateVk::createSwapChainCi(
         m_vk, surface, m_vkPhysicalDevice, width, height,
@@ -128,10 +128,9 @@
     m_vk.vkGetPhysicalDeviceFormatProperties(m_vkPhysicalDevice, swapChainCi->imageFormat,
                                              &formatProps);
     if (!(formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
-        DISPLAY_VK_ERROR(
-            "DisplayVk: The image format chosen for present VkImage can't be used as the color "
-            "attachment, and therefore can't be used as the render target of CompositorVk.");
-        ::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "DisplayVk: The image format chosen for present VkImage can't be used as the color "
+               "attachment, and therefore can't be used as the render target of CompositorVk.";
     }
     m_swapChainStateVk = std::make_unique<SwapChainStateVk>(m_vk, m_vkDevice, *swapChainCi);
     m_compositorVk = CompositorVk::create(
@@ -183,7 +182,6 @@
     }
 
     std::shared_ptr<PostResource> postResource = m_postResourceFuture.value().get();
-
     VkSemaphore imageReadySem = postResource->m_swapchainImageAcquireSemaphore;
 
     uint32_t imageIndex;
@@ -395,9 +393,8 @@
             targetBuffer->m_vkImageView, targetBuffer->m_vkImageCreateInfo.extent.width,
             targetBuffer->m_vkImageCreateInfo.extent.height);
         if (!compositorVkRenderTarget) {
-            DISPLAY_VK_ERROR(
-                "Fail to create CompositorVkRenderTarget for the target display buffer.");
-            std::abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "Failed to create CompositorVkRenderTarget for the target display buffer.";
         }
         m_compositorVkRenderTargets.pop_back();
         m_compositorVkRenderTargets.push_front(compositorVkRenderTarget);
@@ -407,8 +404,8 @@
     std::future<std::unique_ptr<ComposeResource>> composeResourceFuture =
         std::move(m_composeResourceFuture.value());
     if (!composeResourceFuture.valid()) {
-        DISPLAY_VK_ERROR("Invalid composeResourceFuture in m_postResourceFutures.");
-        std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Invalid composeResourceFuture in m_postResourceFutures.";
     }
     std::unique_ptr<ComposeResource> composeResource = composeResourceFuture.get();
 
@@ -637,8 +634,8 @@
     uint32_t renderTargetIndex, uint32_t numLayers, const ComposeLayer layers[],
     const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers) {
     if (!m_surfaceState) {
-        DISPLAY_VK_ERROR("Haven't bound to a surface, can't compare and save composition.");
-        ::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Haven't bound to a surface, can't compare and save composition.";
     }
     auto [iPrevComposition, compositionNotFound] =
         m_surfaceState->m_prevCompositions.emplace(renderTargetIndex, 0);
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index f284eb0..5a4c70f 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -38,6 +38,7 @@
 
 #include "host-common/crash_reporter.h"
 #include "host-common/feature_control.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/logging.h"
 #include "host-common/misc.h"
 #include "host-common/vm_operations.h"
@@ -1391,7 +1392,7 @@
             // emugl::emugl_crash_reporter(
             //     "FATAL: color buffer with handle %u already exists",
             //     handle);
-            ::abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
         }
 
         resHandle = createColorBufferWithHandleLocked(
@@ -2021,8 +2022,9 @@
 
     GLenum resetStatus = s_gles2.glGetGraphicsResetStatusEXT();
     if (resetStatus != GL_NO_ERROR) {
-        ERR("Stream server aborting due to graphics reset. ResetStatus: %#x", resetStatus);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                "Stream server aborting due to graphics reset. ResetStatus: " <<
+                std::hex << resetStatus;
     }
 
     WindowSurface* surface = (*w).second.first.get();
diff --git a/stream-servers/GfxStreamBackend.cpp b/stream-servers/GfxStreamBackend.cpp
index ba96592..5565141 100644
--- a/stream-servers/GfxStreamBackend.cpp
+++ b/stream-servers/GfxStreamBackend.cpp
@@ -22,6 +22,7 @@
 #include "host-common/android_pipe_device.h"
 #include "host-common/vm_operations.h"
 #include "host-common/window_agent.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/HostmemIdMapping.h"
 #include "host-common/FeatureControl.h"
 #include "host-common/feature_control.h"
@@ -406,11 +407,8 @@
            (renderer_flags & GFXSTREAM_RENDERER_FLAGS_ASYNC_FENCE_CB));
 
     if (useVulkanNativeSwapchain && !enableVk) {
-        fprintf(stderr,
-                "%s: can't enable vulkan native swapchain, Vulkan is disabled, "
-                "fatal\n",
-                __func__);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                            "can't enable vulkan native swapchain, Vulkan is disabled";
     }
 
     emugl::vkDispatch(false /* don't use test ICD */);
@@ -470,8 +468,7 @@
     auto openglesRenderer = android_getOpenglesRenderer();
 
     if (!openglesRenderer) {
-        fprintf(stderr, "%s: no renderer started, fatal\n", __func__);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No renderer started, fatal";
     }
 
     address_space_set_vm_operations(getConsoleAgents()->vm);
diff --git a/stream-servers/PostWorker.cpp b/stream-servers/PostWorker.cpp
index edf851f..7a90f0c 100644
--- a/stream-servers/PostWorker.cpp
+++ b/stream-servers/PostWorker.cpp
@@ -24,6 +24,8 @@
 #include "OpenGLESDispatch/EGLDispatch.h"
 #include "OpenGLESDispatch/GLESv2Dispatch.h"
 #include "RenderThreadInfo.h"
+#include "base/Tracing.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/misc.h"
 #include "vulkan/VkCommonOperations.h"
 
@@ -229,8 +231,8 @@
 // clear() is useful for outputting consistent colors.
 void PostWorker::clearImpl() {
     if (m_displayVk) {
-        POST_ERROR("PostWorker with Vulkan doesn't support clear.");
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "PostWorker with Vulkan doesn't support clear";
     }
 #ifndef __linux__
     s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
@@ -241,8 +243,8 @@
 
 void PostWorker::composeImpl(const ComposeDevice* p) {
     if (m_displayVk) {
-        POST_ERROR("PostWorker with Vulkan doesn't support ComposeV1.");
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "PostWorker with Vulkan doesn't support ComposeV1";
     }
     // bind the subwindow eglSurface
     if (!m_mainThreadPostingOnly && m_needsToRebindWindow) {
@@ -317,8 +319,8 @@
 
     if (m_displayVk) {
         if (!targetColorBufferPtr) {
-            ERR("failed to retrieve the composition target buffer\n");
-            std::abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                                "Failed to retrieve the composition target buffer";
         }
         // We don't copy the render result to the targetHandle color buffer
         // when using the Vulkan native host swapchain, because we directly
@@ -434,8 +436,8 @@
 
 void PostWorker::glesComposeLayer(ComposeLayer* l, uint32_t w, uint32_t h) {
     if (m_displayVk) {
-        POST_ERROR("Should not reach with native Vulkan swapchain enabled.");
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                            "Should not reach with native vulkan swapchain enabled.";
     }
     if (l->composeMode == HWC2_COMPOSITION_DEVICE) {
         ColorBufferPtr cb = mFb->findColorBuffer(l->cbHandle);
@@ -463,9 +465,8 @@
     int rotation,
     void* pixels) {
     if (m_displayVk) {
-        POST_ERROR(
-            "Screenshot not supported with native Vulkan swapchain enabled.");
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                            "Screenshot not supported with native Vulkan swapchain enabled.";
     }
     cb->readPixelsScaled(
         width, height, format, type, rotation, pixels);
diff --git a/stream-servers/RingStream.cpp b/stream-servers/RingStream.cpp
index 3aaea95..2df0797 100644
--- a/stream-servers/RingStream.cpp
+++ b/stream-servers/RingStream.cpp
@@ -20,6 +20,7 @@
 #include "host-common/crash_reporter.h"
 #include "host-common/debug.h"
 #include "host-common/dma_device.h"
+#include "host-common/GfxstreamFatalError.h"
 
 #include <assert.h>
 #include <memory.h>
@@ -276,8 +277,7 @@
     uint32_t available,
     size_t* count, char** current,const char* ptrEnd) {
 
-    fprintf(stderr, "%s: nyi. abort\n", __func__);
-    abort();
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "nyi. abort";
 
     uint32_t xferTotal = available / sizeof(struct asg_type2_xfer);
 
@@ -346,8 +346,7 @@
 }
 
 const unsigned char *RingStream::readFully( void *buf, size_t len) {
-    fprintf(stderr, "%s: FATAL: not intended for use with RingStream\n", __func__);
-    abort();
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "not intended for use with RingStream";
 }
 
 void RingStream::onSave(android::base::Stream* stream) {
diff --git a/stream-servers/SyncThread.cpp b/stream-servers/SyncThread.cpp
index 0ce5a0e..f03b01c 100644
--- a/stream-servers/SyncThread.cpp
+++ b/stream-servers/SyncThread.cpp
@@ -20,6 +20,7 @@
 #include "base/Thread.h"
 #include "OpenGLESDispatch/OpenGLDispatchLoader.h"
 #include "host-common/crash_reporter.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/sync_device.h"
 
 #ifndef _MSC_VER
@@ -51,10 +52,8 @@
 #define SYNC_THREAD_CHECK(condition)                                        \
     do {                                                                    \
         if (!(condition)) {                                                 \
-            fprintf(stderr, "%s(%s:%d): %s is false\n", __func__, __FILE__, \
-                    __LINE__, #condition);                                  \
-            fflush(stderr);                                                 \
-            ::std::abort();                                                 \
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<              \
+                #condition << " is false";                                  \
         }                                                                   \
     } while (0)
 
diff --git a/stream-servers/VirtioGpuTimelines.cpp b/stream-servers/VirtioGpuTimelines.cpp
index c4664d4..df5a1ac 100644
--- a/stream-servers/VirtioGpuTimelines.cpp
+++ b/stream-servers/VirtioGpuTimelines.cpp
@@ -16,12 +16,7 @@
 #include <cinttypes>
 #include <cstdio>
 
-#define VGT_ERROR(fmt, ...)                                                   \
-    do {                                                                      \
-        fprintf(stderr, "%s(%s:%d): " fmt "\n", __func__, __FILE__, __LINE__, \
-                ##__VA_ARGS__);                                               \
-        fflush(stderr);                                                       \
-    } while (0)
+#include "host-common/GfxstreamFatalError.h"
 
 using TaskId = VirtioGpuTimelines::TaskId;
 using CtxId = VirtioGpuTimelines::CtxId;
@@ -56,26 +51,22 @@
     AutoLock lock(mLock);
     auto iTask = mTaskIdToTask.find(taskId);
     if (iTask == mTaskIdToTask.end()) {
-        VGT_ERROR("Task(id = %" PRIu64 ") can't be found.",
-                  static_cast<uint64_t>(taskId));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Task(id = " << static_cast<uint64_t>(taskId) << ") can't be found";
     }
     std::shared_ptr<Task> task = iTask->second.lock();
     if (task == nullptr) {
-        VGT_ERROR("Task(id = %" PRIu64 ") has been destroyed.",
-                  static_cast<uint64_t>(taskId));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been destroyed";
     }
     if (task->mId != taskId) {
-        VGT_ERROR("Task id mismatch. Expected %" PRIu64 ". Actual %" PRIu64,
-                  static_cast<uint64_t>(taskId),
-                  static_cast<uint64_t>(task->mId));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Task id mismatch. Expected " << static_cast<uint64_t>(taskId) << " Actual "
+            << static_cast<uint64_t>(task->mId);
     }
     if (task->mHasCompleted) {
-        VGT_ERROR("Task(id = %" PRIu64 ") has been set to completed.",
-                  static_cast<uint64_t>(taskId));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been set to completed.";
     }
     task->mHasCompleted = true;
     poll_locked(task->mCtxId);
@@ -84,9 +75,8 @@
 void VirtioGpuTimelines::poll_locked(CtxId ctxId) {
     auto iTimelineQueue = mTimelineQueues.find(ctxId);
     if (iTimelineQueue == mTimelineQueues.end()) {
-        VGT_ERROR("Context(id = %" PRIu64 ") doesn't exist.",
-                  static_cast<uint64_t>(ctxId));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Context(id = " << ctxId << " doesn't exist";
     }
     std::list<TimelineItem> &timelineQueue = iTimelineQueue->second;
     auto i = timelineQueue.begin();
@@ -107,4 +97,4 @@
         }
     }
     timelineQueue.erase(timelineQueue.begin(), i);
-}
\ No newline at end of file
+}
diff --git a/stream-servers/glestranslator/EGL/EglGlobalInfo.cpp b/stream-servers/glestranslator/EGL/EglGlobalInfo.cpp
index eb0b6f7..f6fcb97 100644
--- a/stream-servers/glestranslator/EGL/EglGlobalInfo.cpp
+++ b/stream-servers/glestranslator/EGL/EglGlobalInfo.cpp
@@ -19,6 +19,7 @@
 #include "EglDisplay.h"
 #include "EglOsApi.h"
 
+#include "host-common/GfxstreamFatalError.h"
 #include "GLcommon/GLutils.h"
 
 #include <string.h>
@@ -39,7 +40,7 @@
 void EglGlobalInfo::setEgl2Egl(EGLBoolean enable, bool nullEgl) {
     if (nullEgl && enable == EGL_FALSE) {
         // No point in nullEgl backend for non egl2egl cases.
-        std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
     }
     sEgl2Egl = enable;
     setGles2Gles(enable);
diff --git a/stream-servers/glestranslator/EGL/EglImp.cpp b/stream-servers/glestranslator/EGL/EglImp.cpp
index e2b67b2..1886598 100644
--- a/stream-servers/glestranslator/EGL/EglImp.cpp
+++ b/stream-servers/glestranslator/EGL/EglImp.cpp
@@ -30,6 +30,7 @@
 #include "base/Stream.h"
 #include "base/System.h"
 #include "base/SharedLibrary.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/logging.h"
 
 #include "EglWindowSurface.h"
@@ -1080,9 +1081,8 @@
     } else if (r == 5 && g == 5 && b == 5 && a == 1) {
         *colorFormat = GL_RGB5_A1;
     } else {
-        fprintf(stderr, "%s:%d: invalid color format R%dG%dB%dA%d\n", __func__,
-                __LINE__, r, g, b, a);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "invalid color format R" << r << "G" << g << "B" << b << "A" << a;
     }
 
     // Blanket provide 24/8 depth/stencil format for now.
diff --git a/stream-servers/virtio-gpu-gfxstream-renderer.cpp b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
index f3bca54..d93e688 100644
--- a/stream-servers/virtio-gpu-gfxstream-renderer.cpp
+++ b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
@@ -24,6 +24,7 @@
 #include "host-common/HostmemIdMapping.h"
 #include "host-common/address_space_device.h"
 #include "host-common/android_pipe_common.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/opengles.h"
 #include "host-common/vm_operations.h"
 
@@ -46,10 +47,9 @@
 #define VGPLOG(fmt,...)
 #endif
 
-#define VGP_FATAL(fmt,...) do { \
-    fprintf(stderr, "virto-goldfish-pipe fatal error: %s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \
-    abort(); \
-} while(0);
+#define VGP_FATAL()                                    \
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << \
+            "virtio-goldfish-pipe fatal error: "
 
 #ifdef VIRTIO_GOLDFISH_EXPORT_API
 
@@ -235,7 +235,8 @@
         case VIRGL_FORMAT_YV12:
             return true;
         default:
-            VGP_FATAL("Unknown virgl format: 0x%x", format);
+            VGP_FATAL() << "Unknown virgl format 0x" << std::hex << format;
+            return false;
     }
 }
 
@@ -331,7 +332,7 @@
                 bpp = 1;
                 break;
             default:
-                VGP_FATAL("Unknown format: 0x%x", format);
+                VGP_FATAL() << "Unknown format: 0x" << std::hex << format;
         }
 
         uint32_t stride = totalWidth * bpp;
@@ -361,7 +362,7 @@
             uvWidth = totalWidth / 2;
             uvPlaneCount = 2;
         } else {
-            VGP_FATAL("Unknown yuv virgl format: 0x%x", format);
+            VGP_FATAL() << "Unknown yuv virgl format: 0x" << std::hex << format;
         }
         uint32_t uvHeight = totalHeight / 2;
         uint32_t uvStride = align_up_power_of_2(uvWidth, uvAlign);
@@ -391,7 +392,7 @@
                 bpp = 1;
                 break;
             default:
-                VGP_FATAL("Unknown format: 0x%x", format);
+                VGP_FATAL() << "Unknown format: 0x" << std::hex << format;
         }
 
         uint32_t stride = totalWidth * bpp;
@@ -415,13 +416,13 @@
             res->linearSize);
 
     if (box->x > res->args.width || box->y > res->args.height) {
-        VGP_FATAL("Box out of range of resource");
+        VGP_FATAL() << "Box out of range of resource";
     }
     if (box->w == 0U || box->h == 0U) {
-        VGP_FATAL("Empty transfer");
+        VGP_FATAL() << "Empty transfer";
     }
     if (box->x + box->w > res->args.width) {
-        VGP_FATAL("Box overflows resource width");
+        VGP_FATAL() << "Box overflows resource width";
     }
 
     size_t linearBase = virgl_format_to_linear_base(
@@ -440,8 +441,9 @@
     size_t end = start + length;
 
     if (end > res->linearSize) {
-        VGP_FATAL("start + length overflows! linearSize %zu, start %zu length %zu (wanted %zu)",
-                  res->linearSize, start, length, start + length);
+        VGP_FATAL() << "start + length overflows! linearSize "
+            << res->linearSize << " start " << start << " length " << length << " (wanted "
+            << start + length << ")";
     }
 
     uint32_t iovIndex = 0;
@@ -452,7 +454,7 @@
     while (written < length) {
 
         if (iovIndex >= res->numIovs) {
-            VGP_FATAL("write request overflowed numIovs");
+            VGP_FATAL() << "write request overflowed numIovs";
         }
 
         const char* iovBase_const = static_cast<const char*>(res->iov[iovIndex].iov_base);
@@ -476,7 +478,7 @@
                            toWrite);
                     break;
                 default:
-                    VGP_FATAL("Invalid sync dir: %d", dir);
+                    VGP_FATAL() << "Invalid sync dir " << dir;
             }
             written += toWrite;
         }
@@ -525,15 +527,17 @@
         mVirglRendererCallbacks = *callbacks;
         mVirtioGpuOps = android_getVirtioGpuOps();
         if (!mVirtioGpuOps) {
-            VGP_FATAL("Could not get virtio gpu ops!");
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Could not get virtio gpu ops!";
         }
         mReadPixelsFunc = android_getReadPixelsFunc();
         if (!mReadPixelsFunc) {
-            VGP_FATAL("Could not get read pixels func!");
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "Could not get read pixels func!";
         }
         mAddressSpaceDeviceControlOps = get_address_space_device_control_ops();
         if (!mAddressSpaceDeviceControlOps) {
-            VGP_FATAL("Could not get address space device control ops!");
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "Could not get address space device control ops!";
         }
         if (flags & GFXSTREAM_RENDERER_FLAGS_ASYNC_FENCE_CB) {
             VGPLOG("Using async fence cb.");
@@ -551,8 +555,8 @@
         VirglCtxId asCtxId = (VirglCtxId)(uintptr_t)hwPipe;
         auto it = mContexts.find(asCtxId);
         if (it == mContexts.end()) {
-            fprintf(stderr, "%s: fatal: pipe id %u not found\n", __func__, asCtxId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "fatal: pipe id " << asCtxId << " not found";
         }
 
         auto& entry = it->second;
@@ -570,8 +574,8 @@
         for (auto resId : resIds) {
             auto resEntryIt = mResources.find(resId);
             if (resEntryIt == mResources.end()) {
-                fprintf(stderr, "%s: fatal: res id %u entry not found\n", __func__, resId);
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                    << "res id " << resId << " entry not found";
             }
 
             auto& resEntry = resEntryIt->second;
@@ -637,9 +641,8 @@
     void setContextAddressSpaceHandleLocked(VirglCtxId ctxId, uint32_t handle) {
         auto ctxIt = mContexts.find(ctxId);
         if (ctxIt == mContexts.end()) {
-            fprintf(stderr, "%s: fatal: ctx id %u not found\n", __func__,
-                    ctxId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "ctx id " << ctxId << " not found";
         }
 
         auto& ctxEntry = ctxIt->second;
@@ -650,17 +653,15 @@
     uint32_t getAddressSpaceHandleLocked(VirglCtxId ctxId) {
         auto ctxIt = mContexts.find(ctxId);
         if (ctxIt == mContexts.end()) {
-            fprintf(stderr, "%s: fatal: ctx id %u not found\n", __func__,
-                    ctxId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "ctx id " << ctxId << " not found ";
         }
 
         auto& ctxEntry = ctxIt->second;
 
         if (!ctxEntry.hasAddressSpaceHandle) {
-            fprintf(stderr, "%s: fatal: ctx id %u doesn't have address space handle\n", __func__,
-                    ctxId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "ctx id " << ctxId << " doesn't have address space handle";
         }
 
         return ctxEntry.addressSpaceHandle;
@@ -670,15 +671,15 @@
 
         auto resEntryIt = mResources.find(resId);
         if (resEntryIt == mResources.end()) {
-            fprintf(stderr, "%s: fatal: resid %u not found\n", __func__, resId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << " resid " << resId << " not found";
         }
 
         auto& resEntry = resEntryIt->second;
 
         if (!resEntry.iov) {
-            fprintf(stderr, "%s: fatal:resid %u had empty iov\n", __func__, resId);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "resid " << resId << " has empty iov ";
         }
 
         uint32_t* iovWords = (uint32_t*)(resEntry.iov[0].iov_base);
diff --git a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
index 9f92bcf..4a8f363 100644
--- a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
+++ b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
@@ -15,6 +15,7 @@
 #include "cereal/common/goldfish_vk_private_defs.h"
 #include "cereal/common/goldfish_vk_extension_structs.h"
 
+#include "host-common/GfxstreamFatalError.h"
 #include "stream-servers/FrameBuffer.h"
 #include "GrallocDefs.h"
 #include "VkCommonOperations.h"
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index fc95906..330324f 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -34,6 +34,7 @@
 #include "base/System.h"
 #include "base/Tracing.h"
 #include "common/goldfish_vk_dispatch.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/vm_operations.h"
 
 #ifdef _WIN32
@@ -792,7 +793,6 @@
 
     sVkEmulation->physdev = physdevs[maxScoringIndex];
     sVkEmulation->deviceInfo = deviceInfos[maxScoringIndex];
-
     // Postcondition: sVkEmulation has valid device support info
 
     // Ask about image format support here.
@@ -1876,7 +1876,6 @@
     bool readRes = FrameBuffer::getFB()->
         readColorBufferContents(
             colorBufferHandle, &cbNumBytes, nullptr);
-
     if (!readRes) {
         fprintf(stderr, "%s: Failed to read color buffer 0x%x\n",
                 __func__, colorBufferHandle);
@@ -2008,7 +2007,7 @@
             });
         }
     }
-        
+
     vk->vkCmdCopyBufferToImage(
         sVkEmulation->commandBuffer,
         sVkEmulation->staging.buffer,
@@ -2469,8 +2468,8 @@
         if (res == VK_NOT_READY) {
             continue;
         }
-        VK_COMMON_ERROR("Invalid fence state: %d", static_cast<int>(res));
-        ::std::abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Invalid fence state: " << static_cast<int>(res);
     }
     VkCommandBuffer commandBuffer;
     VkCommandBufferAllocateInfo allocateInfo = {
@@ -2504,9 +2503,7 @@
 void acquireColorBuffersForHostComposing(const std::vector<uint32_t>& layerColorBuffers,
                                          uint32_t renderTargetColorBuffer) {
     if (!sVkEmulation || !sVkEmulation->live) {
-        VK_COMMON_ERROR("Host Vulkan device lost.");
-        ::std::abort();
-        return;
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
     }
 
     std::vector<std::tuple<uint32_t, VkImageLayout>> colorBuffersAndLayouts;
@@ -2647,9 +2644,7 @@
 static VkFence doReleaseColorBufferForGuestRendering(
     const std::vector<uint32_t>& colorBufferHandles) {
     if (!sVkEmulation || !sVkEmulation->live) {
-        VK_COMMON_ERROR("Host Vulkan device lost.");
-        ::std::abort();
-        return VK_NULL_HANDLE;
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
     }
 
     AutoLock lock(sVkEmulationLock);
@@ -2772,9 +2767,7 @@
 void releaseColorBufferFromHostComposingSync(const std::vector<uint32_t>& colorBufferHandles) {
     VkFence fence = doReleaseColorBufferForGuestRendering(colorBufferHandles);
     if (!sVkEmulation || !sVkEmulation->live) {
-        VK_COMMON_ERROR("Host Vulkan device lost.");
-        ::std::abort();
-        return;
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
     }
 
     AutoLock lock(sVkEmulationLock);
diff --git a/stream-servers/vulkan/VkDecoderGlobalState.cpp b/stream-servers/vulkan/VkDecoderGlobalState.cpp
index d480316..24139fc 100644
--- a/stream-servers/vulkan/VkDecoderGlobalState.cpp
+++ b/stream-servers/vulkan/VkDecoderGlobalState.cpp
@@ -44,6 +44,7 @@
 #include "common/goldfish_vk_deepcopy.h"
 #include "common/goldfish_vk_dispatch.h"
 #include "host-common/address_space_device_control_ops.h"
+#include "host-common/GfxstreamFatalError.h"
 #include "host-common/vm_operations.h"
 #include "host-common/feature_control.h"
 #include "vk_util.h"
@@ -456,8 +457,8 @@
 
         if (m_emu->instanceSupportsMoltenVK) {
             if (!m_vk->vkSetMTLTextureMVK) {
-                fprintf(stderr, "Cannot find vkSetMTLTextureMVK\n");
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                        "Cannot find vkSetMTLTextureMVK";
             }
         }
 
@@ -3032,11 +3033,8 @@
             vk_find_struct<VkExportMemoryAllocateInfo>(pAllocateInfo);
 
         if (exportAllocInfoPtr) {
-            fprintf(stderr,
-                    "%s: Fatal: Export allocs are to be handled "
-                    "on the guest side / VkCommonOperations.\n",
-                    __func__);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                "Export allocs are to be handled on the guest side / VkCommonOperations.";
         }
 
         const VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
@@ -4370,7 +4368,7 @@
                 currSi.pWaitSemaphores = pBindInfo[i].pWaitSemaphores;
                 waitDstStageMasks.resize(pBindInfo[i].waitSemaphoreCount, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
                 currSi.pWaitDstStageMask = waitDstStageMasks.data();
-                
+
                 currSi.signalSemaphoreCount = 0;
                 currSi.pSignalSemaphores = nullptr;
 
@@ -4515,8 +4513,8 @@
 
         auto poolInfo = android::base::find(mDescriptorPoolInfo, pool);
         if (!poolInfo) {
-            fprintf(stderr, "%s: FATAL: descriptor pool %p not found\n", __func__, pool);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "descriptor pool " << pool << " not found ";
         }
 
         DispatchableHandleInfo<uint64_t>* setHandleInfo = sBoxedHandleManager.get(poolId);
@@ -4555,9 +4553,10 @@
                 *didAlloc = true;
                 return allocedSet;
             } else {
-                fprintf(stderr, "%s: FATAL: descriptor pool %p wanted to get set with id 0x%llx but it wasn't allocated\n", __func__,
-                        pool, (unsigned long long)poolId);
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                        << "descriptor pool " << pool << " wanted to get set with id 0x" <<
+                        std::hex << poolId;
+                return nullptr;
             }
         }
     }
@@ -4587,9 +4586,8 @@
         if (queueInfo) {
             device = queueInfo->device;
         } else {
-            fprintf(stderr, "%s: FATAL: queue %p (boxed: %p) with no device registered\n", __func__,
-                    queue, boxed_queue);
-            abort();
+            GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                << "queue " << queue << "(boxed: " << boxed_queue << ") with no device registered";
         }
 
         std::vector<VkDescriptorSet> setsToUpdate(descriptorSetCount, nullptr);
@@ -6259,8 +6257,8 @@
             } else if (isDescriptorTypeBufferView(type)) {
                 numBufferViews += count;
             } else {
-                fprintf(stderr, "%s: fatal: unknown descriptor type 0x%x\n", __func__, type);
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                    << "unknown descriptor type 0x" << std::hex << type;
             }
         }
 
@@ -6303,8 +6301,8 @@
                 entryForHost.stride = sizeof(VkBufferView);
                 ++bufferViewCount;
             } else {
-                fprintf(stderr, "%s: fatal: unknown descriptor type 0x%x\n", __func__, type);
-                abort();
+                GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+                    << "unknown descriptor type 0x" << std::hex << type;
             }
 
             res.linearizedTemplateEntries.push_back(entryForHost);
diff --git a/stream-servers/vulkan/VulkanStream.cpp b/stream-servers/vulkan/VulkanStream.cpp
index 9529c10..7c326d4 100644
--- a/stream-servers/vulkan/VulkanStream.cpp
+++ b/stream-servers/vulkan/VulkanStream.cpp
@@ -18,6 +18,7 @@
 #include "base/BumpPool.h"
 
 #include "host-common/feature_control.h"
+#include "host-common/GfxstreamFatalError.h"
 
 #include <vector>
 
@@ -56,12 +57,12 @@
         *ptrAddr = nullptr;
         return;
     }
-    
+
     *ptrAddr = mPool.alloc(bytes);
 
     if (!*ptrAddr) {
-        fprintf(stderr, "%s: FATAL: alloc failed. Wanted size: %zu\n", __func__, bytes);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                "alloc failed. Wanted size: " << bytes;
     }
 }
 
@@ -99,10 +100,8 @@
     android::base::Stream::fromBe32((uint8_t*)&len);
 
     if (len == UINT32_MAX) {
-        fprintf(stderr,
-                "%s: FATAL: VulkanStream can't allocate %u bytes\n",
-                __func__, UINT32_MAX);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                "VulkanStream can't allocate UINT32_MAX bytes";
     }
 
     alloc((void**)forOutput, len + 1);
@@ -137,8 +136,8 @@
 ssize_t VulkanStream::read(void *buffer, size_t size) {
     commitWrite();
     if (!mStream->readFully(buffer, size)) {
-        E("FATAL: Could not read back %zu bytes", size);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Could not read back " << size << " bytes";
     }
     return size;
 }
@@ -162,16 +161,16 @@
 
 void VulkanStream::commitWrite() {
     if (!valid()) {
-        E("FATAL: Tried to commit write to vulkan pipe with invalid pipe!");
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+                            "Tried to commit write to vulkan pipe with invalid pipe!";
     }
-    
+
     int written =
         mStream->writeFully(mWriteBuffer.data(), mWritePos);
-    
+
     if (written) {
-        E("FATAL: Did not write exactly %zu bytes!", mWritePos);
-        abort();
+        GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+            << "Did not write exactly " << mWritePos << " bytes!";
     }
     mWritePos = 0;
 }
@@ -226,10 +225,8 @@
 }
 
 ssize_t VulkanMemReadingStream::write(const void* buffer, size_t size) {
-    fprintf(stderr,
-            "%s: FATAL: VulkanMemReadingStream does not support writing\n",
-            __func__);
-    abort();
+    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) <<
+            "VulkanMemReadingStream does not support writing";
 }
 
 uint8_t* VulkanMemReadingStream::beginTrace() {
diff --git a/stream-servers/vulkan/vk_util.h b/stream-servers/vulkan/vk_util.h
index 92c0469..053f2e4 100644
--- a/stream-servers/vulkan/vk_util.h
+++ b/stream-servers/vulkan/vk_util.h
@@ -35,6 +35,8 @@
 
 #include "base/Lock.h"
 #include "common/vk_struct_id.h"
+#include "VkCommonOperations.h"
+#include "host-common/GfxstreamFatalError.h"
 
 struct vk_struct_common {
     VkStructureType sType;
@@ -267,9 +269,7 @@
     do {                                                                 \
         VkResult err = x;                                                \
         if (err != VK_SUCCESS) {                                         \
-            ::fprintf(stderr, "%s(%u) %s: %s failed, error code = %d\n", \
-                      __FILE__, __LINE__, __FUNCTION__, #x, err);        \
-            ::abort();                                                   \
+            GFXSTREAM_ABORT(FatalError(err));                            \
         }                                                                \
     } while (0)