[host-build] libOpenglSystemCommon build for host

- Make the thread id getting platform agnostic
- Make QemuPipeStream run either with a real pipe device or
a host-side one
- Split out host versions of stuff, like goldfish_dma_host.cpp

bug: 116524589

Change-Id: Iac8c3161d68e9e71f0e14adecf42ca982d48628e
diff --git a/system/OpenglSystemCommon/Android.mk b/system/OpenglSystemCommon/Android.mk
index 7d34e67..9071cbe 100644
--- a/system/OpenglSystemCommon/Android.mk
+++ b/system/OpenglSystemCommon/Android.mk
@@ -4,12 +4,25 @@
 $(call emugl-import,libGLESv1_enc libGLESv2_enc lib_renderControl_enc)
 
 LOCAL_SRC_FILES := \
-    goldfish_dma.cpp \
     FormatConversions.cpp \
     HostConnection.cpp \
-    ProcessPipe.cpp    \
     QemuPipeStream.cpp \
-    ThreadInfo.cpp
+    ProcessPipe.cpp    \
+
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+
+LOCAL_SRC_FILES += \
+    goldfish_dma_host.cpp \
+    ThreadInfo_host.cpp \
+    qemu_pipe_host.cpp \
+
+else
+
+LOCAL_SRC_FILES += \
+    goldfish_dma.cpp \
+    ThreadInfo.cpp \
+
+endif
 
 ifneq ($(filter virgl, $(BOARD_GPU_DRIVERS)),)
 LOCAL_CFLAGS += -DVIRTIO_GPU
@@ -31,4 +44,8 @@
 
 $(call emugl-export,C_INCLUDES,$(LOCAL_PATH) bionic/libc/private)
 
+ifeq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST))
+$(call emugl-export,SHARED_LIBRARIES,android-emu-shared)
+endif
+
 $(call emugl-end-module)
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index f56e3f5..d04b671 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -119,7 +119,6 @@
                     return NULL;
                 }
                 con->m_stream = stream;
-                con->m_pipeFd = stream->getSocket();
                 con->m_grallocHelper = &m_goldfishGralloc;
                 con->m_processPipe = &m_goldfishProcessPipe;
                 break;
@@ -171,7 +170,8 @@
         *pClientFlags = 0;
         con->m_stream->commitBuffer(sizeof(unsigned int));
 
-        ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
+        ALOGD("HostConnection::get() New Host Connection established %p, tid %d\n",
+              con, getCurrentThreadId());
         tinfo->hostConn = con;
     }
 
@@ -196,7 +196,8 @@
 {
     if (!m_glEnc) {
         m_glEnc = new GLEncoder(m_stream, checksumHelper());
-        DBG("HostConnection::glEncoder new encoder %p, tid %d", m_glEnc, gettid());
+        DBG("HostConnection::glEncoder new encoder %p, tid %d",
+            m_glEnc, getCurrentThreadId());
         m_glEnc->setContextAccessor(s_getGLContext);
     }
     return m_glEnc;
@@ -206,7 +207,8 @@
 {
     if (!m_gl2Enc) {
         m_gl2Enc = new GL2Encoder(m_stream, checksumHelper());
-        DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid());
+        DBG("HostConnection::gl2Encoder new encoder %p, tid %d",
+            m_gl2Enc, getCurrentThreadId());
         m_gl2Enc->setContextAccessor(s_getGL2Context);
         m_gl2Enc->setNoHostError(m_noHostError);
     }
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index e3dbe80..9c0d2b0 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -99,7 +99,7 @@
         goldfish_dma_lock(m_dmaCxt);
         goldfish_dma_write(m_dmaCxt, data, size);
         uint64_t paddr = goldfish_dma_guest_paddr(m_dmaCxt);
-        ALOGV("%s: paddr=0x%llx", __FUNCTION__, paddr);
+        ALOGV("%s: paddr=0x%llx", __FUNCTION__, (unsigned long long)paddr);
         return paddr;
     }
     void setGLESMaxVersion(GLESMaxVersion ver) { m_glesMaxVersion = ver; }
