goldfish_sync: Remove AndroidEmu dependency.

This patch refactors the virtual goldfish_sync device to not
directly depend on AndroidEmu headers and features. This makes
its code easier to rebase, or to upstream.

- Introduce a new header (include/hw/misc/goldfish_sync.h)
  providing a generic interface to be implemented by any
  host-side sync service (GoldfishSyncServiceOps).

- Add glue code (android-qemu2-glue/emulation/goldfish_sync.cpp)
  to link AndroidEmu and the virtual device properly at setup
  time.

- Call the new qemu_android_sync_init() function in
  qemu_android_emulation_setup().

NOTE: This is a pure refactoring patch: it should not provide
      any new features, or fix any bug.

Change-Id: Ib3ef47a8044c1ed1d082961171999e18ceb9219f
diff --git a/android-qemu2-glue/build/Makefile.qemu2-glue.mk b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
index 842325b..e692c27 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-glue.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
@@ -32,6 +32,7 @@
     base/files/QemuFileStream.cpp \
     emulation/charpipe.c \
     emulation/CharSerialLine.cpp \
+    emulation/goldfish_sync.cpp \
     emulation/serial_line.cpp \
     emulation/VmLock.cpp \
     telephony/modem_init.c \
diff --git a/android-qemu2-glue/emulation/goldfish_sync.cpp b/android-qemu2-glue/emulation/goldfish_sync.cpp
new file mode 100644
index 0000000..01cc29f
--- /dev/null
+++ b/android-qemu2-glue/emulation/goldfish_sync.cpp
@@ -0,0 +1,56 @@
+/* Copyright 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.
+*/
+#include "android-qemu2-glue/emulation/goldfish_sync.h"
+
+// Glue code between the virtual goldfish sync device, and the
+// host-side sync service implementation.
+
+#include "android/base/Log.h"
+#include "android/emulation/GoldfishSyncCommandQueue.h"
+#include "android/emulation/goldfish_sync.h"
+
+extern "C" {
+#include "hw/misc/goldfish_sync.h"
+}  // extern "C"
+
+static trigger_wait_fn_t sTriggerWaitFn = nullptr;
+
+// These callbacks are called from the host sync service to operate
+// on the virtual device (.doHostCommand) or register a trigger-waiting
+// callback that will be invoked later from the device
+// (.registerTriggerWait).
+static GoldfishSyncDeviceInterface kSyncDeviceInterface = {
+    .doHostCommand = goldfish_sync_send_command,
+    .registerTriggerWait = [](trigger_wait_fn_t fn) {
+        sTriggerWaitFn = fn;
+    },
+};
+
+// These callbacks are called from the virtual device to send
+// data to the host sync service.
+static const GoldfishSyncServiceOps kSyncServiceOps = {
+    .receive_hostcmd_result = goldfish_sync_receive_hostcmd_result,
+    .trigger_host_wait = [](uint64_t glsync_ptr,
+                            uint64_t thread_ptr,
+                            uint64_t timeline) {
+        if (sTriggerWaitFn) {
+            sTriggerWaitFn(glsync_ptr, thread_ptr, timeline);
+        }
+    }
+};
+
+bool qemu_android_sync_init(android::VmLock* vmLock) {
+    goldfish_sync_set_service_ops(&kSyncServiceOps);
+    goldfish_sync_set_hw_funcs(&kSyncDeviceInterface);
+    android::GoldfishSyncCommandQueue::initThreading(vmLock);
+    return true;
+}
diff --git a/android-qemu2-glue/emulation/goldfish_sync.h b/android-qemu2-glue/emulation/goldfish_sync.h
new file mode 100644
index 0000000..cd20b9d
--- /dev/null
+++ b/android-qemu2-glue/emulation/goldfish_sync.h
@@ -0,0 +1,17 @@
+/* Copyright 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.
+*/
+#pragma once
+
+#include "android/emulation/VmLock.h"
+
+/* Initialize Goldfish Sync device and service. */
+bool qemu_android_sync_init(android::VmLock* vmLock);
diff --git a/android-qemu2-glue/qemu-setup.cpp b/android-qemu2-glue/qemu-setup.cpp
index 6d96824..1130592 100644
--- a/android-qemu2-glue/qemu-setup.cpp
+++ b/android-qemu2-glue/qemu-setup.cpp
@@ -18,8 +18,8 @@
 #include "android/base/Log.h"
 #include "android/console.h"
 #include "android/emulation/AndroidPipe.h"
-#include "android/emulation/GoldfishSyncCommandQueue.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" {
@@ -44,7 +44,10 @@
     CHECK(prevVmLock == nullptr) << "Another VmLock was already installed!";
 
     android::AndroidPipe::initThreading(vmLock);
