android: goldfish_pipe: Remove dependency on AndroidEmu.

This patch refactors the virtual device used to implement the
Android pipe channels in the following ways:

- Rename the source files from "android_pipe.c" to
  "goldfish_pipe.c". It is consistent with the naming of
  other Android-specific devices, and makes it more
  explicit that this is a virtual device, not a service
  implementation (e.g. like android_adb.c in the same
  directory that was used in the past).

- Remove any includes to AndroidEmu from the virtual device
  (e.g. "android/emulation/android_pipe_device.h"). Instead
  provide a callback-based interface to be implemented by
  the host service (GoldfishPipeServiceOps), and injected
  into the device through goldfish_pipe_set_service_ops().

  This makes the virtual device much easier to rebase in
  the future, as well as makes it upstreamable.

- Provide a new header "include/hw/misc/goldfish_pipe.h"
  that contains the declaration for the new interface.
  Note that this also defines types with the GoldfishPipe
  prefix. This increases type-safety and better documents
  usage, compared to the liberal use of void* for what
  is now GoldfishHwPipe and GoldfishHostPipe.

- Provide glue code (android_pipe_device.cpp) that connects
  the implementation of the generic AndroidEmu pipe service
  and the QEMU2-specific virtual device, through the new
  qemu_android_pipe_init() function.

- Ensure that qemu_android_pipe_init() is properly called
  at emulation setup time.

+ Fixed a minor mis-type (uint32 --> uint32_t) to avoid
  future compiler warnings (after the 2.7 rebase).

+ Rename pipe_free() to hwpipe_free() for consistency.

NOTE: This should not change the virtual device's
      implementation in any way: no bug fix, no new features.

Change-Id: I1caae14330e036b4076abd3883891885e49e1fe6
diff --git a/android-qemu2-glue/build/Makefile.qemu2-glue.mk b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
index e692c27..330fb92 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-glue.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
@@ -30,6 +30,7 @@
     utils/stream.cpp \
     base/async/Looper.cpp \
     base/files/QemuFileStream.cpp \
+    emulation/android_pipe_device.cpp \
     emulation/charpipe.c \
     emulation/CharSerialLine.cpp \
     emulation/goldfish_sync.cpp \
diff --git a/android-qemu2-glue/build/Makefile.qemu2-target.mk b/android-qemu2-glue/build/Makefile.qemu2-target.mk
index 26e76d0..621c87c 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-target.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-target.mk
@@ -70,7 +70,7 @@
     hw/display/goldfish_fb.c \
     hw/input/goldfish_events.c \
     hw/intc/goldfish_pic.c \
-    hw/misc/android_pipe.c \
+    hw/misc/goldfish_pipe.c \
     hw/misc/goldfish_battery.c \
     hw/misc/goldfish_sync.c \
     hw/timer/goldfish_timer.c \
diff --git a/android-qemu2-glue/emulation/android_pipe_device.cpp b/android-qemu2-glue/emulation/android_pipe_device.cpp
new file mode 100644
index 0000000..744501c
--- /dev/null
+++ b/android-qemu2-glue/emulation/android_pipe_device.cpp
@@ -0,0 +1,174 @@
+/* Copyright 2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#include "android-qemu2-glue/emulation/android_pipe_device.h"
+
+#include "android/base/Compiler.h"
+#include "android/base/Log.h"
+#include "android/emulation/AndroidPipe.h"
+#include "android/emulation/android_pipe_common.h"
+#include "android/emulation/android_pipe_device.h"
+#include "android/emulation/VmLock.h"
+#include "android/utils/stream.h"
+#include "android-qemu2-glue/utils/stream.h"
+
+#include <assert.h>
+#include <memory>
+
+extern "C" {
+#include "hw/misc/goldfish_pipe.h"
+}  // extern "C"
+
+// Technical note: This file contains the glue code used between the
+// generic AndroidPipe service implementation, and the QEMU2-specific
+// goldfish_pipe virtual device. More specifically:
+//
+// The host service pipe expects a device implementation that will
+// implement the callbacks in AndroidHwPipeFuncs. These are injected
+// into the service by calling android_pipe_set_hw_funcs().
+//
+// The virtual device expects a service implementation that will
+// implement the callbacks in GoldfishPIpeServiceOps. These are injected
+// into the device through goldfish_pipe_set_service_ops().
+//
+// qemu_android_pipe_init() is used to inject all callbacks at setup time
+// and initialize the threading mode of AndroidPipe (see below).
+//
+namespace {
+
+// Convenience class used to wrap a QEMUFile inside a ::Stream instance
+// which will be usable by the generic AndroidPipe service.
+class ScopedStream {
+public:
+    explicit ScopedStream(QEMUFile* file)
+        : mStream(stream_from_qemufile(file)) {}
+
+    ~ScopedStream() { close(); }
+
+    void close() {
+        if (mStream) {
+            stream_free(mStream);
+            mStream = nullptr;
+        }
+    }
+
+    ::Stream* get() const { return mStream; }
+
+    DISALLOW_COPY_ASSIGN_AND_MOVE(ScopedStream);
+
+private:
+    ::Stream* mStream;
+};
+
+}  // namespace
+
+// These callbacks are called from the virtual device into the pipe service.
+static const GoldfishPipeServiceOps goldfish_pipe_service_ops = {
+        // guest_open()
+        [](GoldfishHwPipe* hwPipe) -> GoldfishHostPipe* {
+            return static_cast<GoldfishHostPipe*>(
+                    android_pipe_guest_open(hwPipe));
+        },
+        // guest_load()
+        [](QEMUFile* file,
+           GoldfishHwPipe* hwPipe,
+           char* force_close) -> GoldfishHostPipe* {
+            ScopedStream stream(file);
+            return static_cast<GoldfishHostPipe*>(
+                    android_pipe_guest_load(stream.get(), hwPipe, force_close));
+
+        },
+        // guest_close()
+        [](GoldfishHostPipe* hostPipe) { android_pipe_guest_close(hostPipe); },
+        // guest_save()
+        [](GoldfishHostPipe* hostPipe, QEMUFile* file) {
+            ScopedStream stream(file);
+            android_pipe_guest_save(hostPipe, stream.get());
+        },
+        // guest_poll()
+        [](GoldfishHostPipe* hostPipe) {
+            static_assert((int)GOLDFISH_PIPE_POLL_IN == (int)PIPE_POLL_IN,
+                          "invalid POLL_IN values");
+            static_assert((int)GOLDFISH_PIPE_POLL_OUT == (int)PIPE_POLL_OUT,
+                          "invalid POLL_OUT values");
+            static_assert((int)GOLDFISH_PIPE_POLL_HUP == (int)PIPE_POLL_HUP,
+                          "invalid POLL_HUP values");
+
+            return static_cast<GoldfishPipePollFlags>(
+                    android_pipe_guest_poll(hostPipe));
+        },
+        // guest_recv()
+        [](GoldfishHostPipe* hostPipe,
+           GoldfishPipeBuffer* buffers,
+           int numBuffers) -> int {
+            // NOTE: Assumes that AndroidPipeBuffer and GoldfishPipeBuffer
+            //       have exactly the same layout.
+            static_assert(
+                    sizeof(AndroidPipeBuffer) == sizeof(GoldfishPipeBuffer),
+                    "Invalid PipeBuffer sizes");
+            static_assert(offsetof(AndroidPipeBuffer, data) ==
+                                  offsetof(GoldfishPipeBuffer, data),
+                          "Invalid PipeBuffer::data offsets");
+            static_assert(offsetof(AndroidPipeBuffer, size) ==
+                                  offsetof(GoldfishPipeBuffer, size),
+                          "Invalid PipeBuffer::size offsets");
+            return android_pipe_guest_recv(
+                    hostPipe, reinterpret_cast<AndroidPipeBuffer*>(buffers),
+                    numBuffers);
+        },
+        // guest_send()
+        [](GoldfishHostPipe* hostPipe,
+           const GoldfishPipeBuffer* buffers,
+           int numBuffers) -> int {
+            return android_pipe_guest_send(
+                    hostPipe,
+                    reinterpret_cast<const AndroidPipeBuffer*>(buffers),
+                    numBuffers);
+        },
+        // guest_wake_on()
+        [](GoldfishHostPipe* hostPipe, GoldfishPipeWakeFlags wakeFlags) {
+            android_pipe_guest_wake_on(hostPipe, static_cast<int>(wakeFlags));
+        },
+};
+
+// These callbacks are called from the pipe service into the virtual device.
+static const AndroidPipeHwFuncs android_pipe_hw_funcs = {
+        // resetPipe()
+        [](void* hwPipe, void* hostPipe) {
+            goldfish_pipe_reset(static_cast<GoldfishHwPipe*>(hwPipe),
+                                static_cast<GoldfishHostPipe*>(hostPipe));
+        },
+        // closeFromHost()
+        [](void* hwPipe) {
+            goldfish_pipe_close_from_host(static_cast<GoldfishHwPipe*>(hwPipe));
+        },
+        // signalWake()
+        [](void* hwPipe, unsigned flags) {
+            static_assert(
+                    (int)GOLDFISH_PIPE_WAKE_CLOSED == (int)PIPE_WAKE_CLOSED,
+                    "Invalid PIPE_WAKE_CLOSED values");
+            static_assert((int)GOLDFISH_PIPE_WAKE_READ == (int)PIPE_WAKE_READ,
+                          "Invalid PIPE_WAKE_READ values");
+            static_assert((int)GOLDFISH_PIPE_WAKE_WRITE == (int)PIPE_WAKE_WRITE,
+                          "Invalid PIPE_WAKE_WRITE values");
+
+            goldfish_pipe_signal_wake(
+                    static_cast<GoldfishHwPipe*>(hwPipe),
+                    static_cast<GoldfishPipeWakeFlags>(flags));
+        },
+};
+
+bool qemu_android_pipe_init(android::VmLock* vmLock) {
+    goldfish_pipe_set_service_ops(&goldfish_pipe_service_ops);
+    android_pipe_set_hw_funcs(&android_pipe_hw_funcs);
+    android::AndroidPipe::initThreading(vmLock);
+    return true;
+}
diff --git a/android-qemu2-glue/emulation/android_pipe_device.h b/android-qemu2-glue/emulation/android_pipe_device.h
new file mode 100644
index 0000000..efe0266
--- /dev/null
+++ b/android-qemu2-glue/emulation/android_pipe_device.h
@@ -0,0 +1,18 @@
+/* Copyright 2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#pragma once
+
+#include "android/emulation/VmLock.h"
+
+/* Initialize Android pipe device support. Return true on success, false
+ * otherwise. */
+bool qemu_android_pipe_init(android::VmLock* vmLock);
diff --git a/android-qemu2-glue/qemu-setup.cpp b/android-qemu2-glue/qemu-setup.cpp
index 1130592..0bbdb77 100644
--- a/android-qemu2-glue/qemu-setup.cpp
+++ b/android-qemu2-glue/qemu-setup.cpp
@@ -17,10 +17,10 @@
 #include "android/android.h"
 #include "android/base/Log.h"
 #include "android/console.h"