@@ -154,8 +154,6 @@
 
     bool isGrallocOnly() const { return m_grallocOnly; }
 
-    int getPipeFd() const { return m_pipeFd; }
-
 private:
     HostConnection();
     static gl_client_context_t  *s_getGLContext();
@@ -180,7 +178,6 @@
     ProcessPipe *m_processPipe;
     std::string m_glExtensions;
     bool m_grallocOnly;
-    int m_pipeFd;
     bool m_noHostError;
 };
 
diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp
index 127f273..08e9571 100644
--- a/system/OpenglSystemCommon/ProcessPipe.cpp
+++ b/system/OpenglSystemCommon/ProcessPipe.cpp
@@ -19,8 +19,9 @@
 
 #include <cutils/log.h>
 #include <pthread.h>
+#include <errno.h>
 
-static int                sProcPipe = 0;
+static QEMU_PIPE_HANDLE   sProcPipe = 0;
 static pthread_once_t     sProcPipeOnce = PTHREAD_ONCE_INIT;
 // sProcUID is a unique ID per process assigned by the host.
 // It is different from getpid().
@@ -35,7 +36,7 @@
 // host.
 static void processPipeInitOnce() {
     sProcPipe = qemu_pipe_open("GLProcessPipe");
-    if (sProcPipe < 0) {
+    if (!qemu_pipe_valid(sProcPipe)) {
         sProcPipe = 0;
         ALOGW("Process pipe failed");
         return;
@@ -44,12 +45,13 @@
     int32_t confirmInt = 100;
     ssize_t stat = 0;
     do {
-        stat = ::write(sProcPipe, (const char*)&confirmInt,
+        stat =
+            qemu_pipe_write(sProcPipe, (const char*)&confirmInt,
                 sizeof(confirmInt));
     } while (stat < 0 && errno == EINTR);
 
     if (stat != sizeof(confirmInt)) { // failed
-        close(sProcPipe);
+        qemu_pipe_close(sProcPipe);
         sProcPipe = 0;
         ALOGW("Process pipe failed");
         return;
@@ -57,12 +59,13 @@
 
     // Ask the host for per-process unique ID
     do {
-        stat = ::read(sProcPipe, (char*)&sProcUID,
-                      sizeof(sProcUID));
+        stat =
+            qemu_pipe_read(sProcPipe, (char*)&sProcUID,
+                sizeof(sProcUID));
     } while (stat < 0 && errno == EINTR);
 
     if (stat != sizeof(sProcUID)) {
-        close(sProcPipe);
+        qemu_pipe_close(sProcPipe);
         sProcPipe = 0;
         sProcUID = 0;
         ALOGW("Process pipe failed");
diff --git a/system/OpenglSystemCommon/QemuPipeStream.cpp b/system/OpenglSystemCommon/QemuPipeStream.cpp
index 58703bf..451f0db 100644
--- a/system/OpenglSystemCommon/QemuPipeStream.cpp
+++ b/system/OpenglSystemCommon/QemuPipeStream.cpp
@@ -14,8 +14,8 @@
 * limitations under the License.
 */
 #include "QemuPipeStream.h"
-#include "qemu_pipe.h"
 
+#include <cutils/log.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -24,13 +24,13 @@
 
 QemuPipeStream::QemuPipeStream(size_t bufSize) :
     IOStream(bufSize),
-    m_sock(-1),
+    m_sock((QEMU_PIPE_HANDLE)(-1)),
     m_bufsize(bufSize),
     m_buf(NULL)
 {
 }
 
-QemuPipeStream::QemuPipeStream(int sock, size_t bufSize) :
+QemuPipeStream::QemuPipeStream(QEMU_PIPE_HANDLE sock, size_t bufSize) :
     IOStream(bufSize),
     m_sock(sock),
     m_bufsize(bufSize),
@@ -40,9 +40,9 @@
 
 QemuPipeStream::~QemuPipeStream()
 {
-    if (m_sock >= 0) {
+    if (valid()) {
         flush();
-        ::close(m_sock);
+        qemu_pipe_close(m_sock);
     }
     if (m_buf != NULL) {
         free(m_buf);
@@ -52,9 +52,10 @@
 
 int QemuPipeStream::connect(void)
 {
-     m_sock = qemu_pipe_open("opengles");
+    m_sock = qemu_pipe_open("opengles");
     if (!valid()) {
-        ALOGE("%s: failed with fd %d errno %d", __FUNCTION__, m_sock, errno);
+        ALOGE("%s: failed to connect to opengles pipe", __FUNCTION__);
+        qemu_pipe_print_error(m_sock);
         return -1;
     }
     return 0;
@@ -72,7 +73,7 @@
             m_buf = p;
             m_bufsize = allocSize;
         } else {
-            ERR("realloc (%d) failed\n", allocSize);
+            ERR("realloc (%zu) failed\n", allocSize);
             free(m_buf);
             m_buf = NULL;
             m_bufsize = 0;
@@ -95,7 +96,7 @@
        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 %d,"
+           ERR("QemuPipeStream::writeFully failed, buf=NULL, len %zu,"
                    " lethal error, exiting", len);
            abort();
        }
@@ -106,7 +107,7 @@
     int retval = 0;
 
     while (res > 0) {
-        ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res);
+        ssize_t stat = qemu_pipe_write(m_sock, (const char *)(buf) + (len - res), res);
         if (stat > 0) {
             res -= stat;
             continue;
@@ -128,7 +129,7 @@
     return retval;
 }
 
-int QemuPipeStream::getSocket() const {
+QEMU_PIPE_HANDLE QemuPipeStream::getSocket() const {
     return m_sock;
 }
 
@@ -148,7 +149,7 @@
     }
     size_t res = len;
     while (res > 0) {
-        ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, res);
+        ssize_t stat = qemu_pipe_read(m_sock, (char *)(buf) + len - res, res);
         if (stat == 0) {
             // client shutdown;
             return NULL;
@@ -195,7 +196,7 @@
     char* p = (char *)buf;
     int ret = 0;
     while(len > 0) {
-        int res = ::read(m_sock, p, len);
+        int res = qemu_pipe_read(m_sock, p, len);
         if (res > 0) {
             p += res;
             ret += res;
diff --git a/system/OpenglSystemCommon/QemuPipeStream.h b/system/OpenglSystemCommon/QemuPipeStream.h
index 15f74e6..0884d57 100644
--- a/system/OpenglSystemCommon/QemuPipeStream.h
+++ b/system/OpenglSystemCommon/QemuPipeStream.h
@@ -23,6 +23,8 @@
 #include <stdlib.h>
 #include "IOStream.h"
 
+#include "qemu_pipe.h"
+
 class QemuPipeStream : public IOStream {
 public:
     typedef enum { ERR_INVALID_SOCKET = -1000 } QemuPipeStreamError;
@@ -36,17 +38,17 @@
     virtual const unsigned char *readFully( void *buf, size_t len);
     virtual const unsigned char *read( void *buf, size_t *inout_len);
 
-    bool valid() { return m_sock >= 0; }
+    bool valid() { return qemu_pipe_valid(m_sock); }
     int recv(void *buf, size_t len);
 
     virtual int writeFully(const void *buf, size_t len);
 
-    int getSocket() const;
+    QEMU_PIPE_HANDLE getSocket() const;
 private:
-    int m_sock;
+    QEMU_PIPE_HANDLE m_sock;
     size_t m_bufsize;
     unsigned char *m_buf;
-    QemuPipeStream(int sock, size_t bufSize);
+    QemuPipeStream(QEMU_PIPE_HANDLE sock, size_t bufSize);
 };
 
 #endif
diff --git a/system/OpenglSystemCommon/ThreadInfo.cpp b/system/OpenglSystemCommon/ThreadInfo.cpp
index 425904e..32bb54e 100644
--- a/system/OpenglSystemCommon/ThreadInfo.cpp
+++ b/system/OpenglSystemCommon/ThreadInfo.cpp
@@ -16,6 +16,9 @@
 #include "ThreadInfo.h"
 #include "cutils/threads.h"
 
+#include <bionic_tls.h>
+#include <pthread.h>
+
 thread_store_t s_tls = THREAD_STORE_INITIALIZER;
 
 static bool sDefaultTlsDestructorCallback(__attribute__((__unused__)) void* ptr) {
@@ -51,3 +54,21 @@
 
     return ti;
 }
+
+EGLThreadInfo* getEGLThreadInfo() {
+#ifdef __ANDROID__
+    EGLThreadInfo *tInfo =
+        (EGLThreadInfo *)(((uintptr_t *)__get_tls())[TLS_SLOT_OPENGL]);
+    if (!tInfo) {
+        tInfo = goldfish_get_egl_tls();
+        ((uintptr_t *)__get_tls())[TLS_SLOT_OPENGL] = (uintptr_t)tInfo;
+    }
+    return tInfo;
+#else
+    return goldfish_get_egl_tls();
+#endif
+}
+
+int32_t getCurrentThreadId() {
+    return (int32_t)gettid();
+}
diff --git a/system/OpenglSystemCommon/ThreadInfo.h b/system/OpenglSystemCommon/ThreadInfo.h
index 57fd5ef..7d2260a 100644
--- a/system/OpenglSystemCommon/ThreadInfo.h
+++ b/system/OpenglSystemCommon/ThreadInfo.h
@@ -17,9 +17,9 @@
 #define _THREAD_INFO_H
 
 #include "HostConnection.h"
-#include <pthread.h>
 
-#include <bionic_tls.h>
+#include <inttypes.h>
+
 struct EGLContext_t;
 
 struct EGLThreadInfo
@@ -31,24 +31,13 @@
     int           eglError;
 };
 
-
 typedef bool (*tlsDtorCallback)(void*);
 void setTlsDestructor(tlsDtorCallback);
 
 extern "C" __attribute__((visibility("default"))) EGLThreadInfo *goldfish_get_egl_tls();
 
-inline EGLThreadInfo* getEGLThreadInfo() {
-#ifdef __ANDROID__
-    EGLThreadInfo *tInfo =
-        (EGLThreadInfo *)(((uintptr_t *)__get_tls())[TLS_SLOT_OPENGL]);
-    if (!tInfo) {
-        tInfo = goldfish_get_egl_tls();
-        ((uintptr_t *)__get_tls())[TLS_SLOT_OPENGL] = (uintptr_t)tInfo;
-    }
-    return tInfo;
-#else
-    return goldfish_get_egl_tls();
-#endif
-}
+EGLThreadInfo* getEGLThreadInfo();
+
+int32_t getCurrentThreadId();
 
 #endif // of _THREAD_INFO_H
diff --git a/system/OpenglSystemCommon/ThreadInfo_host.cpp b/system/OpenglSystemCommon/ThreadInfo_host.cpp
new file mode 100644
index 0000000..8492039
--- /dev/null
+++ b/system/OpenglSystemCommon/ThreadInfo_host.cpp
@@ -0,0 +1,37 @@
+// 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 "ThreadInfo.h"
+
+#include "android/base/threads/Thread.h"
+
+EGLThreadInfo *goldfish_get_egl_tls()
+{
+    return 0;
+    // EGLThreadInfo* ti = (EGLThreadInfo*)thread_store_get(&s_tls);
+
+    // if (ti) return ti;
+
+    // ti = new EGLThreadInfo();
+    // thread_store_set(&s_tls, ti, tlsDestruct);
+
+    // return ti;
+}
+
+EGLThreadInfo* getEGLThreadInfo() {
+    return goldfish_get_egl_tls();
+}
+
+int32_t getCurrentThreadId() {
+    return (int32_t)android::base::getCurrentThreadId();
+}
diff --git a/system/OpenglSystemCommon/goldfish_dma.cpp b/system/OpenglSystemCommon/goldfish_dma.cpp
index 046367d..2d7c298 100644
--- a/system/OpenglSystemCommon/goldfish_dma.cpp
+++ b/system/OpenglSystemCommon/goldfish_dma.cpp
@@ -16,10 +16,34 @@
 #include "qemu_pipe.h"
 
 #include <cutils/log.h>
+#include <errno.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <sys/cdefs.h>
 #include <sys/mman.h>
+#include <fcntl.h>
+#include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 
+/* There is an ioctl associated with goldfish dma driver.
+ * Make it conflict with ioctls that are not likely to be used
+ * in the emulator.
+ * 'G'	00-3F	drivers/misc/sgi-gru/grulib.h	conflict!
+ * 'G'	00-0F	linux/gigaset_dev.h	conflict!
+ */
+#define GOLDFISH_DMA_IOC_MAGIC	'G'
+
+#define GOLDFISH_DMA_IOC_LOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 0, struct goldfish_dma_ioctl_info)
+#define GOLDFISH_DMA_IOC_UNLOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 1, struct goldfish_dma_ioctl_info)
+#define GOLDFISH_DMA_IOC_GETOFF			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 2, struct goldfish_dma_ioctl_info)
+#define GOLDFISH_DMA_IOC_CREATE_REGION	_IOWR(GOLDFISH_DMA_IOC_MAGIC, 3, struct goldfish_dma_ioctl_info)
+
+struct goldfish_dma_ioctl_info {
+    uint64_t phys_begin;
+    uint64_t size;
+};
+
 int goldfish_dma_lock(struct goldfish_dma_context* cxt) {
     struct goldfish_dma_ioctl_info info;
 
diff --git a/system/OpenglSystemCommon/goldfish_dma.h b/system/OpenglSystemCommon/goldfish_dma.h
index 6c1b09a..1350ace 100644
--- a/system/OpenglSystemCommon/goldfish_dma.h
+++ b/system/OpenglSystemCommon/goldfish_dma.h
@@ -15,30 +15,7 @@
 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_DMA_H
 
-#include <errno.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#include <sys/cdefs.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-/* There is an ioctl associated with goldfish dma driver.
- * Make it conflict with ioctls that are not likely to be used
- * in the emulator.
- * 'G'	00-3F	drivers/misc/sgi-gru/grulib.h	conflict!
- * 'G'	00-0F	linux/gigaset_dev.h	conflict!
- */
-#define GOLDFISH_DMA_IOC_MAGIC	'G'
-
-#define GOLDFISH_DMA_IOC_LOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 0, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_UNLOCK			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 1, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_GETOFF			_IOWR(GOLDFISH_DMA_IOC_MAGIC, 2, struct goldfish_dma_ioctl_info)
-#define GOLDFISH_DMA_IOC_CREATE_REGION	_IOWR(GOLDFISH_DMA_IOC_MAGIC, 3, struct goldfish_dma_ioctl_info)
-
-struct goldfish_dma_ioctl_info {
-    uint64_t phys_begin;
-    uint64_t size;
-};
+#include <inttypes.h>
 
 // userspace interface
 struct goldfish_dma_context {
diff --git a/system/OpenglSystemCommon/goldfish_dma_host.cpp b/system/OpenglSystemCommon/goldfish_dma_host.cpp
new file mode 100644
index 0000000..4e07c11
--- /dev/null
+++ b/system/OpenglSystemCommon/goldfish_dma_host.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 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_dma.h"
+
+int goldfish_dma_lock(struct goldfish_dma_context* cxt) {
+    return 0;
+}
+
+int goldfish_dma_unlock(struct goldfish_dma_context* cxt) {
+    return 0;
+}
+
+int goldfish_dma_create_region(uint32_t sz, struct goldfish_dma_context* res) {
+    return 0;
+}
+
+void* goldfish_dma_map(struct goldfish_dma_context* cxt) {
+    return 0;
+}
+
+int goldfish_dma_unmap(struct goldfish_dma_context* cxt) {
+    return 0;
+}
+
+void goldfish_dma_write(struct goldfish_dma_context* cxt,
+                               const void* to_write,
+                               uint32_t sz) {
+}
+
+void goldfish_dma_free(goldfish_dma_context* cxt) {
+}
+
+uint64_t goldfish_dma_guest_paddr(struct goldfish_dma_context* cxt) {
+    return 0;
+}
+
diff --git a/system/OpenglSystemCommon/qemu_pipe.h b/system/OpenglSystemCommon/qemu_pipe.h
index 52f4ee7..4b1aaf2 100644
--- a/system/OpenglSystemCommon/qemu_pipe.h
+++ b/system/OpenglSystemCommon/qemu_pipe.h
@@ -16,6 +16,28 @@
 #ifndef ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
 #define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
 
+#ifdef HOST_BUILD
+
+#include <sys/types.h>
+
+typedef void* QEMU_PIPE_HANDLE;
+
+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;
+
+#include <cutils/log.h>
 #include <sys/cdefs.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -30,7 +52,7 @@
 #  define  D(...)   do{}while(0)
 #endif
 
-static bool WriteFully(int fd, const void* data, size_t byte_count) {
+static bool WriteFully(QEMU_PIPE_HANDLE fd, const void* data, size_t byte_count) {
   const uint8_t* p = (const uint8_t*)(data);
   size_t remaining = byte_count;
   while (remaining > 0) {
@@ -64,12 +86,11 @@
  * 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__ int
-qemu_pipe_open(const char*  pipeName)
-{
+static __inline__ QEMU_PIPE_HANDLE
+qemu_pipe_open(const char* pipeName) {
     char  buff[256];
     int   buffLen;
-    int   fd;
+    QEMU_PIPE_HANDLE   fd;
 
     if (pipeName == NULL || pipeName[0] == '\0') {
         errno = EINVAL;
@@ -97,4 +118,36 @@
     return fd;
 }
 
+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;
+}
+
+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
+
 #endif /* ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H */
diff --git a/system/OpenglSystemCommon/qemu_pipe_host.cpp b/system/OpenglSystemCommon/qemu_pipe_host.cpp
new file mode 100644
index 0000000..b4dc2af
--- /dev/null
+++ b/system/OpenglSystemCommon/qemu_pipe_host.cpp
@@ -0,0 +1,50 @@
+// 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.h"
+
+#include "android/emulation/hostpipe/HostGoldfishPipe.h"
+
+#include <cutils/log.h>
+
+using android::HostGoldfishPipeDevice;
+
+QEMU_PIPE_HANDLE qemu_pipe_open(const char* pipeName) {
+    return HostGoldfishPipeDevice::get()->connect(pipeName);
+}
+
+void qemu_pipe_close(QEMU_PIPE_HANDLE pipe) {
+    HostGoldfishPipeDevice::get()->close(pipe);
+}
+
+ssize_t qemu_pipe_read(QEMU_PIPE_HANDLE pipe, void* buffer, size_t len) {
+    return HostGoldfishPipeDevice::get()->read(pipe, buffer, len);
+}
+
+ssize_t qemu_pipe_write(QEMU_PIPE_HANDLE pipe, const void* buffer, size_t 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;
+}
+
+void qemu_pipe_print_error(QEMU_PIPE_HANDLE pipe) {
+    int err = HostGoldfishPipeDevice::get()->getErrno();
+    ALOGE("pipe error: pipe %p err %d", pipe, err);
+}