-    android::GoldfishSyncCommandQueue::initThreading(vmLock);
+
+    if (!qemu_android_sync_init(vmLock)) {
+        return false;
+    }
 
     return android_emulation_setup(&consoleAgents);
 }
diff --git a/hw/misc/goldfish_sync.c b/hw/misc/goldfish_sync.c
index 777e6de..443086b 100644
--- a/hw/misc/goldfish_sync.c
+++ b/hw/misc/goldfish_sync.c
@@ -10,7 +10,7 @@
 ** GNU General Public License for more details.
 */
 
-#include "android/emulation/goldfish_sync.h"
+#include "hw/misc/goldfish_sync.h"
 #include "android/utils/debug.h"
 
 #include "hw/hw.h"
@@ -20,14 +20,6 @@
 #include "qemu/main-loop.h"
 #include "trace.h"
 
-#ifndef max
-#define max(x, y) ((x) < (y) ? y : x)
-#endif
-
-#ifndef min
-#define min(x, y) ((x) > (y) ? y : x)
-#endif
-
 #define DEBUG_LOG_ALL_DEVICE_OPS 0
 
 #if DEBUG_LOG_ALL_DEVICE_OPS
@@ -82,6 +74,20 @@
                          uint64_t timeline);
 };
 
+// Command numbers that can only be sent from the guest to the device.
+#define SYNC_GUEST_CMD_READY 0
+#define SYNC_GUEST_CMD_TRIGGER_HOST_WAIT 5
+
+// The register layout is:
+
+#define SYNC_REG_BATCH_COMMAND                0x00 // host->guest batch commands
+#define SYNC_REG_BATCH_GUESTCOMMAND           0x04 // guest->host batch commands
+#define SYNC_REG_BATCH_COMMAND_ADDR           0x08 // communicate physical address of host->guest batch commands
+#define SYNC_REG_BATCH_COMMAND_ADDR_HIGH      0x0c // 64-bit part
+#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR      0x10 // communicate physical address of guest->host commands
+#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH 0x14 // 64-bit part
+#define SYNC_REG_INIT                         0x18 // to signal that the device has been detected by the kernel
+
 // The goldfish sync device is represented by the goldfish_sync_state struct.
 // Besides the machinery necessary to do I/O with the guest:
 // |pending|: a linked list of |goldfish_sync_pending_cmd|'s
@@ -115,6 +121,12 @@
 
 static struct goldfish_sync_state* s_goldfish_sync_dev;
 
+static const GoldfishSyncServiceOps* service_ops = NULL;
+
+void goldfish_sync_set_service_ops(const GoldfishSyncServiceOps *ops) {
+    service_ops = ops;
+}
+
 // Command list operations======================================================
 
 static struct goldfish_sync_pending_cmd*
@@ -187,15 +199,14 @@
 
 // Callbacks and hw_funcs struct================================================
 
-// goldfish_sync_host_signal does the actual work of setting up
+// goldfish_sync_send_command does the actual work of setting up
 // the sync device registers, causing IRQ blip,
 // and waiting for + reading back results from the guest
 // (if appplicable)
-static void goldfish_sync_host_signal(
-        uint32_t cmd,
-        uint64_t handle,
-        uint32_t time_arg,
-        uint64_t hostcmd_handle) {
+void goldfish_sync_send_command(uint32_t cmd,
+                                uint64_t handle,
+                                uint32_t time_arg,
+                                uint64_t hostcmd_handle) {
 
     struct goldfish_sync_state* s;
     struct goldfish_sync_pending_cmd* to_send;
@@ -221,31 +232,6 @@
     DPRINT("Exit");
 }
 
-// This sets |trigger_fn| as the function to call
-// when guest asks the host to trigger a wait.
-void goldfish_sync_register_trigger_wait_impl(
-        trigger_wait_fn_t trigger_fn) {
-
-    DPRINT("Enter");
-
-    struct goldfish_sync_state* s = s_goldfish_sync_dev;
-
-    if (!s->ops) {
-        s->ops =
-            (struct goldfish_sync_ops*)
-            (malloc(sizeof(struct goldfish_sync_ops)));
-    }
-
-    s->ops->trigger_wait = trigger_fn;
-
-    DPRINT("Exit");
-}
-
-static GoldfishSyncDeviceInterface qemu2_goldfish_sync_hw_funcs = {
-    .doHostCommand = goldfish_sync_host_signal,
-    .registerTriggerWait = goldfish_sync_register_trigger_wait_impl,
-};
-
 #define TYPE_GOLDFISH_SYNC "goldfish_sync"
 #define GOLDFISH_SYNC(obj) \
     OBJECT_CHECK(struct goldfish_sync_state, (obj), TYPE_GOLDFISH_SYNC)
@@ -365,7 +351,7 @@
                incoming.handle,
                incoming.time_arg,
                incoming.hostcmd_handle);