-#include "android/emulation/AndroidPipe.h"
+#include "android-qemu2-glue/emulation/android_pipe_device.h"
+#include "android-qemu2-glue/emulation/VmLock.h"
 #include "android-qemu2-glue/qemu-control-impl.h"
 #include "android-qemu2-glue/emulation/goldfish_sync.h"
-#include "android-qemu2-glue/emulation/VmLock.h"
 
 extern "C" {
 #include "qemu/main-loop.h"
@@ -43,7 +43,10 @@
     VmLock* prevVmLock = VmLock::set(vmLock);
     CHECK(prevVmLock == nullptr) << "Another VmLock was already installed!";
 
-    android::AndroidPipe::initThreading(vmLock);
+    // Initialize host pipe service.
+    if (!qemu_android_pipe_init(vmLock)) {
+        return false;
+    }
 
     if (!qemu_android_sync_init(vmLock)) {
         return false;
diff --git a/hw/misc/android_pipe.c b/hw/misc/goldfish_pipe.c
similarity index 77%
rename from hw/misc/android_pipe.c
rename to hw/misc/goldfish_pipe.c
index 6be9b73..a1d1bd8 100755
--- a/hw/misc/android_pipe.c
+++ b/hw/misc/goldfish_pipe.c
@@ -19,7 +19,7 @@
 ** for various purposes including the adb debug bridge and
 ** (eventually) the opengles pass-through. This file contains only the
 ** basic pipe infrastructure and a couple of test pipes. Additional
-** pipes are registered with the android_pipe_add_type() call.
+** pipes are registered with the goldfish_pipe_add_type() call.
 **
 ** Open Questions
 **
@@ -28,8 +28,9 @@
 ** should give some thought to if this needs re-writing to take
 ** advantage of that infrastructure to create the pipes.
 */
+#include "hw/misc/goldfish_pipe.h"
+
 #include "android-qemu2-glue/utils/stream.h"
-#include "android/emulation/android_pipe_device.h"
 #include "hw/hw.h"
 #include "hw/sysbus.h"
 #include "qemu/error-report.h"
@@ -138,18 +139,55 @@
     PIPE_DRIVER_VERSION_v1 = 0,  // used to not report its version at all
 };
 
+/* These default callbacks are provided to detect when emulation setup
+ * didn't register a pipe service implementation correctly! There is no
+ * need to provide other GoldfishPipeServiceOps callbacks, since they
+ * cannot be called if one could not open or create a host pipe.
+ *
+ * NOTE: Returning NULL will force-close the pipe as soon as it is
+ *       opened by the guest. */
+static GoldfishHostPipe *null_guest_open(GoldfishHwPipe *hw_pipe)
+{
+    E("Android guest tried to open a pipe before service registration!\n"
+      "Please call goldfish_pipe_set_service_ops() at setup time!");
+    (void)hw_pipe;
+    return NULL;
+}
+
+static GoldfishHostPipe *null_guest_load(QEMUFile *file,
+                                         GoldfishHwPipe *hw_pipe,
+                                         char *force_close)
+{
+    E("Trying to load a pipe before service registration!\n"
+      "Please call goldfish_pipe_set_service_ops() at setup time!");
+    (void)file;
+    (void)hw_pipe;
+    (void)force_close;
+    return NULL;
+}
+
+static const GoldfishPipeServiceOps  s_null_service_ops = {
+    .guest_open = null_guest_open,
+    .guest_load = null_guest_load,
+};
+
+static const GoldfishPipeServiceOps* service_ops = &s_null_service_ops;
+
+void goldfish_pipe_set_service_ops(const GoldfishPipeServiceOps* ops) {
+    service_ops = ops;
+}
+
 /* from AOSP version include/hw/android/goldfish/device.h
  * FIXME?: needs to use proper qemu abstractions
  */
-static inline void uint64_set_low(uint64_t* addr, uint32 value) {
+static inline void uint64_set_low(uint64_t* addr, uint32_t value) {
     *addr = (*addr & ~(0xFFFFFFFFULL)) | value;
 }
 
-static inline void uint64_set_high(uint64_t* addr, uint32 value) {
+static inline void uint64_set_high(uint64_t* addr, uint32_t value) {
     *addr = (*addr & 0xFFFFFFFFULL) | ((uint64_t)value << 32);
 }
 
-typedef struct HwPipe HwPipe;
 typedef struct PipeDevice PipeDevice;
 
 struct access_params_32 {
@@ -179,9 +217,9 @@
 
 /* A set of version-specific pipe operations */
 typedef struct {
-    void (*wanted_list_add)(PipeDevice* dev, HwPipe* pipe);
+    void (*wanted_list_add)(PipeDevice* dev, GoldfishHwPipe* pipe);
     void (*close_all)(PipeDevice* dev);
-    void (*save)(Stream* stream, PipeDevice* dev);
+    void (*save)(QEMUFile* file, PipeDevice* dev);
 
     void (*dev_write)(PipeDevice* dev, hwaddr offset, uint64_t value);
     uint64_t (*dev_read)(PipeDevice* dev, hwaddr offset);
@@ -214,21 +252,24 @@
     };
 } PipeCommand;
 
-typedef struct HwPipe {
-    struct HwPipe* wanted_next;
-    struct HwPipe* wanted_prev;
+struct GoldfishHwPipe {
+    struct GoldfishHwPipe *wanted_next;
+    struct GoldfishHwPipe *wanted_prev;
     PipeDevice* dev;
     uint32_t id;  // pipe ID is its index into the PipeDevice::pipes array
     unsigned char wanted;
     char closed;
-    void* pipe_impl_by_user;
+    GoldfishHostPipe *host_pipe;
     uint64_t command_buffer_addr;
     PipeCommand* command_buffer;
 
     // v1-specific fields
-    struct HwPipe* next;
+    struct GoldfishHwPipe* next;
     uint64_t channel; /* opaque kernel handle */
-} HwPipe;
+};
+
+typedef GoldfishHwPipe HwPipe;
+typedef GoldfishHostPipe HostPipe;
 
 typedef struct GuestSignalledPipe {
     uint32_t id;
@@ -336,33 +377,35 @@
 }
 #endif
 
-static unsigned char get_and_clear_pipe_wanted(HwPipe* pipe) {
+static unsigned char hwpipe_get_and_clear_wanted(HwPipe* pipe) {
     unsigned char val = pipe->wanted;
     pipe->wanted = 0;
     return val;
 }
 
-static void set_pipe_wanted_bits(HwPipe* pipe, unsigned char val) {
+static void hwpipe_set_wanted(HwPipe* pipe, unsigned char val) {
     pipe->wanted |= val;
 }
 
-static HwPipe* pipe_new0(PipeDevice* dev) {
+static HwPipe* hwpipe_new0(PipeDevice* dev) {
     HwPipe* pipe;
     pipe = g_malloc0(sizeof(HwPipe));
     pipe->dev = dev;
     return pipe;
 }
 
-static HwPipe* pipe_new(uint32_t id, uint64_t channel, PipeDevice* dev) {
-    HwPipe* pipe = pipe_new0(dev);
+static HwPipe* hwpipe_new(uint32_t id, uint64_t channel, PipeDevice* dev) {
+    HwPipe* pipe = hwpipe_new0(dev);
     pipe->id = id;
     pipe->channel = channel;
-    pipe->pipe_impl_by_user = android_pipe_guest_open(pipe);
+    pipe->host_pipe = service_ops->guest_open(pipe);
     return pipe;
 }
 
-static void pipe_free(HwPipe* pipe) {
-    android_pipe_guest_close(pipe->pipe_impl_by_user);
+static void hwpipe_free(HwPipe* pipe) {
+    if (pipe->host_pipe)
+        service_ops->guest_close(pipe->host_pipe);
+
     g_free(pipe);
 }
 
@@ -489,7 +532,7 @@
     HwPipe* pipe = dev->pipes_list;
     while (pipe) {
         HwPipe* next = pipe->next;
-        pipe_free(pipe);
+        hwpipe_free(pipe);
         pipe = next;
     }
     dev->pipes_list = NULL;
@@ -501,7 +544,7 @@
         HwPipe* pipe = dev->pipes[i];
         if (pipe) {
             unmap_command_buffer(pipe->command_buffer);
-            pipe_free(pipe);
+            hwpipe_free(pipe);
             dev->pipes[i] = NULL;
         }
     }
@@ -520,24 +563,30 @@
 
     /* Check that we're referring a known pipe channel */
     if (command != PIPE_CMD_OPEN && pipe == NULL) {
-        dev->status = PIPE_ERROR_INVAL;
+        dev->status = GOLDFISH_PIPE_ERROR_INVAL;
         return;
     }
 
     /* If the pipe is closed by the host, return an error */
     if (pipe != NULL && pipe->closed && command != PIPE_CMD_CLOSE) {
-        dev->status = PIPE_ERROR_IO;
+        dev->status = GOLDFISH_PIPE_ERROR_IO;
         return;
     }
 
     switch (command) {
     case PIPE_CMD_OPEN:
-        DD("%s: CMD_OPEN channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
+        DD("%s: CMD_OPEN channel=0x%llx", __func__,
+           (unsigned long long)dev->channel);
         if (pipe != NULL) {
-            dev->status = PIPE_ERROR_INVAL;
+            dev->status = GOLDFISH_PIPE_ERROR_INVAL;
             break;
         }
-        pipe = pipe_new(0, dev->channel, dev);
+        pipe = hwpipe_new(0, dev->channel, dev);
+        if (!pipe->host_pipe) {
+            hwpipe_free(pipe);
+            dev->status = GOLDFISH_PIPE_ERROR_INVAL;
+            break;
+        }
         pipe->next = dev->pipes_list;
         dev->pipes_list = pipe;
         dev->status = 0;
@@ -546,7 +595,8 @@
         break;
 
     case PIPE_CMD_CLOSE: {
-        DD("%s: CMD_CLOSE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
+        DD("%s: CMD_CLOSE channel=0x%llx", __func__,
+           (unsigned long long)dev->channel);
         // Remove from device's lists.
         // This linear lookup is potentially slow, but we don't delete pipes
         // often enough for it to become noticable.
@@ -555,7 +605,7 @@
             pnode = &(*pnode)->next;
         }
         if (!*pnode) {
-            dev->status = PIPE_ERROR_INVAL;
+            dev->status = GOLDFISH_PIPE_ERROR_INVAL;
             break;
         }
         *pnode = pipe->next;
@@ -564,27 +614,28 @@
                             hash_cast_key_from_channel(&pipe->channel));
         wanted_pipes_remove_v1(dev, pipe);
 
-        pipe_free(pipe);
+        hwpipe_free(pipe);
         break;
     }
 
     case PIPE_CMD_POLL:
-        dev->status = android_pipe_guest_poll(pipe->pipe_impl_by_user);
-        DD("%s: CMD_POLL > status=%d", __FUNCTION__, dev->status);
+        dev->status = service_ops->guest_poll(pipe->host_pipe);
+        DD("%s: CMD_POLL > status=%d", __func__, dev->status);
         break;
 
     case PIPE_CMD_READ: {
         /* Translate guest physical address into emulator memory. */
-        AndroidPipeBuffer  buffer;
+        GoldfishPipeBuffer buffer;
         buffer.data = map_guest_buffer(dev->address, dev->size, /*is_write*/1);
         if (!buffer.data) {
-            dev->status = PIPE_ERROR_INVAL;
+            dev->status = GOLDFISH_PIPE_ERROR_INVAL;
             break;
         }
         buffer.size = dev->size;
-        dev->status = android_pipe_guest_recv(pipe->pipe_impl_by_user, &buffer, 1);
+        dev->status = service_ops->guest_recv(pipe->host_pipe, &buffer, 1);
         DD("%s: CMD_READ channel=0x%llx address=0x%16llx size=%d > status=%d",
-           __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address,
+           __func__, (unsigned long long)dev->channel,
+           (unsigned long long)dev->address,
            dev->size, dev->status);
         cpu_physical_memory_unmap(buffer.data, dev->size,
                                   /*is_write*/1, dev->size);
@@ -593,42 +644,44 @@
 
     case PIPE_CMD_WRITE: {
         /* Translate guest physical address into emulator memory. */
-        AndroidPipeBuffer  buffer;
+        GoldfishPipeBuffer  buffer;
         buffer.data = map_guest_buffer(dev->address, dev->size, /*is_write*/0);
         if (!buffer.data) {
-            dev->status = PIPE_ERROR_INVAL;
+            dev->status = GOLDFISH_PIPE_ERROR_INVAL;
             break;
         }
         buffer.size = dev->size;
-        dev->status = android_pipe_guest_send(pipe->pipe_impl_by_user, &buffer, 1);
-        DD("%s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d",
-           __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address,
-           dev->size, dev->status);
+        dev->status = service_ops->guest_send(pipe->host_pipe, &buffer, 1);
+        DD("%s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > "
+           "status=%d", __func__, (unsigned long long)dev->channel,
+           (unsigned long long)dev->address, dev->size, dev->status);
         cpu_physical_memory_unmap(buffer.data, dev->size,
                                   /*is_write*/0, dev->size);
         break;
     }
 
     case PIPE_CMD_WAKE_ON_READ:
-        DD("%s: CMD_WAKE_ON_READ channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
-        if ((pipe->wanted & PIPE_WAKE_READ) == 0) {
-            pipe->wanted |= PIPE_WAKE_READ;
-            android_pipe_guest_wake_on(pipe->pipe_impl_by_user, pipe->wanted);
+        DD("%s: CMD_WAKE_ON_READ channel=0x%llx", __func__,
+           (unsigned long long)dev->channel);
+        if ((pipe->wanted & GOLDFISH_PIPE_WAKE_READ) == 0) {
+            pipe->wanted |= GOLDFISH_PIPE_WAKE_READ;
+            service_ops->guest_wake_on(pipe->host_pipe, pipe->wanted);
         }
         dev->status = 0;
         break;
 
     case PIPE_CMD_WAKE_ON_WRITE:
-        DD("%s: CMD_WAKE_ON_WRITE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
-        if ((pipe->wanted & PIPE_WAKE_WRITE) == 0) {
-            pipe->wanted |= PIPE_WAKE_WRITE;
-            android_pipe_guest_wake_on(pipe->pipe_impl_by_user, pipe->wanted);
+        DD("%s: CMD_WAKE_ON_WRITE channel=0x%llx", __func__,
+           (unsigned long long)dev->channel);
+        if ((pipe->wanted & GOLDFISH_PIPE_WAKE_WRITE) == 0) {
+            pipe->wanted |= GOLDFISH_PIPE_WAKE_WRITE;
+            service_ops->guest_wake_on(pipe->host_pipe, pipe->wanted);
         }
         dev->status = 0;
         break;
 
     default:
-        D("%s: command=%d (0x%x)\n", __FUNCTION__, command, command);
+        D("%s: command=%d (0x%x)\n", __func__, command, command);
     }
 }
 
@@ -641,7 +694,7 @@
         return;
     }
     if (commandBuffer->id != id) {
-        commandBuffer->status = PIPE_ERROR_INVAL;
+        commandBuffer->status = GOLDFISH_PIPE_ERROR_INVAL;
         unmap_command_buffer(commandBuffer);
         return;
     }
@@ -652,7 +705,7 @@
         return;
     }
     if (commandBuffer->cmd != PIPE_CMD_OPEN) {
-        commandBuffer->status = PIPE_ERROR_INVAL;
+        commandBuffer->status = GOLDFISH_PIPE_ERROR_INVAL;
         unmap_command_buffer(commandBuffer);
         return;
     }
@@ -662,7 +715,7 @@
                                   : 2 * dev->pipes_capacity;
         HwPipe** pipes = calloc(newCapacity, sizeof(HwPipe*));
         if (!pipes) {
-            commandBuffer->status = PIPE_ERROR_NOMEM;
+            commandBuffer->status = GOLDFISH_PIPE_ERROR_NOMEM;
             unmap_command_buffer(commandBuffer);
             return;
         }
@@ -671,10 +724,10 @@
         dev->pipes_capacity = newCapacity;
     }
 
-    HwPipe* pipe = pipe_new(id, 0, dev);
-    if (!pipe || !pipe->pipe_impl_by_user) {
-        free(pipe);
-        commandBuffer->status = PIPE_ERROR_NOMEM;
+    HwPipe* pipe = hwpipe_new(id, 0, dev);
+    if (!pipe || !pipe->host_pipe) {
+        hwpipe_free(pipe);
+        commandBuffer->status = GOLDFISH_PIPE_ERROR_NOMEM;
         unmap_command_buffer(commandBuffer);
         return;
     }
@@ -694,7 +747,7 @@
 
     /* If the pipe is closed by the host, return an error */
     if (pipe->closed && command != PIPE_CMD_CLOSE) {
-        pipe->command_buffer->status = PIPE_ERROR_IO;
+        pipe->command_buffer->status = GOLDFISH_PIPE_ERROR_IO;
         return;
     }
 
@@ -706,12 +759,13 @@
             wanted_pipes_remove_v2(dev, pipe);
             pipe->command_buffer->status = 0;
             unmap_command_buffer(pipe->command_buffer);
-            pipe_free(pipe);
+            hwpipe_free(pipe);
             break;
         }
 
         case PIPE_CMD_POLL:
-            pipe->command_buffer->status = android_pipe_guest_poll(pipe->pipe_impl_by_user);
+            pipe->command_buffer->status =
+                    service_ops->guest_poll(pipe->host_pipe);
             DD("%s: CMD_POLL > status=%d", __func__,
                pipe->command_buffer->status);
             break;
@@ -726,7 +780,7 @@
                 buffers_count = MAX_BUFFERS_COUNT;
             }
 
-            AndroidPipeBuffer buffers[MAX_BUFFERS_COUNT];
+            GoldfishPipeBuffer buffers[MAX_BUFFERS_COUNT];
             unsigned i;
             for (i = 0; i < buffers_count; ++i) {
                 buffers[i].size = pipe->command_buffer->rw_params.sizes[i];
@@ -735,17 +789,19 @@
                         pipe->command_buffer->rw_params.sizes[i],
                         willModifyData);
                 if (!buffers[i].data) {
-                    pipe->command_buffer->status = PIPE_ERROR_INVAL;
+                    pipe->command_buffer->status = GOLDFISH_PIPE_ERROR_INVAL;
                     goto done;
                 }
             }
 
             pipe->command_buffer->status =
                     willModifyData
-                            ? android_pipe_guest_recv(pipe->pipe_impl_by_user, buffers,
-                                                      buffers_count)
-                            : android_pipe_guest_send(pipe->pipe_impl_by_user, buffers,
-                                                      buffers_count);
+                            ? service_ops->guest_recv(pipe->host_pipe,
+                                                        buffers,
+                                                        buffers_count)
+                            : service_ops->guest_send(pipe->host_pipe,
+                                                        buffers,
+                                                        buffers_count);
             // TODO(zyy): create an extended version of send()/recv() functions
             // to
             //  return both transferred size and resulting status in single
@@ -772,12 +828,13 @@
         case PIPE_CMD_WAKE_ON_READ:
         case PIPE_CMD_WAKE_ON_WRITE: {
             bool read = (command == PIPE_CMD_WAKE_ON_READ);
+            int wake_flags = read
+                    ? GOLDFISH_PIPE_WAKE_READ : GOLDFISH_PIPE_WAKE_WRITE;
             DD("%s: CMD_WAKE_ON_%s id=%d", __func__, (read ? "READ" : "WRITE"),
                (int)pipe->id);
-            if ((pipe->wanted & (read ? PIPE_WAKE_READ : PIPE_WAKE_WRITE)) ==
-                0) {
-                pipe->wanted |= (read ? PIPE_WAKE_READ : PIPE_WAKE_WRITE);
-                android_pipe_guest_wake_on(pipe->pipe_impl_by_user, pipe->wanted);
+            if ((pipe->wanted & wake_flags) == 0) {
+                pipe->wanted |= wake_flags;
+                service_ops->guest_wake_on(pipe->host_pipe, pipe->wanted);
             }
             pipe->command_buffer->status = 0;
             break;
@@ -974,19 +1031,19 @@
 {
     switch (offset) {
     case PIPE_REG_STATUS:
-        DR("%s: REG_STATUS status=%d (0x%x)", __FUNCTION__, dev->status, dev->status);
+        DR("%s: REG_STATUS status=%d (0x%x)", __func__, dev->status, dev->status);
         return dev->status;
 
     case PIPE_REG_CHANNEL: {
         HwPipe* wanted_pipe = wanted_pipes_pop_first_v1(dev);
         if (wanted_pipe != NULL) {
-            dev->wakes = get_and_clear_pipe_wanted(wanted_pipe);
-            DR("%s: channel=0x%llx wanted=%d", __FUNCTION__,
+            dev->wakes = hwpipe_get_and_clear_wanted(wanted_pipe);
+            DR("%s: channel=0x%llx wanted=%d", __func__,
                (unsigned long long)wanted_pipe->channel, dev->wakes);
             return (uint32_t)(wanted_pipe->channel & 0xFFFFFFFFUL);
         } else {
             qemu_set_irq(dev->ps->irq, 0);
-            DD("%s: no signaled channels, lowering IRQ", __FUNCTION__);
+            DD("%s: no signaled channels, lowering IRQ", __func__);
             return 0;
         }
     }
@@ -1000,7 +1057,7 @@
         HwPipe* wanted_pipe = wanted_pipes_pop_first_v1(dev);
         if (wanted_pipe != NULL) {
             dev->wanted_pipe_after_channel_high = wanted_pipe;
-            DR("%s: channel_high=0x%llx wanted=%d", __FUNCTION__,
+            DR("%s: channel_high=0x%llx wanted=%d", __func__,
                (unsigned long long)wanted_pipe->channel, wanted_pipe->wanted);
             assert((uint32_t)(wanted_pipe->channel >> 32) != 0);
             return (uint32_t)(wanted_pipe->channel >> 32);
@@ -1012,7 +1069,7 @@
     }
 
     case PIPE_REG_WAKES:
-        DR("%s: wakes %d", __FUNCTION__, dev->wakes);
+        DR("%s: wakes %d", __func__, dev->wakes);
         return dev->wakes;
 
     case PIPE_REG_PARAMS_ADDR_HIGH:
@@ -1023,7 +1080,7 @@
 
     default:
         qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown register %" HWADDR_PRId
-                      " (0x%" HWADDR_PRIx ")\n", __FUNCTION__, offset, offset);
+                      " (0x%" HWADDR_PRIx ")\n", __func__, offset, offset);
     }
     return 0;
 }
@@ -1037,7 +1094,7 @@
                    (pipe = wanted_pipes_pop_first_v2(dev)) != NULL) {
                 dev->signalled_pipe_buffer[count].id = pipe->id;
                 dev->signalled_pipe_buffer[count].flags =
-                        get_and_clear_pipe_wanted(pipe);
+                        hwpipe_get_and_clear_wanted(pipe);
                 ++count;
             }
             if (!dev->wanted_pipes_first) {
@@ -1053,48 +1110,36 @@
     return 0;
 }
 
-static const MemoryRegionOps android_pipe_iomem_ops = {
+static const MemoryRegionOps goldfish_pipe_iomem_ops = {
         .read = pipe_dev_read,
         .write = pipe_dev_write,
         .endianness = DEVICE_NATIVE_ENDIAN
 };
 
-static void qemu2_android_pipe_reset(void* hwpipe, void* internal_pipe);
-static void qemu2_android_pipe_host_signal_wake(void* hwpipe, unsigned flags);
-static void qemu2_android_pipe_host_close(void* hwpipe);
-
-static const AndroidPipeHwFuncs qemu2_android_pipe_hw_funcs = {
-        .resetPipe = qemu2_android_pipe_reset,
-        .closeFromHost = qemu2_android_pipe_host_close,
-        .signalWake = qemu2_android_pipe_host_signal_wake,
-};
-
 // Don't change this version unless you want to break forward compatibility.
 // Instead, use the different device version as a first saved field.
 enum {
-    ANDROID_PIPE_SAVE_VERSION = 1,
+    GOLDFISH_PIPE_SAVE_VERSION = 1,
 };
 
-static void android_pipe_save(QEMUFile* f, void* opaque) {
+static void goldfish_pipe_save(QEMUFile* f, void* opaque) {
     AndroidPipeState* s = opaque;
     PipeDevice* dev = s->dev;
-    Stream* stream = stream_from_qemufile(f);
-    dev->ops->save(stream, dev);
-    stream_free(stream);
+    dev->ops->save(f, dev);
 }
 
-static void android_pipe_save_v1(Stream* stream, PipeDevice* dev) {
+static void goldfish_pipe_save_v1(QEMUFile* file, PipeDevice* dev) {
     assert(dev->device_version == PIPE_DEVICE_VERSION_v1);
-    stream_put_be32(stream, dev->device_version);
+    qemu_put_be32(file, dev->device_version);
 
     /* Save the device version */
     /* Save i/o registers. */
-    stream_put_be64(stream, dev->address);
-    stream_put_be32(stream, dev->size);
-    stream_put_be32(stream, dev->status);
-    stream_put_be64(stream, dev->channel);
-    stream_put_be32(stream, dev->wakes);
-    stream_put_be64(stream, dev->params_addr);
+    qemu_put_be64(file, dev->address);
+    qemu_put_be32(file, dev->size);
+    qemu_put_be32(file, dev->status);
+    qemu_put_be64(file, dev->channel);
+    qemu_put_be32(file, dev->wakes);
+    qemu_put_be64(file, dev->params_addr);
 
     /* Save the pipe count and state of the pipes. */
     int pipe_count = 0;
@@ -1102,12 +1147,12 @@
     for (pipe = dev->pipes_list; pipe; pipe = pipe->next) {
         ++pipe_count;
     }
-    stream_put_be32(stream, pipe_count);
+    qemu_put_be32(file, pipe_count);
     for (pipe = dev->pipes_list; pipe; pipe = pipe->next) {
-        stream_put_be64(stream, pipe->channel);
-        stream_put_byte(stream, pipe->closed);
-        stream_put_byte(stream, pipe->wanted);
-        android_pipe_guest_save(pipe->pipe_impl_by_user, stream);
+        qemu_put_be64(file, pipe->channel);
+        qemu_put_byte(file, pipe->closed);
+        qemu_put_byte(file, pipe->wanted);
+        service_ops->guest_save(pipe->host_pipe, file);
     }
 
     /* Save wanted pipes list. */
@@ -1115,28 +1160,28 @@
     for (pipe = dev->wanted_pipes_first; pipe; pipe = pipe->wanted_next) {
         wanted_pipes_count++;
     }
-    stream_put_be32(stream, wanted_pipes_count);
+    qemu_put_be32(file, wanted_pipes_count);
     for (pipe = dev->wanted_pipes_first; pipe; pipe = pipe->wanted_next) {
-        stream_put_be64(stream, pipe->channel);
+        qemu_put_be64(file, pipe->channel);
     }
     if (dev->wanted_pipe_after_channel_high) {
-        stream_put_byte(stream, 1);
-        stream_put_be64(stream, dev->wanted_pipe_after_channel_high->channel);
+        qemu_put_byte(file, 1);
+        qemu_put_be64(file, dev->wanted_pipe_after_channel_high->channel);
     } else {
-        stream_put_byte(stream, 0);
+        qemu_put_byte(file, 0);
     }
 }
 
-static void android_pipe_save_v2(Stream* stream, PipeDevice* dev) {
+static void goldfish_pipe_save_v2(QEMUFile* file, PipeDevice* dev) {
     assert(dev->device_version == PIPE_DEVICE_VERSION);
-    stream_put_be32(stream, dev->device_version);
+    qemu_put_be32(file, dev->device_version);
 
     /* Save the device data. */
-    stream_put_be32(stream, dev->driver_version);
-    stream_put_be32(stream, dev->signalled_pipe_buffer_size);
-    stream_put_be64(stream, dev->signalled_pipe_buffer_addr);
-    stream_put_be64(stream, dev->open_command_addr);
-    stream_put_be32(stream, dev->pipes_capacity);
+    qemu_put_be32(file, dev->driver_version);
+    qemu_put_be32(file, dev->signalled_pipe_buffer_size);
+    qemu_put_be64(file, dev->signalled_pipe_buffer_addr);
+    qemu_put_be64(file, dev->open_command_addr);
+    qemu_put_be32(file, dev->pipes_capacity);
 
     /* Save the pipes. */
     int i;
@@ -1146,18 +1191,18 @@
             ++pipe_count;
         }
     }
-    stream_put_be32(stream, pipe_count);
+    qemu_put_be32(file, pipe_count);
 
     for (i = 0; i < dev->pipes_capacity; ++i) {
         HwPipe* pipe = dev->pipes[i];
         if (!pipe) {
             continue;
         }
-        stream_put_be32(stream, pipe->id);
-        stream_put_be64(stream, pipe->command_buffer_addr);
-        stream_put_byte(stream, pipe->closed);
-        stream_put_byte(stream, pipe->wanted);
-        android_pipe_guest_save(pipe->pipe_impl_by_user, stream);
+        qemu_put_be32(file, pipe->id);
+        qemu_put_be64(file, pipe->command_buffer_addr);
+        qemu_put_byte(file, pipe->closed);
+        qemu_put_byte(file, pipe->wanted);
+        service_ops->guest_save(pipe->host_pipe, file);
     }
 
     /* Save wanted pipes list. */
@@ -1166,55 +1211,55 @@
     for (pipe = dev->wanted_pipes_first; pipe; pipe = pipe->wanted_next) {
         wanted_pipes_count++;
     }
-    stream_put_be32(stream, wanted_pipes_count);
+    qemu_put_be32(file, wanted_pipes_count);
     for (pipe = dev->wanted_pipes_first; pipe; pipe = pipe->wanted_next) {
-        stream_put_be32(stream, pipe->id);
+        qemu_put_be32(file, pipe->id);
     }
 }
 
-static int android_pipe_load_v1(Stream* stream, PipeDevice* dev) {
+static int goldfish_pipe_load_v1(QEMUFile* file, PipeDevice* dev) {
     HwPipe* pipe;
 
     assert(dev->device_version == PIPE_DEVICE_VERSION_v1);
     dev->driver_version = PIPE_DRIVER_VERSION_v1;
 
     /* Load i/o registers. */
-    dev->address = stream_get_be64(stream);
-    dev->size = stream_get_be32(stream);
-    dev->status = stream_get_be32(stream);
-    dev->channel = stream_get_be64(stream);
-    dev->wakes = stream_get_be32(stream);
-    dev->params_addr = stream_get_be64(stream);
+    dev->address = qemu_get_be64(file);
+    dev->size = qemu_get_be32(file);
+    dev->status = qemu_get_be32(file);
+    dev->channel = qemu_get_be64(file);
+    dev->wakes = qemu_get_be32(file);
+    dev->params_addr = qemu_get_be64(file);
 
     /* Clean up old pipe objects. */
     dev->ops->close_all(dev);
     dev->ops = &pipe_ops_v1;
 
     /* Restore pipes. */
-    int pipe_count = stream_get_be32(stream);
+    int pipe_count = qemu_get_be32(file);
     int pipe_n;
     HwPipe** pipe_list_end = &dev->pipes_list;
     *pipe_list_end = NULL;
     uint64_t* force_closed_pipes = malloc(sizeof(uint64_t) * pipe_count);
     int force_closed_pipes_count = 0;
     for (pipe_n = 0; pipe_n < pipe_count; pipe_n++) {
-        HwPipe* pipe = pipe_new0(dev);
+        HwPipe* pipe = hwpipe_new0(dev);
         char force_close = 0;
-        pipe->channel = stream_get_be64(stream);
-        pipe->closed = stream_get_byte(stream);
-        pipe->wanted = stream_get_byte(stream);
-        pipe->pipe_impl_by_user = android_pipe_guest_load(stream, pipe, &force_close);
+        pipe->channel = qemu_get_be64(file);
+        pipe->closed = qemu_get_byte(file);
+        pipe->wanted = qemu_get_byte(file);
+        pipe->host_pipe = service_ops->guest_load(file, pipe, &force_close);
         pipe->wanted_next = pipe->wanted_prev = NULL;
 
         // |pipe| might be NULL in case it couldn't be saved. However,
-        // in that case |force_close| will be set by android_pipe_guest_load,
+        // in that case |force_close| will be set by goldfish_pipe_guest_load,
         // so |force_close| should be checked first so that the function
         // can continue.
         if (force_close) {
             pipe->closed = 1;
             force_closed_pipes[force_closed_pipes_count++] = pipe->channel;
-        } else if (!pipe->pipe_impl_by_user) {
-            pipe_free(pipe);
+        } else if (!pipe->host_pipe) {
+            hwpipe_free(pipe);
             free(force_closed_pipes);
             return -EIO;
         }
@@ -1235,10 +1280,10 @@
     /* Reconstruct wanted pipes list. */
     HwPipe** wanted_pipe_list_end = &dev->wanted_pipes_first;
     *wanted_pipe_list_end = NULL;
-    int wanted_pipes_count = stream_get_be32(stream);
+    int wanted_pipes_count = qemu_get_be32(file);
     uint64_t channel;
     for (pipe_n = 0; pipe_n < wanted_pipes_count; ++pipe_n) {
-        channel = stream_get_be64(stream);
+        channel = qemu_get_be64(file);
         HwPipe* pipe = g_hash_table_lookup(dev->pipes_by_channel,
                                            hash_cast_key_from_channel(&channel));
         if (pipe) {
@@ -1251,8 +1296,8 @@
             return -EIO;
         }
     }
-    if (stream_get_byte(stream)) {
-        channel = stream_get_be64(stream);
+    if (qemu_get_byte(file)) {
+        channel = qemu_get_be64(file);
         dev->wanted_pipe_after_channel_high =
             g_hash_table_lookup(dev->pipes_by_channel,
                                 hash_cast_key_from_channel(&channel));
@@ -1270,7 +1315,7 @@
             g_hash_table_lookup(dev->pipes_by_channel,
                                 hash_cast_key_from_channel(
                                     &force_closed_pipes[pipe_n]));
-        set_pipe_wanted_bits(pipe, PIPE_WAKE_CLOSED);
+        hwpipe_set_wanted(pipe, GOLDFISH_PIPE_WAKE_CLOSED);
         pipe->closed = 1;
         if (!pipe->wanted_next &&
             !pipe->wanted_prev &&
@@ -1285,26 +1330,26 @@
     return 0;
 }
 
-static int android_pipe_load_v2(Stream* stream, PipeDevice* dev) {
+static int goldfish_pipe_load_v2(QEMUFile* file, PipeDevice* dev) {
     int res = -EIO;
     uint32_t* force_closed_pipes = NULL;
 
     /* Load the device. */
-    dev->device_version = stream_get_be32(stream);
+    dev->device_version = qemu_get_be32(file);
     if (dev->device_version > PIPE_DEVICE_VERSION) {
         goto done;
     } else if (dev->device_version == PIPE_DEVICE_VERSION_v1) {
         // redirect to the v1 loader if this is an old pipe.
-        return android_pipe_load_v1(stream, dev);
+        return goldfish_pipe_load_v1(file, dev);
     }
 
-    dev->driver_version = stream_get_be32(stream);
+    dev->driver_version = qemu_get_be32(file);
     if (dev->driver_version > MAX_SUPPORTED_DRIVER_VERSION) {
         goto done;
     }
 
-    dev->signalled_pipe_buffer_size = stream_get_be32(stream);
-    dev->signalled_pipe_buffer_addr = stream_get_be64(stream);
+    dev->signalled_pipe_buffer_size = qemu_get_be32(file);
+    dev->signalled_pipe_buffer_addr = qemu_get_be64(file);
     dev->signalled_pipe_buffer = (GuestSignalledPipe*)map_guest_buffer(
             dev->signalled_pipe_buffer_addr,
             sizeof(*dev->signalled_pipe_buffer) *
@@ -1313,7 +1358,7 @@
     if (!dev->signalled_pipe_buffer) {
         goto done;
     }
-    dev->open_command_addr = stream_get_be64(stream);
+    dev->open_command_addr = qemu_get_be64(file);
     dev->open_command = (OpenCommandParams*)map_guest_buffer(
             dev->open_command_addr, sizeof(*dev->open_command), /*is_write*/0);
     if (!dev->open_command) {
@@ -1325,7 +1370,7 @@
     dev->ops->close_all(dev);
     dev->ops = &pipe_ops_v2;
 
-    int pipes_capacity = stream_get_be32(stream);
+    int pipes_capacity = qemu_get_be32(file);
     if (dev->pipes_capacity < pipes_capacity) {
         void* pipes = calloc(pipes_capacity, sizeof(*dev->pipes));
         if (!pipes) {
@@ -1337,7 +1382,7 @@
     }
     dev->pipes_capacity = pipes_capacity;
 
-    int pipe_count = stream_get_be32(stream);
+    int pipe_count = qemu_get_be32(file);
     force_closed_pipes = malloc(sizeof(*force_closed_pipes) * pipe_count);
     if (!force_closed_pipes) {
         goto done;
@@ -1345,46 +1390,46 @@
     int i;
     int force_closed_pipes_count = 0;
     for (i = 0; i < pipe_count; ++i) {
-        HwPipe* pipe = pipe_new0(dev);
-        pipe->id = stream_get_be32(stream);
-        pipe->command_buffer_addr = stream_get_be64(stream);
+        HwPipe* pipe = hwpipe_new0(dev);
+        pipe->id = qemu_get_be32(file);
+        pipe->command_buffer_addr = qemu_get_be64(file);
         pipe->command_buffer = (PipeCommand*)map_guest_buffer(
                 pipe->command_buffer_addr, COMMAND_BUFFER_SIZE, /*is_write*/1);
         if (!pipe->command_buffer) {
-            pipe_free(pipe);
+            hwpipe_free(pipe);
             goto done;
         }
-        pipe->closed = stream_get_byte(stream);
-        pipe->wanted = stream_get_byte(stream);
+        pipe->closed = qemu_get_byte(file);
+        pipe->wanted = qemu_get_byte(file);
 
         char force_close = 0;
-        pipe->pipe_impl_by_user = android_pipe_guest_load(stream, pipe, &force_close);
+        pipe->host_pipe = service_ops->guest_load(file, pipe, &force_close);
 
         // |pipe| might be NULL in case it couldn't be saved. However,
-        // in that case |force_close| will be set by android_pipe_guest_load,
+        // in that case |force_close| will be set by goldfish_pipe_guest_load,
         // so |force_close| should be checked first so that the function
         // can continue.
         if (force_close) {
             pipe->closed = 1;
             force_closed_pipes[force_closed_pipes_count++] = pipe->id;
-        } else if (!pipe->pipe_impl_by_user) {
+        } else if (!pipe->host_pipe) {
             unmap_command_buffer(pipe->command_buffer);
-            pipe_free(pipe);
+            hwpipe_free(pipe);
             goto done;
         }
 
         if (dev->pipes[pipe->id]) {
             unmap_command_buffer(pipe->command_buffer);
-            pipe_free(pipe);
+            hwpipe_free(pipe);
             goto done;
         }
         dev->pipes[pipe->id] = pipe;
     }
 
     /* Reconstruct wanted pipes list. */
-    int wanted_pipes_count = stream_get_be32(stream);
+    int wanted_pipes_count = qemu_get_be32(file);
     for (i = 0; i < wanted_pipes_count; ++i) {
-        int id = stream_get_be32(stream);
+        int id = qemu_get_be32(file);
         HwPipe* pipe = dev->pipes[id];
         if (!pipe) {
             goto done;
@@ -1395,7 +1440,7 @@
     /* Add forcibly closed pipes to wanted pipes list */
     for (i = 0; i < force_closed_pipes_count; ++i) {
         HwPipe* pipe = dev->pipes[force_closed_pipes[i]];
-        set_pipe_wanted_bits(pipe, PIPE_WAKE_CLOSED);
+        hwpipe_set_wanted(pipe, GOLDFISH_PIPE_WAKE_CLOSED);
         pipe->closed = 1;
         wanted_pipes_add_v2(dev, pipe);
     }
@@ -1407,16 +1452,14 @@
     return res;
 }
 
-static int android_pipe_load(QEMUFile* f, void* opaque, int version_id) {
+static int goldfish_pipe_load(QEMUFile* f, void* opaque, int version_id) {
     AndroidPipeState* s = opaque;
     PipeDevice* dev = s->dev;
-    Stream* stream = stream_from_qemufile(f);
-    int res = android_pipe_load_v2(stream, dev);
-    stream_free(stream);
+    int res = goldfish_pipe_load_v2(f, dev);
     return res;
 }
 
-static void android_pipe_post_load(void* opaque) {
+static void goldfish_pipe_post_load(void* opaque) {
     /* This function gets invoked after all VM state has
      * been loaded. Raising IRQ in the load handler causes
      * problems.
@@ -1429,7 +1472,7 @@
     }
 }
 
-static void android_pipe_realize(DeviceState* dev, Error** errp) {
+static void goldfish_pipe_realize(DeviceState* dev, Error** errp) {
     SysBusDevice* sbdev = SYS_BUS_DEVICE(dev);
     AndroidPipeState* s = ANDROID_PIPE(dev);
 
@@ -1452,31 +1495,29 @@
         APANIC("%s: failed to initialize pipes hash\n", __func__);
     }
 
-    memory_region_init_io(&s->iomem, OBJECT(s), &android_pipe_iomem_ops, s,
-                          "android_pipe", 0x2000 /*TODO: ?how big?*/);
+    memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_pipe_iomem_ops, s,
+                          "goldfish_pipe", 0x2000 /*TODO: ?how big?*/);
     sysbus_init_mmio(sbdev, &s->iomem);
     sysbus_init_irq(sbdev, &s->irq);
 
-    android_pipe_set_hw_funcs(&qemu2_android_pipe_hw_funcs);
-
+    /* NOTE: "android_pipe" is the legacy name used in snapshots. */
     register_savevm_with_post_load(
-            dev, "android_pipe", 0, ANDROID_PIPE_SAVE_VERSION,
-            android_pipe_save, android_pipe_load, android_pipe_post_load, s);
+            dev, "android_pipe", 0, GOLDFISH_PIPE_SAVE_VERSION,
+            goldfish_pipe_save, goldfish_pipe_load, goldfish_pipe_post_load, s);
 }
 
-static void qemu2_android_pipe_reset(void* hwpipe, void* internal_pipe) {
-    HwPipe* pipe = hwpipe;
-    pipe->pipe_impl_by_user = internal_pipe;
+void goldfish_pipe_reset(GoldfishHwPipe *pipe, GoldfishHostPipe *host_pipe) {
+    pipe->host_pipe = host_pipe;
 }
 
-static void qemu2_android_pipe_host_signal_wake(void* hwpipe, unsigned flags) {
-    HwPipe* pipe = hwpipe;
-    PipeDevice* dev = pipe->dev;
+void goldfish_pipe_signal_wake(GoldfishHwPipe *pipe,
+                               GoldfishPipeWakeFlags flags) {
+    PipeDevice *dev = pipe->dev;
 
-    DD("%s: id=%d channel=0x%llx flags=%d", __func__,
-        (int)pipe->id, pipe->channel, flags);
+    DD("%s: id=%d channel=0x%llx flags=%d", __func__, (int)pipe->id,
+       pipe->channel, flags);
 
-    set_pipe_wanted_bits(pipe, (unsigned char)flags);
+    hwpipe_set_wanted(pipe, (unsigned char)flags);
     dev->ops->wanted_list_add(dev, pipe);
 
     /* Raise IRQ to indicate there are items on our list ! */
@@ -1484,40 +1525,39 @@
     DD("%s: raising IRQ", __func__);
 }
 
-static void qemu2_android_pipe_host_close(void* hwpipe) {
-    HwPipe* pipe = hwpipe;
-
+void goldfish_pipe_close_from_host(GoldfishHwPipe *pipe)
+{
     D("%s: id=%d channel=0x%llx (closed=%d)", __func__, (int)pipe->id,
         pipe->channel, pipe->closed);
 
     if (!pipe->closed) {
         pipe->closed = 1;
-        qemu2_android_pipe_host_signal_wake(hwpipe, PIPE_WAKE_CLOSED);
+        goldfish_pipe_signal_wake(pipe, GOLDFISH_PIPE_WAKE_CLOSED);
     }
 }
 
-static void android_pipe_class_init(ObjectClass* klass, void* data) {
+static void goldfish_pipe_class_init(ObjectClass* klass, void* data) {
     DeviceClass* dc = DEVICE_CLASS(klass);
-    dc->realize = android_pipe_realize;
+    dc->realize = goldfish_pipe_realize;
     dc->desc = "android pipe";
 }
 
-static const TypeInfo android_pipe_info = {
+static const TypeInfo goldfish_pipe_info = {
         .name = TYPE_ANDROID_PIPE,
         .parent = TYPE_SYS_BUS_DEVICE,
         .instance_size = sizeof(AndroidPipeState),
-        .class_init = android_pipe_class_init};
+        .class_init = goldfish_pipe_class_init};
 
-static void android_pipe_register(void) {
-    type_register_static(&android_pipe_info);
+static void goldfish_pipe_register(void) {
+    type_register_static(&goldfish_pipe_info);
 }
 
-type_init(android_pipe_register);
+type_init(goldfish_pipe_register);
 
 static const PipeOperations pipe_ops_v2 = {
         .wanted_list_add = &wanted_pipes_add_v2,
         .close_all = &close_all_pipes_v2,
-        .save = &android_pipe_save_v2,
+        .save = &goldfish_pipe_save_v2,
         .dev_read = &pipe_dev_read_v2,
         .dev_write = &pipe_dev_write_v2
 };
@@ -1525,7 +1565,7 @@
 static const PipeOperations pipe_ops_v1 = {
         .wanted_list_add = &wanted_pipes_add_v1,
         .close_all = &close_all_pipes_v1,
-        .save = &android_pipe_save_v1,
+        .save = &goldfish_pipe_save_v1,
         .dev_read = &pipe_dev_read_v1,
         .dev_write = &pipe_dev_write_v1
 };
diff --git a/include/hw/misc/goldfish_pipe.h b/include/hw/misc/goldfish_pipe.h
new file mode 100644
index 0000000..219ddd6
--- /dev/null
+++ b/include/hw/misc/goldfish_pipe.h
@@ -0,0 +1,147 @@
+/* Copyright (C) 2016 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#ifndef _HW_GOLDFISH_PIPE_H
+#define _HW_GOLDFISH_PIPE_H
+
+#include "qemu/typedefs.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* The Android pipe virtual device expects an implementation of
+ * pipe services to be provided according to the following interface
+ */
+typedef struct GoldfishPipeBuffer {
+    void* data;
+    size_t size;
+} GoldfishPipeBuffer;
+
+/* List of bitflags returned by guest_poll() */
+typedef enum {
+    GOLDFISH_PIPE_POLL_IN = (1 << 0),   /* means guest can read */
+    GOLDFISH_PIPE_POLL_OUT = (1 << 1),  /* means guest can write */
+    GOLDFISH_PIPE_POLL_HUP = (1 << 2),  /* means closed by host */
+} GoldfishPipePollFlags;
+
+/* List of bitflags used to call goldfish_pipe_signal_wake() and
+ * guest_wake_on() */
+typedef enum {
+    GOLDFISH_PIPE_WAKE_CLOSED = (1 << 0),  /* emulator closed the pipe */
+    GOLDFISH_PIPE_WAKE_READ = (1 << 1),    /* pipe can now be read from */
+    GOLDFISH_PIPE_WAKE_WRITE = (1 << 2),   /* pipe can now be written to */
+} GoldfishPipeWakeFlags;
+
+/* List of error values possibly returned by guest_recv() and
+ * guest_send(). */
+typedef enum {
+    GOLDFISH_PIPE_ERROR_INVAL = -1,
+    GOLDFISH_PIPE_ERROR_AGAIN = -2,
+    GOLDFISH_PIPE_ERROR_NOMEM = -3,
+    GOLDFISH_PIPE_ERROR_IO = -4,
+} GoldfishPipeError;
+
+/* Opaque type of the hardware-side view of a pipe connection. This structure
+ * is implemented by the virtual device and is hidden from the host service
+ * implementation. */
+typedef struct GoldfishHwPipe GoldfishHwPipe;
+
+/* Opaque type of the host-side view of a pipe connection. This structure is
+ * implemented by the host pipe service implementation, and is hidden from
+ * the virtual device. */
+typedef struct GoldfishHostPipe GoldfishHostPipe;
+
+typedef struct {
+    // Open a new pipe. |hw_pipe| is a unique pointer value identifying the
+    // hardware-side view of the pipe, and will be passed to the
+    // goldfish_pipe_xxx() functions below. This returns a new host-specific
+    // pipe value that is only used by the virtual device to call other
+    // callbacks here. There is a one-to-one association between a |hw_pipe|
+    // and its |host_pipe| value, which can be reset by calling
+    // goldfish_pipe_reset().
+    GoldfishHostPipe* (*guest_open)(GoldfishHwPipe *hw_pipe);
+
+    // Load the state of a  pipe from a stream. |file| is the input stream,
+    // |hw_pipe| is the hardware-side pipe descriptor. On success, return a new
+    // internal pipe instance (similar to one returned by guest_open()), and
+    // sets |*force_close| to 1 to indicate that the pipe must be force-closed
+    // just after its load/creation (only useful for certain services that can't
+    // preserve state into streams). Return NULL on faillure.
+    GoldfishHostPipe* (*guest_load)(QEMUFile *file, GoldfishHwPipe *hw_pipe,
+                                    char *force_close);
+
+    // Close and free a pipe. |host_pipe| must be the result of a previous
+    // guest_open() or guest_load() call, or the second parameter to
+    // goldfish_pipe_reset().
+    void (*guest_close)(GoldfishHostPipe *host_pipe);
+
+    // Save the state of a pipe to a stream. |host_pipe| is the pipe
+    // instance from guest_open() or guest_load(). and |file| is the
+    // output stream.
+    void (*guest_save)(GoldfishHostPipe *host_pipe, QEMUFile *file);
+
+    // Poll the state of the pipe associated with |host_pipe|.
+    // This returns a combination of GoldfishPipePollFlags.
+    GoldfishPipePollFlags (*guest_poll)(GoldfishHostPipe *host_pipe);
+
+    // Called when the guest tries to receive data from the host through
+    // |host_pipe|. This will try to copy data to the memory ranges
+    // decribed by the array |buffers| or |num_buffers| items.
+    // Return number of bytes transferred, or a (negative) GoldfishPipeError
+    // value otherwise.
+    int (*guest_recv)(GoldfishHostPipe *host_pipe,
+                      GoldfishPipeBuffer *buffers,
+                      int num_buffers);
+
+    // Called when the guest tries to send data to the host through
+    // |host_pipe|. This will try to copy data from the memory ranges
+    // decribed by the array |buffers| or |num_buffers| items.
+    // Return number of bytes transferred, or a (negative) GoldfishPipeError
+    // value otherwise.
+    int (*guest_send)(GoldfishHostPipe *host_pipe,
+                      const GoldfishPipeBuffer *buffers,
+                      int num_buffers);
+
+    // Called when the guest wants to be waked on specific events.
+    // identified by the |wake_flags| bitmask. The host should call
+    // goldfish_pipe_signal_wake() with the appropriate bitmask when
+    // any of these events occur.
+    void (*guest_wake_on)(GoldfishHostPipe *host_pipe,
+                          GoldfishPipeWakeFlags wake_flags);
+} GoldfishPipeServiceOps;
+
+/* Called by the service implementation to register its callbacks.
+ * The default implementation doesn't do anything except returning
+ * an error when |guest_open| or |guest_load| are called. */
+extern void goldfish_pipe_set_service_ops(
+        const GoldfishPipeServiceOps* ops);
+
+/* Implemented by the virtual device, always called from the service in
+ * a thread that owns the BQL. */
+
+/* Reset the association of |hw_pipe| with a new |host_pipe|
+ * value. This is called once the guest has written the service name
+ * to the initial pipe connection, and the host decided of the right
+ * implementation for it. */
+extern void goldfish_pipe_reset(GoldfishHwPipe *hw_pipe,
+                                GoldfishHostPipe *host_pipe);
+
+/* Called by the host to notify the virtual device that it has
+ * closed its side of the pipe. */
+extern void goldfish_pipe_close_from_host(GoldfishHwPipe *hw_pipe);
+
+/* Called by the host to notify that one or more conditions identified
+ * by |flags| has been met for a given pipe identified by |hw_pipe|. */
+extern void goldfish_pipe_signal_wake(GoldfishHwPipe *hw_pipe,
+                                      GoldfishPipeWakeFlags flags);
+
+#endif /* _HW_GOLDFISH_PIPE_H */