-        goldfish_sync_receive_hostcmd_result(
+        service_ops->receive_hostcmd_result(
                incoming.cmd,
                incoming.handle,
                incoming.time_arg,
@@ -373,7 +359,7 @@
         break;
     // SYNC_REG_BATCH_GUESTCOMMAND write: Used to send
     // guest->host commands. Currently, the only guest->host command
-    // that matters is CMD_TRIGGER_HOST_WAIT, which is used
+    // that matters is SYNC_GUEST_CMD_TRIGGER_HOST_WAIT, which is used
     // to cause a OpenGL client wait on the host GPU/CPU.
     case SYNC_REG_BATCH_GUESTCOMMAND:
         DPRINT("write SYNC_REG_BATCH_GUESTCOMMAND. obtaining batch cmd vals.");
@@ -392,14 +378,14 @@
                 guest_incoming.thread_handle,
                 guest_incoming.guest_timeline_handle);
         switch (guest_incoming.host_command) {
-        case CMD_TRIGGER_HOST_WAIT:
-            DPRINT("exec CMD_TRIGGER_HOST_WAIT");
-            s->ops->trigger_wait(guest_incoming.glsync_handle,
-                                 guest_incoming.thread_handle,
-                                 guest_incoming.guest_timeline_handle);
+        case SYNC_GUEST_CMD_TRIGGER_HOST_WAIT:
+            DPRINT("exec SYNC_GUEST_CMD_TRIGGER_HOST_WAIT");
+            service_ops->trigger_host_wait(guest_incoming.glsync_handle,
+                                           guest_incoming.thread_handle,
+                                           guest_incoming.guest_timeline_handle);
             break;
-        case CMD_SYNC_READY:
-            DPRINT("exec CMD_SYNC_READY");
+        case SYNC_GUEST_CMD_READY:
+            DPRINT("exec SYNC_GUEST_CMD_READY");
             break;
         }
         break;
@@ -458,8 +444,6 @@
                           0x2000);
     sysbus_init_mmio(sbdev, &s->iomem);
     sysbus_init_irq(sbdev, &s->irq);
-
-    goldfish_sync_set_hw_funcs(&qemu2_goldfish_sync_hw_funcs);
 }
 
 static Property goldfish_sync_properties[] = {
diff --git a/include/hw/misc/goldfish_sync.h b/include/hw/misc/goldfish_sync.h
new file mode 100644
index 0000000..26d714a
--- /dev/null
+++ b/include/hw/misc/goldfish_sync.h
@@ -0,0 +1,60 @@
+/* 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_MISC_GOLDFISH_SYNC_H
+#define HW_MISC_GOLDFISH_SYNC_H
+
+#include <stdint.h>
+
+/* A list of commands to send to the guest through the goldfish_sync device
+ * CMD_CREATE_TIMELINE: used to create a new timeline handle.
+ * CMD_CREATE_FENCE: used to create a new sync fence handle.
+ * CMD_INCREMENT_TIMELINE: used to increment a timeline's value.
+ * CMD_DESTROY_TIMELINE: used to destroy a given timeline handle.
+ * and sync thread handle. */
+typedef enum {
+    GOLDFISH_SYNC_CMD_CREATE_TIMELINE = 1,
+    GOLDFISH_SYNC_CMD_CREATE_FENCE = 2,
+    GOLDFISH_SYNC_CMD_INCREMENT_TIMELINE = 3,
+    GOLDFISH_SYNC_CMD_DESTROY_TIMELINE = 4,
+} GoldfishSyncCommand;
+
+/* A set of callbacks that must be implemented by the host-side sync service
+ * and will be called by the virtual device at runtime. */
+typedef struct {
+    /* Called when the guest sends the result of a previous command to the
+     * host. See goldfish_send_send_command(). */
+    void (*receive_hostcmd_result)(uint32_t cmd,
+                                   uint64_t handle,
+                                   uint32_t time_arg,
+                                   uint64_t hostcmd_handle);
+
+    /* Called when the guest wants to trigger a host-side wait for a
+     * specific glsync and thread pointer pair. */
+    void (*trigger_host_wait)(uint64_t glsync_ptr,
+                              uint64_t thread_ptr,
+                              uint64_t timeline);
+} GoldfishSyncServiceOps;
+
+/* Register the host-side sync service callbacks with the device. This
+ * must be called at emulation setup time before the device runs. */
+void goldfish_sync_set_service_ops(const GoldfishSyncServiceOps *ops);
+
+/* Send a command to the guest through the goldfish_sync device.
+ * The result will be sent asynchronously through the |receive_hostcmd_result|
+ * callback. */
+void goldfish_sync_send_command(uint32_t cmd,
+                                uint64_t handle,
+                                uint32_t time_arg,
+                                uint64_t hostcmd_handle);
+
+#endif  /* HW_MISC_GOLDFISH_SYNC_H */