android: Add QEMU2 <-> AndroidEmu glue

This adds all the glue code required by QEMU2 to use the AndroidEmu
library and interface properly with it.

The next patch will modify vl.c to hook everything up at
emulation startup.
diff --git a/android-qemu2-glue/android_qemud.cpp b/android-qemu2-glue/android_qemud.cpp
new file mode 100644
index 0000000..26e4313
--- /dev/null
+++ b/android-qemu2-glue/android_qemud.cpp
@@ -0,0 +1,53 @@
+// 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/android_qemud.h"
+
+#include "android/emulation/android_qemud.h"
+#include "android/hw-qemud.h"
+#include "android-qemu2-glue/utils/stream.h"
+
+extern "C" {
+    #include "qemu-common.h"
+    #include "migration/vmstate.h"
+}
+
+/* Version number of snapshots code. Increment whenever the data saved
+ * or the layout in which it is saved is changed.
+ */
+#define QEMUD_SAVE_VERSION 5
+
+static void qemud_save(QEMUFile* f, void* opaque) {
+    Stream* stream = stream_from_qemufile(f);
+    QemudMultiplexer* m = static_cast<QemudMultiplexer*>(opaque);
+    qemud_multiplexer_save(m, stream);
+    stream_free(stream);
+}
+
+static int qemud_load(QEMUFile* f, void* opaque, int version) {
+    Stream* stream = stream_from_qemufile(f);
+    QemudMultiplexer* m = static_cast<QemudMultiplexer*>(opaque);
+    int ret = qemud_multiplexer_load(m, stream, version);
+    stream_free(stream);
+    return ret;
+}
+
+void android_qemu2_qemud_init(void) {
+    (void) android_qemud_get_serial_line();
+
+    register_savevm(nullptr,
+                    "qemud",
+                    0,
+                    QEMUD_SAVE_VERSION,
+                    qemud_save,
+                    qemud_load,
+                    qemud_multiplexer);
+}
diff --git a/android-qemu2-glue/android_qemud.h b/android-qemu2-glue/android_qemud.h
new file mode 100644
index 0000000..f898912
--- /dev/null
+++ b/android-qemu2-glue/android_qemud.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2007-2008 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/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+/* Initialize the qemud service for use in QEMU2
+ */
+extern void android_qemu2_qemud_init(void);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/base/async/Looper.cpp b/android-qemu2-glue/base/async/Looper.cpp
new file mode 100644
index 0000000..3aa29a6
--- /dev/null
+++ b/android-qemu2-glue/base/async/Looper.cpp
@@ -0,0 +1,340 @@
+// Copyright 2014 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/base/async/Looper.h"
+
+#include "android/base/Log.h"
+#include "android/base/containers/TailQueueList.h"
+#include "android/base/containers/ScopedPointerSet.h"
+#include "android/base/sockets/SocketUtils.h"
+#include "android-qemu2-glue/base/files/QemuFileStream.h"
+#include "android/utils/stream.h"
+
+extern "C" {
+#include "qemu-common.h"
+#include "qemu/timer.h"
+#include "sysemu/char.h"
+}  // extern "C"
+
+namespace android {
+namespace qemu {
+
+namespace {
+
+extern "C" void qemu_system_shutdown_request(void);
+
+typedef ::android::base::Looper BaseLooper;
+typedef ::android::base::Looper::Timer BaseTimer;
+typedef ::android::base::Looper::FdWatch BaseFdWatch;
+
+// An implementation of android::base::Looper on top of the QEMU main
+// event loop. There are few important things here:
+//
+//  1/ There is a single global QEMU event loop, so all instances returned
+//     by createLooper() will really use the same state!
+//
+//     In other words, don't call it more than once!
+//
+//  2/ It is not possible to call the runWithDeadlineMs() method, since
+//     the event loop is started in the application's main thread by
+//     the executable.
+//
+// The implementation uses a bottom-half handler to process pending
+// FdWatch instances, see the comment in the declaration of FdWatch
+// below to understand why.
+//
+class QemuLooper : public BaseLooper {
+public:
+    QemuLooper() :
+            Looper(),
+            mQemuBh(NULL),
+            mPendingFdWatches(),
+            mTimers() {
+    }
+
+    virtual ~QemuLooper() {
+        if (mQemuBh) {
+            qemu_bh_delete(mQemuBh);
+        }
+    }
+
+    static QEMUClockType toQemuClockType(ClockType clock) {
+        static_assert((int) QEMU_CLOCK_HOST == (int) BaseLooper::ClockType::kHost &&
+                      (int) QEMU_CLOCK_VIRTUAL == (int) BaseLooper::ClockType::kVirtual &&
+                      (int) QEMU_CLOCK_REALTIME == (int) BaseLooper::ClockType::kRealtime,
+                      "Values in the Looper::ClockType enumeration are out of sync with "
+                              "QEMUClockType");
+
+        return static_cast<QEMUClockType>(clock);
+    }
+
+    //
+    // F D   W A T C H E S
+    //
+
+    // Implementation is slightly more complicated because QEMU uses
+    // distinct callback functions for read/write events, so use a pending
+    // list to collect all FdWatch instances that have received any of such
+    // call, then later process it.
+
+    class FdWatch : public BaseFdWatch {
+    public:
+        FdWatch(QemuLooper* looper,
+                int fd,
+                BaseFdWatch::Callback callback,
+                void* opaque) :
+                        BaseFdWatch(looper, fd, callback, opaque),
+                        mWantedEvents(0U),
+                        mPendingEvents(0U),
+                        mLink() {
+        }
+
+        virtual ~FdWatch() {
+            clearPending();
+            qemu_set_fd_handler(mFd, NULL, NULL, NULL);
+        }
+
+        virtual void addEvents(unsigned events) {
+            events &= kEventMask;
+            updateEvents(mWantedEvents | events);
+        }
+
+        virtual void removeEvents(unsigned events) {
+            events &= kEventMask;
+            updateEvents(mWantedEvents & ~events);
+        }
+
+        virtual unsigned poll() const {
+            return mPendingEvents;
+        }
+
+        bool isPending() const {
+            return mPendingEvents != 0U;
+        }
+
+        void fire() {
+            DCHECK(mPendingEvents);
+            unsigned events = mPendingEvents;
+            mPendingEvents = 0U;
+            mCallback(mOpaque, mFd, events);
+        }
+
+        TAIL_QUEUE_LIST_TRAITS(Traits, FdWatch, mLink);
+
+    private:
+        void updateEvents(unsigned events) {
+            IOHandler* cbRead = (events & kEventRead) ? handleRead : NULL;
+            IOHandler* cbWrite = (events & kEventWrite) ? handleWrite : NULL;
+            qemu_set_fd_handler(mFd, cbRead, cbWrite, this);
+            mWantedEvents = events;
+        }
+
+        void setPending(unsigned event) {
+            if (!mPendingEvents) {
+                asQemuLooper(mLooper)->addPendingFdWatch(this);
+            }
+            mPendingEvents |= event;
+        }
+
+        void clearPending() {
+            if (mPendingEvents) {
+                asQemuLooper(mLooper)->delPendingFdWatch(this);
+                mPendingEvents = 0;
+            }
+        }
+
+        // Called by QEMU on a read i/o event. |opaque| is a FdWatch handle.
+        static void handleRead(void* opaque) {
+            FdWatch* watch = static_cast<FdWatch*>(opaque);
+            watch->setPending(kEventRead);
+        }
+
+        // Called by QEMU on a write i/o event. |opaque| is a FdWatch handle.
+        static void handleWrite(void* opaque) {
+            FdWatch* watch = static_cast<FdWatch*>(opaque);
+            watch->setPending(kEventWrite);
+        }
+
+        unsigned mWantedEvents;
+        unsigned mPendingEvents;
+        ::android::base::TailQueueLink<FdWatch> mLink;
+    };
+
+    virtual BaseFdWatch* createFdWatch(int fd,
+                                       BaseFdWatch::Callback callback,
+                                       void* opaque) {
+        ::android::base::socketSetNonBlocking(fd);
+        return new FdWatch(this, fd, callback, opaque);
+    }
+
+    //
+    // T I M E R S
+    //
+    class Timer : public BaseTimer {
+    public:
+        Timer(QemuLooper* looper,
+              BaseTimer::Callback callback,
+              void* opaque, ClockType clock) :
+                    BaseTimer(looper, callback, opaque, clock),
+                    mTimer(NULL) {
+            mTimer = ::timer_new(QemuLooper::toQemuClockType(mClockType),
+                                 SCALE_MS,
+                                 qemuTimerCallbackAdapter,
+                                 this);
+        }
+
+        ~Timer() {
+            ::timer_free(mTimer);
+        }
+
+        virtual void startRelative(Duration timeout_ms) {
+            if (timeout_ms == kDurationInfinite) {
+                timer_del(mTimer);
+            } else {
+                timeout_ms += qemu_clock_get_ms(
+                        QemuLooper::toQemuClockType(mClockType));
+                timer_mod(mTimer, timeout_ms);
+            }
+        }
+
+        virtual void startAbsolute(Duration deadline_ms) {
+            if (deadline_ms == kDurationInfinite) {
+                timer_del(mTimer);
+            } else {
+                timer_mod(mTimer, deadline_ms);
+            }
+        }
+
+        virtual void stop() {
+            ::timer_del(mTimer);
+        }
+
+        virtual bool isActive() const {
+            return timer_pending(mTimer);
+        }
+
+        void save(android::base::Stream* stream) const {
+            timer_put(
+                reinterpret_cast<android::qemu::QemuFileStream*>(stream)->file(),
+                mTimer);
+        }
+
+        void load(android::base::Stream* stream) {
+            timer_get(
+                reinterpret_cast<android::qemu::QemuFileStream*>(stream)->file(),
+                mTimer);
+        }
+
+    private:
+        static void qemuTimerCallbackAdapter(void* opaque) {
+            Timer* timer = static_cast<Timer*>(opaque);
+            timer->mCallback(timer->mOpaque, timer);
+        }
+
+        QEMUTimer* mTimer;
+    };
+
+    virtual BaseTimer* createTimer(BaseTimer::Callback callback,
+                                   void* opaque, ClockType clock) {
+        return new QemuLooper::Timer(this, callback, opaque, clock);
+    }
+
+    //
+    //  L O O P E R
+    //
+
+    virtual Duration nowMs(ClockType clockType) {
+        return qemu_clock_get_ms(toQemuClockType(clockType));
+    }
+
+    virtual DurationNs nowNs(ClockType clockType) {
+        return qemu_clock_get_ns(toQemuClockType(clockType));
+    }
+
+    virtual int runWithDeadlineMs(Duration deadline_ms) {
+        CHECK(false) << "User cannot call looper_run on a QEMU event loop";
+        errno = ENOSYS;
+        return -1;
+    }
+
+    virtual void forceQuit() {
+        qemu_system_shutdown_request();
+    }
+
+private:
+
+    typedef ::android::base::TailQueueList<QemuLooper::FdWatch> FdWatchList;
+    typedef ::android::base::ScopedPointerSet<FdWatch> FdWatchSet;
+    typedef ::android::base::ScopedPointerSet<Timer> TimerSet;
+
+    static inline QemuLooper* asQemuLooper(BaseLooper* looper) {
+        return reinterpret_cast<QemuLooper*>(looper);
+    }
+
+
+    void addTimer(Timer* timer) {
+        mTimers.add(timer);
+    }
+
+    void delTimer(Timer* timer) {
+        mTimers.remove(timer);
+    }
+
+    void addPendingFdWatch(FdWatch* watch) {
+        DCHECK(watch);
+        DCHECK(!watch->isPending());
+
+        if (mPendingFdWatches.empty()) {
+            // Ensure the bottom-half is triggered to act on pending
+            // watches as soon as possible.
+            if (!mQemuBh) {
+                mQemuBh = qemu_bh_new(handleBottomHalf, this);
+            }
+            qemu_bh_schedule(mQemuBh);
+        }
+
+        mPendingFdWatches.insertTail(watch);
+    }
+
+    void delPendingFdWatch(FdWatch* watch) {
+        DCHECK(watch);
+        DCHECK(watch->isPending());
+        mPendingFdWatches.remove(watch);
+    }
+
+    // Called by QEMU as soon as the main loop has finished processed
+    // I/O events. Used to look at pending watches and fire them.
+    static void handleBottomHalf(void* opaque) {
+        QemuLooper* looper = reinterpret_cast<QemuLooper*>(opaque);
+        for (;;) {
+            FdWatch* watch = looper->mPendingFdWatches.front();
+            if (!watch) {
+                break;
+            }
+            looper->delPendingFdWatch(watch);
+            watch->fire();
+        }
+    }
+
+    QEMUBH* mQemuBh;
+    FdWatchList mPendingFdWatches;
+    TimerSet mTimers;
+};
+
+}  // namespace
+
+BaseLooper* createLooper() {
+    return new QemuLooper();
+}
+
+}  // namespace qemu
+}  // namespace android
+
diff --git a/android-qemu2-glue/base/async/Looper.h b/android-qemu2-glue/base/async/Looper.h
new file mode 100644
index 0000000..970638b
--- /dev/null
+++ b/android-qemu2-glue/base/async/Looper.h
@@ -0,0 +1,27 @@
+// Copyright 2014 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/base/async/Looper.h"
+
+// An implementation of android::base::Looper based on the QEMU event loop.
+namespace android {
+namespace qemu {
+
+// Create a new android::base::Looper instance that is implemented through
+// the QEMU main event loop. There is only one instance, so any call will
+// return an object corresponding to the same global state, even if they
+// are different instances!
+android::base::Looper* createLooper();
+
+}  // namespace qemu
+}  // namespace android
diff --git a/android-qemu2-glue/base/files/QemuFileStream.cpp b/android-qemu2-glue/base/files/QemuFileStream.cpp
new file mode 100644
index 0000000..32ac51e
--- /dev/null
+++ b/android-qemu2-glue/base/files/QemuFileStream.cpp
@@ -0,0 +1,49 @@
+// 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/base/files/QemuFileStream.h"
+
+#include "android/base/Log.h"
+
+extern "C" {
+#include "qemu-common.h"
+#include "migration/qemu-file.h"
+}
+
+namespace android {
+namespace qemu {
+
+QemuFileStream::QemuFileStream(QEMUFile* file) : mFile(file) {}
+
+QemuFileStream::~QemuFileStream() {}
+
+ssize_t QemuFileStream::read(void* buffer, size_t len) {
+    DCHECK(static_cast<ssize_t>(len) >= 0);
+    DCHECK(static_cast<ssize_t>(len) == static_cast<int>(len));
+    return static_cast<ssize_t>(
+            qemu_get_buffer(mFile,
+                            static_cast<uint8_t*>(buffer),
+                            static_cast<int>(len)));
+}
+
+ssize_t QemuFileStream::write(const void* buffer, size_t len) {
+    DCHECK(static_cast<ssize_t>(len) >= 0);
+    DCHECK(static_cast<ssize_t>(len) == static_cast<int>(len));
+    qemu_put_buffer(mFile,
+                    static_cast<const uint8_t*>(buffer),
+                    static_cast<int>(len));
+    // There is no way to know if all could be written, so always
+    // return success here.
+    return static_cast<ssize_t>(len);
+}
+
+}  // namespace qemu
+}  // namespace android
diff --git a/android-qemu2-glue/base/files/QemuFileStream.h b/android-qemu2-glue/base/files/QemuFileStream.h
new file mode 100644
index 0000000..82b8247
--- /dev/null
+++ b/android-qemu2-glue/base/files/QemuFileStream.h
@@ -0,0 +1,42 @@
+// 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/base/Compiler.h"
+#include "android/base/files/Stream.h"
+
+struct QEMUFile;
+
+namespace android {
+namespace qemu {
+
+// A simple wrapper around QEMUFile* that implements the android::base::Stream
+// interface. Note that the instance doesn't own the QEMUFile*, i.e. the
+// destructor will never close it.
+class QemuFileStream : public android::base::Stream {
+public:
+    explicit QemuFileStream(QEMUFile* file);
+    virtual ~QemuFileStream();
+    virtual ssize_t read(void* buffer, size_t len);
+    virtual ssize_t write(const void* buffer, size_t len);
+
+    QEMUFile* file() const { return mFile; }
+
+private:
+    QemuFileStream();
+    DISALLOW_COPY_AND_ASSIGN(QemuFileStream);
+
+    QEMUFile* mFile;
+};
+
+}  // namespace qemu
+}  // namespace android
diff --git a/android-qemu2-glue/build/Makefile.qemu2-glue.mk b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
new file mode 100644
index 0000000..bb10d77
--- /dev/null
+++ b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
@@ -0,0 +1,42 @@
+# A static library containing the android-emu glue code
+
+$(call start-emulator-library,libqemu2_glue)
+
+LOCAL_CFLAGS += $(QEMU2_CFLAGS)
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_INCLUDES) \
+    $(LOCAL_PATH)/slirp \
+    $(LOCAL_PATH)/tcg \
+
+LOCAL_SRC_FILES := \
+    android_qemud.cpp \
+    display.cpp \
+    looper-qemu.cpp \
+    net-android.cpp \
+    qemu-battery-agent-impl.c \
+    qemu-cellular-agent-impl.c \
+    qemu-display-agent-impl.cpp \
+    qemu-finger-agent-impl.c \
+    qemu-location-agent-impl.c \
+    qemu-net-agent-impl.c \
+    qemu-sensors-agent-impl.c \
+    qemu-setup.cpp \
+    qemu-telephony-agent-impl.c \
+    qemu-user-event-agent-impl.c \
+    qemu-vm-operations-impl.c \
+    qemu-window-agent-impl.c \
+    utils/stream.cpp \
+    base/async/Looper.cpp \
+    base/files/QemuFileStream.cpp \
+    emulation/charpipe.c \
+    emulation/CharSerialLine.cpp \
+    emulation/serial_line.cpp \
+    emulation/VmLock.cpp \
+    telephony/modem_init.c \
+
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES:%=android-qemu2-glue/%)
+
+$(call end-emulator-library)
+
+QEMU2_GLUE_STATIC_LIBRARIES := libqemu2_glue
diff --git a/android-qemu2-glue/build/Makefile.qemu2-sources.mk b/android-qemu2-glue/build/Makefile.qemu2-sources.mk
new file mode 100644
index 0000000..08b3395
--- /dev/null
+++ b/android-qemu2-glue/build/Makefile.qemu2-sources.mk
@@ -0,0 +1,1110 @@
+# Auto-generated by gen-qemu2-sources-mk.py - DO NOT EDIT !!
+
+QEMU2_COMMON_SOURCES := \
+    accel.c \
+    async.c \
+    audio/audio.c \
+    audio/mixeng.c \
+    audio/noaudio.c \
+    audio/wavaudio.c \
+    audio/wavcapture.c \
+    backends/hostmem-ram.c \
+    backends/hostmem.c \
+    backends/msmouse.c \
+    backends/rng-egd.c \
+    backends/rng.c \
+    backends/testdev.c \
+    backends/tpm.c \
+    block-migration.c \
+    block.c \
+    block/accounting.c \
+    block/backup.c \
+    block/blkdebug.c \
+    block/blkverify.c \
+    block/block-backend.c \
+    block/bochs.c \
+    block/cloop.c \
+    block/commit.c \
+    block/dmg.c \
+    block/mirror.c \
+    block/nbd-client.c \
+    block/nbd.c \
+    block/null.c \
+    block/parallels.c \
+    block/qapi.c \
+    block/qcow.c \
+    block/qcow2-cache.c \
+    block/qcow2-cluster.c \
+    block/qcow2-refcount.c \
+    block/qcow2-snapshot.c \
+    block/qcow2.c \
+    block/qed-check.c \
+    block/qed-cluster.c \
+    block/qed-gencb.c \
+    block/qed-l2-cache.c \
+    block/qed-table.c \
+    block/qed.c \
+    block/raw_bsd.c \
+    block/sheepdog.c \
+    block/snapshot.c \
+    block/stream.c \
+    block/vdi.c \
+    block/vmdk.c \
+    block/vpc.c \
+    block/vvfat.c \
+    blockdev-nbd.c \
+    blockdev.c \
+    blockjob.c \
+    bt-host.c \
+    bt-vhci.c \
+    device-hotplug.c \
+    disas/i386.c \
+    dma-helpers.c \
+    hmp.c \
+    hw/audio/ac97.c \
+    hw/audio/es1370.c \
+    hw/audio/hda-codec.c \
+    hw/audio/intel-hda.c \
+    hw/block/block.c \
+    hw/block/cdrom.c \
+    hw/block/hd-geometry.c \
+    hw/block/nvme.c \
+    hw/block/pflash_cfi01.c \
+    hw/bt/core.c \
+    hw/bt/hci-csr.c \
+    hw/bt/hci.c \
+    hw/bt/hid.c \
+    hw/bt/l2cap.c \
+    hw/bt/sdp.c \
+    hw/char/ipoctal232.c \
+    hw/char/serial-isa.c \
+    hw/char/serial-pci.c \
+    hw/char/serial.c \
+    hw/char/virtio-console.c \
+    hw/char/virtio-pingpong.c \
+    hw/core/fw-path-provider.c \
+    hw/core/hotplug.c \
+    hw/core/irq.c \
+    hw/core/loader.c \
+    hw/core/machine.c \
+    hw/core/nmi.c \
+    hw/core/null-machine.c \
+    hw/core/platform-bus.c \
+    hw/core/qdev-properties-system.c \
+    hw/core/qdev-properties.c \
+    hw/core/qdev.c \
+    hw/core/sysbus.c \
+    hw/i2c/core.c \
+    hw/i2c/smbus.c \
+    hw/i2c/smbus_eeprom.c \
+    hw/ide/ahci.c \
+    hw/ide/atapi.c \
+    hw/ide/core.c \
+    hw/ide/ich.c \
+    hw/ide/pci.c \
+    hw/ide/qdev.c \
+    hw/input/hid.c \
+    hw/input/ps2.c \
+    hw/ipack/ipack.c \
+    hw/ipack/tpci200.c \
+    hw/isa/isa-bus.c \
+    hw/misc/pci-testdev.c \
+    hw/net/e1000.c \
+    hw/net/eepro100.c \
+    hw/net/ne2000.c \
+    hw/net/pcnet-pci.c \
+    hw/net/pcnet.c \
+    hw/net/rtl8139.c \
+    hw/net/vmxnet3.c \
+    hw/net/vmxnet_rx_pkt.c \
+    hw/net/vmxnet_tx_pkt.c \
+    hw/nvram/eeprom93xx.c \
+    hw/nvram/fw_cfg.c \
+    hw/pci-bridge/i82801b11.c \
+    hw/pci-bridge/ioh3420.c \
+    hw/pci-bridge/pci_bridge_dev.c \
+    hw/pci-bridge/xio3130_downstream.c \
+    hw/pci-bridge/xio3130_upstream.c \
+    hw/pci-host/pam.c \
+    hw/pci/msi.c \
+    hw/pci/msix.c \
+    hw/pci/pci.c \
+    hw/pci/pci_bridge.c \
+    hw/pci/pci_host.c \
+    hw/pci/pcie.c \
+    hw/pci/pcie_aer.c \
+    hw/pci/pcie_host.c \
+    hw/pci/pcie_port.c \
+    hw/pci/shpc.c \
+    hw/pci/slotid_cap.c \
+    hw/pcmcia/pcmcia.c \
+    hw/scsi/esp-pci.c \
+    hw/scsi/esp.c \
+    hw/scsi/lsi53c895a.c \
+    hw/scsi/megasas.c \
+    hw/scsi/scsi-bus.c \
+    hw/scsi/scsi-disk.c \
+    hw/scsi/scsi-generic.c \
+    hw/scsi/vmw_pvscsi.c \
+    hw/usb/bus.c \
+    hw/usb/ccid-card-passthru.c \
+    hw/usb/combined-packet.c \
+    hw/usb/core.c \
+    hw/usb/desc-msos.c \
+    hw/usb/desc.c \
+    hw/usb/dev-audio.c \
+    hw/usb/dev-bluetooth.c \
+    hw/usb/dev-hid.c \
+    hw/usb/dev-hub.c \
+    hw/usb/dev-network.c \
+    hw/usb/dev-serial.c \
+    hw/usb/dev-smartcard-reader.c \
+    hw/usb/dev-storage.c \
+    hw/usb/dev-uas.c \
+    hw/usb/dev-wacom.c \
+    hw/usb/hcd-ehci-pci.c \
+    hw/usb/hcd-ehci-sysbus.c \
+    hw/usb/hcd-ehci.c \
+    hw/usb/hcd-ohci.c \
+    hw/usb/hcd-uhci.c \
+    hw/usb/hcd-xhci.c \
+    hw/usb/host-stub.c \
+    hw/usb/libhw.c \
+    hw/virtio/dataplane/vring.c \
+    hw/virtio/virtio-bus.c \
+    hw/virtio/virtio-mmio.c \
+    hw/virtio/virtio-pci.c \
+    hw/virtio/virtio-rng.c \
+    hw/watchdog/watchdog.c \
+    hw/watchdog/wdt_i6300esb.c \
+    iohandler.c \
+    iothread.c \
+    main-loop.c \
+    migration-tcp.c \
+    migration.c \
+    nbd.c \
+    net/checksum.c \
+    net/dump.c \
+    net/eth.c \
+    net/hub.c \
+    net/net.c \
+    net/queue.c \
+    net/slirp.c \
+    net/socket.c \
+    net/util.c \
+    page_cache.c \
+    qdev-monitor.c \
+    qemu-char.c \
+    qemu-coroutine-io.c \
+    qemu-coroutine-lock.c \
+    qemu-coroutine-sleep.c \
+    qemu-coroutine.c \
+    qemu-file-stdio.c \
+    qemu-file-unix.c \
+    qemu-file.c \
+    qemu-io-cmds.c \
+    qemu-log.c \
+    qemu-timer.c \
+    qmp.c \
+    qom/container.c \
+    qom/cpu.c \
+    qom/object.c \
+    qom/object_interfaces.c \
+    qom/qom-qobject.c \
+    slirp/arp_table.c \
+    slirp/bootp.c \
+    slirp/cksum.c \
+    slirp/dnssearch.c \
+    slirp/if.c \
+    slirp/ip_icmp.c \
+    slirp/ip_input.c \
+    slirp/ip_output.c \
+    slirp/mbuf.c \
+    slirp/misc.c \
+    slirp/sbuf.c \
+    slirp/slirp.c \
+    slirp/socket.c \
+    slirp/tcp_input.c \
+    slirp/tcp_output.c \
+    slirp/tcp_subr.c \
+    slirp/tcp_timer.c \
+    slirp/tftp.c \
+    slirp/udp.c \
+    tcg-runtime.c \
+    thread-pool.c \
+    tpm.c \
+    ui/console.c \
+    ui/cursor.c \
+    ui/d3des.c \
+    ui/input-keymap.c \
+    ui/input-legacy.c \
+    ui/input.c \
+    ui/keymaps.c \
+    ui/qemu-pixman.c \
+    ui/vnc-enc-hextile.c \
+    ui/vnc-enc-tight.c \
+    ui/vnc-enc-zlib.c \
+    ui/vnc-enc-zrle.c \
+    ui/vnc-jobs.c \
+    ui/vnc-palette.c \
+    ui/vnc.c \
+    ui/x_keymap.c \
+    vmstate.c \
+    xbzrle.c \
+
+QEMU2_COMMON_SOURCES_darwin-x86_64 := \
+    aio-posix.c \
+    audio/coreaudio.c \
+    backends/rng-random.c \
+    block/raw-posix.c \
+    coroutine-sigaltstack.c \
+    hw/usb/dev-mtp.c \
+    migration-exec.c \
+    migration-fd.c \
+    migration-unix.c \
+    net/tap-bsd.c \
+    net/tap.c \
+    net/vhost-user.c \
+    os-posix.c \
+
+QEMU2_COMMON_SOURCES_linux-x86_64 := \
+    aio-posix.c \
+    audio/audio_pt_int.c \
+    audio/paaudio.c \
+    backends/hostmem-file.c \
+    backends/rng-random.c \
+    block/raw-posix.c \
+    coroutine-ucontext.c \
+    fsdev/qemu-fsdev-dummy.c \
+    fsdev/qemu-fsdev-opts.c \
+    hw/tpm/tpm_passthrough.c \
+    hw/usb/dev-mtp.c \
+    migration-exec.c \
+    migration-fd.c \
+    migration-unix.c \
+    net/tap-linux.c \
+    net/tap.c \
+    net/vhost-user.c \
+    os-posix.c \
+
+QEMU2_COMMON_SOURCES_windows-x86 := \
+    aio-win32.c \
+    audio/audio_win_int.c \
+    audio/winaudio.c \
+    audio/winwaveaudio.c \
+    block/raw-win32.c \
+    block/win32-aio.c \
+    coroutine-win32.c \
+    net/tap-win32.c \
+    os-win32.c \
+
+QEMU2_COMMON_SOURCES_windows-x86_64 := \
+    aio-win32.c \
+    audio/audio_win_int.c \
+    audio/winaudio.c \
+    audio/winwaveaudio.c \
+    block/raw-win32.c \
+    block/win32-aio.c \
+    coroutine-win32.c \
+    net/tap-win32.c \
+    os-win32.c \
+
+QEMU2_TARGET_SOURCES := \
+    arch_init.c \
+    balloon.c \
+    bootdevice.c \
+    cpu-exec.c \
+    cpus.c \
+    cputlb.c \
+    device_tree.c \
+    disas.c \
+    dump.c \
+    exec.c \
+    fpu/softfloat.c \
+    gdbstub.c \
+    hw/block/dataplane/virtio-blk.c \
+    hw/block/virtio-blk.c \
+    hw/char/virtio-serial-bus.c \
+    hw/display/vga.c \
+    hw/net/vhost_net.c \
+    hw/net/virtio-net.c \
+    hw/scsi/virtio-scsi-dataplane.c \
+    hw/scsi/virtio-scsi.c \
+    hw/virtio/virtio-balloon.c \
+    hw/virtio/virtio.c \
+    ioport.c \
+    memory.c \
+    memory_mapping.c \
+    monitor.c \
+    numa.c \
+    qtest.c \
+    savevm.c \
+    tcg/optimize.c \
+    tcg/tcg.c \
+    translate-all.c \
+    vl.c \
+    xen-common-stub.c \
+    xen-hvm-stub.c \
+
+QEMU2_TARGET_aarch64_SOURCES := \
+    disas/arm.c \
+    hax-stub.c \
+    hw/arm/allwinner-a10.c \
+    hw/arm/armv7m.c \
+    hw/arm/boot.c \
+    hw/arm/collie.c \
+    hw/arm/cubieboard.c \
+    hw/arm/digic.c \
+    hw/arm/digic_boards.c \
+    hw/arm/exynos4210.c \
+    hw/arm/exynos4_boards.c \
+    hw/arm/gumstix.c \
+    hw/arm/highbank.c \
+    hw/arm/integratorcp.c \
+    hw/arm/kzm.c \
+    hw/arm/mainstone.c \
+    hw/arm/musicpal.c \
+    hw/arm/nseries.c \
+    hw/arm/omap1.c \
+    hw/arm/omap2.c \
+    hw/arm/omap_sx1.c \
+    hw/arm/palm.c \
+    hw/arm/pxa2xx.c \
+    hw/arm/pxa2xx_gpio.c \
+    hw/arm/pxa2xx_pic.c \
+    hw/arm/realview.c \
+    hw/arm/spitz.c \
+    hw/arm/stellaris.c \
+    hw/arm/strongarm.c \
+    hw/arm/tosa.c \
+    hw/arm/versatilepb.c \
+    hw/arm/vexpress.c \
+    hw/arm/virt.c \
+    hw/arm/xilinx_zynq.c \
+    hw/arm/z2.c \
+    hw/audio/lm4549.c \
+    hw/audio/marvell_88w8618.c \
+    hw/audio/pl041.c \
+    hw/audio/wm8750.c \
+    hw/block/ecc.c \
+    hw/block/m25p80.c \
+    hw/block/nand.c \
+    hw/block/onenand.c \
+    hw/block/pflash_cfi02.c \
+    hw/char/cadence_uart.c \
+    hw/char/digic-uart.c \
+    hw/char/exynos4210_uart.c \
+    hw/char/imx_serial.c \
+    hw/char/omap_uart.c \
+    hw/char/pl011.c \
+    hw/core/ptimer.c \
+    hw/cpu/a15mpcore.c \
+    hw/cpu/a9mpcore.c \
+    hw/cpu/arm11mpcore.c \
+    hw/cpu/realview_mpcore.c \
+    hw/display/ads7846.c \
+    hw/display/blizzard.c \
+    hw/display/exynos4210_fimd.c \
+    hw/display/omap_dss.c \
+    hw/display/omap_lcdc.c \
+    hw/display/pl110.c \
+    hw/display/pxa2xx_lcd.c \
+    hw/display/ssd0303.c \
+    hw/display/ssd0323.c \
+    hw/display/tc6393xb.c \
+    hw/dma/omap_dma.c \
+    hw/dma/pl080.c \
+    hw/dma/pl330.c \
+    hw/dma/pxa2xx_dma.c \
+    hw/dma/soc_dma.c \
+    hw/gpio/max7310.c \
+    hw/gpio/omap_gpio.c \
+    hw/gpio/pl061.c \
+    hw/gpio/zaurus.c \
+    hw/i2c/bitbang_i2c.c \
+    hw/i2c/exynos4210_i2c.c \
+    hw/i2c/omap_i2c.c \
+    hw/i2c/versatile_i2c.c \
+    hw/ide/microdrive.c \
+    hw/input/lm832x.c \
+    hw/input/pl050.c \
+    hw/input/pxa2xx_keypad.c \
+    hw/input/stellaris_input.c \
+    hw/input/tsc2005.c \
+    hw/input/tsc210x.c \
+    hw/intc/allwinner-a10-pic.c \
+    hw/intc/arm_gic.c \
+    hw/intc/arm_gic_common.c \
+    hw/intc/armv7m_nvic.c \
+    hw/intc/exynos4210_combiner.c \
+    hw/intc/exynos4210_gic.c \
+    hw/intc/imx_avic.c \
+    hw/intc/omap_intc.c \
+    hw/intc/pl190.c \
+    hw/intc/realview_gic.c \
+    hw/misc/a9scu.c \
+    hw/misc/arm11scu.c \
+    hw/misc/arm_integrator_debug.c \
+    hw/misc/arm_l2x0.c \
+    hw/misc/arm_sysctl.c \
+    hw/misc/cbus.c \
+    hw/misc/exynos4210_pmu.c \
+    hw/misc/imx_ccm.c \
+    hw/misc/max111x.c \
+    hw/misc/mst_fpga.c \
+    hw/misc/omap_clk.c \
+    hw/misc/omap_gpmc.c \
+    hw/misc/omap_l4.c \
+    hw/misc/omap_sdrc.c \
+    hw/misc/omap_tap.c \
+    hw/misc/tmp105.c \
+    hw/misc/zynq_slcr.c \
+    hw/net/allwinner_emac.c \
+    hw/net/cadence_gem.c \
+    hw/net/lan9118.c \
+    hw/net/smc91c111.c \
+    hw/net/stellaris_enet.c \
+    hw/net/xgmac.c \
+    hw/pci-host/versatile.c \
+    hw/pcmcia/pxa2xx.c \
+    hw/sd/omap_mmc.c \
+    hw/sd/pl181.c \
+    hw/sd/pxa2xx_mmci.c \
+    hw/sd/sd.c \
+    hw/sd/sdhci.c \
+    hw/sd/ssi-sd.c \
+    hw/ssi/omap_spi.c \
+    hw/ssi/pl022.c \
+    hw/ssi/ssi.c \
+    hw/ssi/xilinx_spips.c \
+    hw/timer/a9gtimer.c \
+    hw/timer/allwinner-a10-pit.c \
+    hw/timer/arm_mptimer.c \
+    hw/timer/arm_timer.c \
+    hw/timer/cadence_ttc.c \
+    hw/timer/digic-timer.c \
+    hw/timer/ds1338.c \
+    hw/timer/exynos4210_mct.c \
+    hw/timer/exynos4210_pwm.c \
+    hw/timer/exynos4210_rtc.c \
+    hw/timer/imx_epit.c \
+    hw/timer/imx_gpt.c \
+    hw/timer/omap_gptimer.c \
+    hw/timer/omap_synctimer.c \
+    hw/timer/pl031.c \
+    hw/timer/pxa2xx_timer.c \
+    hw/timer/tusb6010.c \
+    hw/timer/twl92230.c \
+    hw/usb/hcd-musb.c \
+    kvm-stub.c \
+    target-arm/arm-semi.c \
+    target-arm/cpu.c \
+    target-arm/cpu64.c \
+    target-arm/crypto_helper.c \
+    target-arm/gdbstub.c \
+    target-arm/gdbstub64.c \
+    target-arm/helper-a64.c \
+    target-arm/helper.c \
+    target-arm/iwmmxt_helper.c \
+    target-arm/kvm-stub.c \
+    target-arm/machine.c \
+    target-arm/neon_helper.c \
+    target-arm/op_helper.c \
+    target-arm/psci.c \
+    target-arm/translate-a64.c \
+    target-arm/translate.c \
+
+QEMU2_TARGET_arm_SOURCES := \
+    disas/arm.c \
+    hax-stub.c \
+    hw/arm/allwinner-a10.c \
+    hw/arm/armv7m.c \
+    hw/arm/boot.c \
+    hw/arm/collie.c \
+    hw/arm/cubieboard.c \
+    hw/arm/digic.c \
+    hw/arm/digic_boards.c \
+    hw/arm/exynos4210.c \
+    hw/arm/exynos4_boards.c \
+    hw/arm/gumstix.c \
+    hw/arm/highbank.c \
+    hw/arm/integratorcp.c \
+    hw/arm/kzm.c \
+    hw/arm/mainstone.c \
+    hw/arm/musicpal.c \
+    hw/arm/nseries.c \
+    hw/arm/omap1.c \
+    hw/arm/omap2.c \
+    hw/arm/omap_sx1.c \
+    hw/arm/palm.c \
+    hw/arm/pxa2xx.c \
+    hw/arm/pxa2xx_gpio.c \
+    hw/arm/pxa2xx_pic.c \
+    hw/arm/realview.c \
+    hw/arm/spitz.c \
+    hw/arm/stellaris.c \
+    hw/arm/strongarm.c \
+    hw/arm/tosa.c \
+    hw/arm/versatilepb.c \
+    hw/arm/vexpress.c \
+    hw/arm/virt.c \
+    hw/arm/xilinx_zynq.c \
+    hw/arm/z2.c \
+    hw/audio/lm4549.c \
+    hw/audio/marvell_88w8618.c \
+    hw/audio/pl041.c \
+    hw/audio/wm8750.c \
+    hw/block/ecc.c \
+    hw/block/m25p80.c \
+    hw/block/nand.c \
+    hw/block/onenand.c \
+    hw/block/pflash_cfi02.c \
+    hw/char/cadence_uart.c \
+    hw/char/digic-uart.c \
+    hw/char/exynos4210_uart.c \
+    hw/char/imx_serial.c \
+    hw/char/omap_uart.c \
+    hw/char/pl011.c \
+    hw/core/ptimer.c \
+    hw/cpu/a15mpcore.c \
+    hw/cpu/a9mpcore.c \
+    hw/cpu/arm11mpcore.c \
+    hw/cpu/realview_mpcore.c \
+    hw/display/ads7846.c \
+    hw/display/blizzard.c \
+    hw/display/exynos4210_fimd.c \
+    hw/display/omap_dss.c \
+    hw/display/omap_lcdc.c \
+    hw/display/pl110.c \
+    hw/display/pxa2xx_lcd.c \
+    hw/display/ssd0303.c \
+    hw/display/ssd0323.c \
+    hw/display/tc6393xb.c \
+    hw/dma/omap_dma.c \
+    hw/dma/pl080.c \
+    hw/dma/pl330.c \
+    hw/dma/pxa2xx_dma.c \
+    hw/dma/soc_dma.c \
+    hw/gpio/max7310.c \
+    hw/gpio/omap_gpio.c \
+    hw/gpio/pl061.c \
+    hw/gpio/zaurus.c \
+    hw/i2c/bitbang_i2c.c \
+    hw/i2c/exynos4210_i2c.c \
+    hw/i2c/omap_i2c.c \
+    hw/i2c/versatile_i2c.c \
+    hw/ide/microdrive.c \
+    hw/input/lm832x.c \
+    hw/input/pl050.c \
+    hw/input/pxa2xx_keypad.c \
+    hw/input/stellaris_input.c \
+    hw/input/tsc2005.c \
+    hw/input/tsc210x.c \
+    hw/intc/allwinner-a10-pic.c \
+    hw/intc/arm_gic.c \
+    hw/intc/arm_gic_common.c \
+    hw/intc/armv7m_nvic.c \
+    hw/intc/exynos4210_combiner.c \
+    hw/intc/exynos4210_gic.c \
+    hw/intc/imx_avic.c \
+    hw/intc/omap_intc.c \
+    hw/intc/pl190.c \
+    hw/intc/realview_gic.c \
+    hw/misc/a9scu.c \
+    hw/misc/arm11scu.c \
+    hw/misc/arm_integrator_debug.c \
+    hw/misc/arm_l2x0.c \
+    hw/misc/arm_sysctl.c \
+    hw/misc/cbus.c \
+    hw/misc/exynos4210_pmu.c \
+    hw/misc/imx_ccm.c \
+    hw/misc/max111x.c \
+    hw/misc/mst_fpga.c \
+    hw/misc/omap_clk.c \
+    hw/misc/omap_gpmc.c \
+    hw/misc/omap_l4.c \
+    hw/misc/omap_sdrc.c \
+    hw/misc/omap_tap.c \
+    hw/misc/tmp105.c \
+    hw/misc/zynq_slcr.c \
+    hw/net/allwinner_emac.c \
+    hw/net/cadence_gem.c \
+    hw/net/lan9118.c \
+    hw/net/smc91c111.c \
+    hw/net/stellaris_enet.c \
+    hw/net/xgmac.c \
+    hw/pci-host/versatile.c \
+    hw/pcmcia/pxa2xx.c \
+    hw/sd/omap_mmc.c \
+    hw/sd/pl181.c \
+    hw/sd/pxa2xx_mmci.c \
+    hw/sd/sd.c \
+    hw/sd/sdhci.c \
+    hw/sd/ssi-sd.c \
+    hw/ssi/omap_spi.c \
+    hw/ssi/pl022.c \
+    hw/ssi/ssi.c \
+    hw/ssi/xilinx_spips.c \
+    hw/timer/a9gtimer.c \
+    hw/timer/allwinner-a10-pit.c \
+    hw/timer/arm_mptimer.c \
+    hw/timer/arm_timer.c \
+    hw/timer/cadence_ttc.c \
+    hw/timer/digic-timer.c \
+    hw/timer/ds1338.c \
+    hw/timer/exynos4210_mct.c \
+    hw/timer/exynos4210_pwm.c \
+    hw/timer/exynos4210_rtc.c \
+    hw/timer/imx_epit.c \
+    hw/timer/imx_gpt.c \
+    hw/timer/omap_gptimer.c \
+    hw/timer/omap_synctimer.c \
+    hw/timer/pl031.c \
+    hw/timer/pxa2xx_timer.c \
+    hw/timer/tusb6010.c \
+    hw/timer/twl92230.c \
+    hw/usb/hcd-musb.c \
+    kvm-stub.c \
+    target-arm/arm-semi.c \
+    target-arm/cpu.c \
+    target-arm/crypto_helper.c \
+    target-arm/gdbstub.c \
+    target-arm/helper.c \
+    target-arm/iwmmxt_helper.c \
+    target-arm/kvm-stub.c \
+    target-arm/machine.c \
+    target-arm/neon_helper.c \
+    target-arm/op_helper.c \
+    target-arm/psci.c \
+    target-arm/translate.c \
+
+QEMU2_TARGET_i386_SOURCES := \
+    hw/acpi/acpi_interface.c \
+    hw/acpi/core.c \
+    hw/acpi/cpu_hotplug.c \
+    hw/acpi/ich9.c \
+    hw/acpi/memory_hotplug.c \
+    hw/acpi/pcihp.c \
+    hw/acpi/piix4.c \
+    hw/audio/adlib.c \
+    hw/audio/cs4231a.c \
+    hw/audio/fmopl.c \
+    hw/audio/gus.c \
+    hw/audio/gusemu_hal.c \
+    hw/audio/gusemu_mixer.c \
+    hw/audio/pcspk.c \
+    hw/audio/sb16.c \
+    hw/block/fdc.c \
+    hw/char/debugcon.c \
+    hw/char/parallel.c \
+    hw/cpu/icc_bus.c \
+    hw/display/cirrus_vga.c \
+    hw/display/vga-isa.c \
+    hw/display/vga-pci.c \
+    hw/display/vmware_vga.c \
+    hw/dma/i8257.c \
+    hw/i2c/pm_smbus.c \
+    hw/i2c/smbus_ich9.c \
+    hw/i386/acpi-build.c \
+    hw/i386/bios-linker-loader.c \
+    hw/i386/intel_iommu.c \
+    hw/i386/kvmvapic.c \
+    hw/i386/multiboot.c \
+    hw/i386/pc.c \
+    hw/i386/pc_piix.c \
+    hw/i386/pc_q35.c \
+    hw/i386/pc_sysfw.c \
+    hw/i386/smbios.c \
+    hw/ide/isa.c \
+    hw/ide/piix.c \
+    hw/input/pckbd.c \
+    hw/input/vmmouse.c \
+    hw/intc/apic.c \
+    hw/intc/apic_common.c \
+    hw/intc/i8259.c \
+    hw/intc/i8259_common.c \
+    hw/intc/ioapic.c \
+    hw/intc/ioapic_common.c \
+    hw/isa/apm.c \
+    hw/isa/lpc_ich9.c \
+    hw/mem/pc-dimm.c \
+    hw/misc/applesmc.c \
+    hw/misc/debugexit.c \
+    hw/misc/pc-testdev.c \
+    hw/misc/pvpanic.c \
+    hw/misc/sga.c \
+    hw/misc/vmport.c \
+    hw/net/ne2000-isa.c \
+    hw/pci-host/piix.c \
+    hw/pci-host/q35.c \
+    hw/pci/pci-hotplug-old.c \
+    hw/timer/hpet.c \
+    hw/timer/i8254.c \
+    hw/timer/i8254_common.c \
+    hw/timer/mc146818rtc.c \
+    hw/tpm/tpm_tis.c \
+    hw/watchdog/wdt_ib700.c \
+    target-i386/arch_dump.c \
+    target-i386/arch_memory_mapping.c \
+    target-i386/cc_helper.c \
+    target-i386/cpu.c \
+    target-i386/excp_helper.c \
+    target-i386/fpu_helper.c \
+    target-i386/gdbstub.c \
+    target-i386/helper.c \
+    target-i386/int_helper.c \
+    target-i386/machine.c \
+    target-i386/mem_helper.c \
+    target-i386/misc_helper.c \
+    target-i386/seg_helper.c \
+    target-i386/smm_helper.c \
+    target-i386/svm_helper.c \
+    target-i386/translate.c \
+
+QEMU2_TARGET_mips64el_SOURCES := \
+    disas/mips.c \
+    hax-stub.c \
+    hw/acpi/acpi_interface.c \
+    hw/acpi/core.c \
+    hw/acpi/cpu_hotplug.c \
+    hw/acpi/ich9.c \
+    hw/acpi/memory_hotplug.c \
+    hw/acpi/pcihp.c \
+    hw/acpi/piix4.c \
+    hw/audio/adlib.c \
+    hw/audio/cs4231a.c \
+    hw/audio/fmopl.c \
+    hw/audio/gus.c \
+    hw/audio/gusemu_hal.c \
+    hw/audio/gusemu_mixer.c \
+    hw/audio/pcspk.c \
+    hw/audio/sb16.c \
+    hw/block/fdc.c \
+    hw/char/parallel.c \
+    hw/core/empty_slot.c \
+    hw/display/cirrus_vga.c \
+    hw/display/g364fb.c \
+    hw/display/jazz_led.c \
+    hw/display/vga-isa-mm.c \
+    hw/display/vga-isa.c \
+    hw/display/vga-pci.c \
+    hw/display/vmware_vga.c \
+    hw/dma/i8257.c \
+    hw/dma/rc4030.c \
+    hw/i2c/pm_smbus.c \
+    hw/i2c/smbus_ich9.c \
+    hw/ide/isa.c \
+    hw/ide/piix.c \
+    hw/ide/via.c \
+    hw/input/pckbd.c \
+    hw/intc/i8259.c \
+    hw/intc/i8259_common.c \
+    hw/isa/apm.c \
+    hw/isa/piix4.c \
+    hw/isa/vt82c686.c \
+    hw/mips/addr.c \
+    hw/mips/cputimer.c \
+    hw/mips/gt64xxx_pci.c \
+    hw/mips/mips_fulong2e.c \
+    hw/mips/mips_int.c \
+    hw/mips/mips_jazz.c \
+    hw/mips/mips_malta.c \
+    hw/mips/mips_mipssim.c \
+    hw/mips/mips_r4k.c \
+    hw/misc/pc-testdev.c \
+    hw/net/dp8393x.c \
+    hw/net/mipsnet.c \
+    hw/net/ne2000-isa.c \
+    hw/nvram/ds1225y.c \
+    hw/pci-host/bonito.c \
+    hw/timer/i8254.c \
+    hw/timer/i8254_common.c \
+    hw/timer/mc146818rtc.c \
+    kvm-stub.c \
+    target-mips/cpu.c \
+    target-mips/dsp_helper.c \
+    target-mips/gdbstub.c \
+    target-mips/helper.c \
+    target-mips/lmi_helper.c \
+    target-mips/machine.c \
+    target-mips/msa_helper.c \
+    target-mips/op_helper.c \
+    target-mips/translate.c \
+
+QEMU2_TARGET_mipsel_SOURCES := \
+    disas/mips.c \
+    hax-stub.c \
+    hw/acpi/acpi_interface.c \
+    hw/acpi/core.c \
+    hw/acpi/cpu_hotplug.c \
+    hw/acpi/ich9.c \
+    hw/acpi/memory_hotplug.c \
+    hw/acpi/pcihp.c \
+    hw/acpi/piix4.c \
+    hw/audio/adlib.c \
+    hw/audio/cs4231a.c \
+    hw/audio/fmopl.c \
+    hw/audio/gus.c \
+    hw/audio/gusemu_hal.c \
+    hw/audio/gusemu_mixer.c \
+    hw/audio/pcspk.c \
+    hw/audio/sb16.c \
+    hw/block/fdc.c \
+    hw/char/parallel.c \
+    hw/core/empty_slot.c \
+    hw/display/cirrus_vga.c \
+    hw/display/g364fb.c \
+    hw/display/jazz_led.c \
+    hw/display/vga-isa-mm.c \
+    hw/display/vga-isa.c \
+    hw/display/vga-pci.c \
+    hw/display/vmware_vga.c \
+    hw/dma/i8257.c \
+    hw/dma/rc4030.c \
+    hw/i2c/pm_smbus.c \
+    hw/i2c/smbus_ich9.c \
+    hw/ide/isa.c \
+    hw/ide/piix.c \
+    hw/input/pckbd.c \
+    hw/intc/i8259.c \
+    hw/intc/i8259_common.c \
+    hw/isa/apm.c \
+    hw/isa/piix4.c \
+    hw/mips/addr.c \
+    hw/mips/cputimer.c \
+    hw/mips/gt64xxx_pci.c \
+    hw/mips/mips_int.c \
+    hw/mips/mips_jazz.c \
+    hw/mips/mips_malta.c \
+    hw/mips/mips_mipssim.c \
+    hw/mips/mips_r4k.c \
+    hw/misc/pc-testdev.c \
+    hw/net/dp8393x.c \
+    hw/net/mipsnet.c \
+    hw/net/ne2000-isa.c \
+    hw/nvram/ds1225y.c \
+    hw/timer/i8254.c \
+    hw/timer/i8254_common.c \
+    hw/timer/mc146818rtc.c \
+    kvm-stub.c \
+    target-mips/cpu.c \
+    target-mips/dsp_helper.c \
+    target-mips/gdbstub.c \
+    target-mips/helper.c \
+    target-mips/lmi_helper.c \
+    target-mips/machine.c \
+    target-mips/msa_helper.c \
+    target-mips/op_helper.c \
+    target-mips/translate.c \
+
+QEMU2_TARGET_x86_64_SOURCES := \
+    hw/acpi/acpi_interface.c \
+    hw/acpi/core.c \
+    hw/acpi/cpu_hotplug.c \
+    hw/acpi/ich9.c \
+    hw/acpi/memory_hotplug.c \
+    hw/acpi/pcihp.c \
+    hw/acpi/piix4.c \
+    hw/audio/adlib.c \
+    hw/audio/cs4231a.c \
+    hw/audio/fmopl.c \
+    hw/audio/gus.c \
+    hw/audio/gusemu_hal.c \
+    hw/audio/gusemu_mixer.c \
+    hw/audio/pcspk.c \
+    hw/audio/sb16.c \
+    hw/block/fdc.c \
+    hw/char/debugcon.c \
+    hw/char/parallel.c \
+    hw/cpu/icc_bus.c \
+    hw/display/cirrus_vga.c \
+    hw/display/vga-isa.c \
+    hw/display/vga-pci.c \
+    hw/display/vmware_vga.c \
+    hw/dma/i8257.c \
+    hw/i2c/pm_smbus.c \
+    hw/i2c/smbus_ich9.c \
+    hw/i386/acpi-build.c \
+    hw/i386/bios-linker-loader.c \
+    hw/i386/intel_iommu.c \
+    hw/i386/kvmvapic.c \
+    hw/i386/multiboot.c \
+    hw/i386/pc.c \
+    hw/i386/pc_piix.c \
+    hw/i386/pc_q35.c \
+    hw/i386/pc_sysfw.c \
+    hw/i386/smbios.c \
+    hw/ide/isa.c \
+    hw/ide/piix.c \
+    hw/input/pckbd.c \
+    hw/input/vmmouse.c \
+    hw/intc/apic.c \
+    hw/intc/apic_common.c \
+    hw/intc/i8259.c \
+    hw/intc/i8259_common.c \
+    hw/intc/ioapic.c \
+    hw/intc/ioapic_common.c \
+    hw/isa/apm.c \
+    hw/isa/lpc_ich9.c \
+    hw/mem/pc-dimm.c \
+    hw/misc/applesmc.c \
+    hw/misc/debugexit.c \
+    hw/misc/pc-testdev.c \
+    hw/misc/pvpanic.c \
+    hw/misc/sga.c \
+    hw/misc/vmport.c \
+    hw/net/ne2000-isa.c \
+    hw/pci-host/piix.c \
+    hw/pci-host/q35.c \
+    hw/pci/pci-hotplug-old.c \
+    hw/timer/hpet.c \
+    hw/timer/i8254.c \
+    hw/timer/i8254_common.c \
+    hw/timer/mc146818rtc.c \
+    hw/tpm/tpm_tis.c \
+    hw/watchdog/wdt_ib700.c \
+    target-i386/arch_dump.c \
+    target-i386/arch_memory_mapping.c \
+    target-i386/cc_helper.c \
+    target-i386/cpu.c \
+    target-i386/excp_helper.c \
+    target-i386/fpu_helper.c \
+    target-i386/gdbstub.c \
+    target-i386/helper.c \
+    target-i386/int_helper.c \
+    target-i386/machine.c \
+    target-i386/mem_helper.c \
+    target-i386/misc_helper.c \
+    target-i386/seg_helper.c \
+    target-i386/smm_helper.c \
+    target-i386/svm_helper.c \
+    target-i386/translate.c \
+
+QEMU2_TARGET_aarch64_SOURCES_darwin-x86_64 := \
+
+QEMU2_TARGET_aarch64_SOURCES_linux-x86_64 := \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+
+QEMU2_TARGET_aarch64_SOURCES_windows-x86 := \
+
+QEMU2_TARGET_aarch64_SOURCES_windows-x86_64 := \
+
+QEMU2_TARGET_arm_SOURCES_darwin-x86_64 := \
+
+QEMU2_TARGET_arm_SOURCES_linux-x86_64 := \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+
+QEMU2_TARGET_arm_SOURCES_windows-x86 := \
+
+QEMU2_TARGET_arm_SOURCES_windows-x86_64 := \
+
+QEMU2_TARGET_i386_SOURCES_darwin-x86_64 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-darwin.c \
+    target-i386/hax-slot.c \
+    target-i386/kvm-stub.c \
+
+QEMU2_TARGET_i386_SOURCES_linux-x86_64 := \
+    hax-stub.c \
+    hw/i386/kvm/apic.c \
+    hw/i386/kvm/clock.c \
+    hw/i386/kvm/i8254.c \
+    hw/i386/kvm/i8259.c \
+    hw/i386/kvm/ioapic.c \
+    hw/i386/kvm/pci-assign.c \
+    hw/misc/ivshmem.c \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+    kvm-all.c \
+    target-i386/kvm.c \
+
+QEMU2_TARGET_i386_SOURCES_windows-x86 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-slot.c \
+    target-i386/hax-windows.c \
+    target-i386/kvm-stub.c \
+
+QEMU2_TARGET_i386_SOURCES_windows-x86_64 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-slot.c \
+    target-i386/hax-windows.c \
+    target-i386/kvm-stub.c \
+
+QEMU2_TARGET_mips64el_SOURCES_darwin-x86_64 := \
+
+QEMU2_TARGET_mips64el_SOURCES_linux-x86_64 := \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+
+QEMU2_TARGET_mips64el_SOURCES_windows-x86 := \
+
+QEMU2_TARGET_mips64el_SOURCES_windows-x86_64 := \
+
+QEMU2_TARGET_mipsel_SOURCES_darwin-x86_64 := \
+
+QEMU2_TARGET_mipsel_SOURCES_linux-x86_64 := \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+
+QEMU2_TARGET_mipsel_SOURCES_windows-x86 := \
+
+QEMU2_TARGET_mipsel_SOURCES_windows-x86_64 := \
+
+QEMU2_TARGET_x86_64_SOURCES_darwin-x86_64 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-darwin.c \
+    target-i386/hax-slot.c \
+    target-i386/kvm-stub.c \
+
+QEMU2_TARGET_x86_64_SOURCES_linux-x86_64 := \
+    hax-stub.c \
+    hw/i386/kvm/apic.c \
+    hw/i386/kvm/clock.c \
+    hw/i386/kvm/i8254.c \
+    hw/i386/kvm/i8259.c \
+    hw/i386/kvm/ioapic.c \
+    hw/i386/kvm/pci-assign.c \
+    hw/misc/ivshmem.c \
+    hw/misc/vfio.c \
+    hw/scsi/vhost-scsi.c \
+    hw/virtio/vhost-backend.c \
+    hw/virtio/vhost-user.c \
+    hw/virtio/vhost.c \
+    kvm-all.c \
+    target-i386/kvm.c \
+
+QEMU2_TARGET_x86_64_SOURCES_windows-x86 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-slot.c \
+    target-i386/hax-windows.c \
+    target-i386/kvm-stub.c \
+
+QEMU2_TARGET_x86_64_SOURCES_windows-x86_64 := \
+    kvm-stub.c \
+    target-i386/hax-all.c \
+    target-i386/hax-slot.c \
+    target-i386/hax-windows.c \
+    target-i386/kvm-stub.c \
+
diff --git a/android-qemu2-glue/build/Makefile.qemu2-target.mk b/android-qemu2-glue/build/Makefile.qemu2-target.mk
new file mode 100644
index 0000000..a09a9aa
--- /dev/null
+++ b/android-qemu2-glue/build/Makefile.qemu2-target.mk
@@ -0,0 +1,127 @@
+# Rules to build the final target-specific QEMU2 binaries from sources.
+
+# The QEMU-specific target name for a given emulator CPU architecture.
+QEMU2_TARGET_CPU_x86 := i386
+QEMU2_TARGET_CPU_x86_64 := x86_64
+QEMU2_TARGET_CPU_mips := mipsel
+QEMU2_TARGET_CPU_mips64 := mips64el
+QEMU2_TARGET_CPU_arm := arm
+QEMU2_TARGET_CPU_arm64 := aarch64
+
+# The engine will use the sources from target-<name> to emulate a given
+# emulator CPU architecture.
+QEMU2_TARGET_TARGET_x86 := i386
+QEMU2_TARGET_TARGET_x86_64 := i386
+QEMU2_TARGET_TARGET_mips := mips
+QEMU2_TARGET_TARGET_mips64 := mips
+QEMU2_TARGET_TARGET_arm := arm
+QEMU2_TARGET_TARGET_arm64 := arm
+
+# As a special case, the 32-bit ARM binary is named qemu-system-armel to match
+QEMU2_TARGET_CPU := $(QEMU2_TARGET_CPU_$(QEMU2_TARGET))
+QEMU2_TARGET_TARGET := $(QEMU2_TARGET_TARGET_$(QEMU2_TARGET))
+
+# upstream QEMU, even though the upstream configure script now uses the 'arm'
+# target name (and stores the build files under arm-softmmu instead of
+# armel-softmmu. qemu-system-armel is also  what the top-level 'emulator'
+# launcher expects.
+QEMU2_TARGET_SYSTEM := $(QEMU2_TARGET_CPU)
+ifeq (arm,$(QEMU2_TARGET))
+    QEMU2_TARGET_SYSTEM := armel
+endif
+
+# If $(QEMU2_TARGET) is $1, then return $2, or the empty string otherwise.
+qemu2-if-target = $(if $(filter $1,$(QEMU2_TARGET)),$2,$3)
+
+# If $(QEMU2_TARGET_CPU) is $1, then return $2, or the empty string otherwise.
+qemu2-if-target-arch = $(if $(filter $1,$(QEMU2_TARGET_CPU)),$2)
+
+$(call start-emulator-program,qemu-system-$(QEMU2_TARGET_SYSTEM))
+
+LOCAL_CFLAGS += \
+    $(QEMU2_CFLAGS) \
+    $(EMULATOR_LIBUI_CFLAGS)
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_INCLUDES) \
+    $(QEMU2_DEPS_TOP_DIR)/include \
+    $(call qemu2-if-linux,$(LOCAL_PATH)/linux-headers) \
+    $(LOCAL_PATH)/android-qemu2-glue/config/target-$(QEMU2_TARGET) \
+    $(LOCAL_PATH)/target-$(QEMU2_TARGET_TARGET) \
+    $(LOCAL_PATH)/tcg \
+    $(LOCAL_PATH)/tcg/i386 \
+    $(LOCAL_PATH)/target-$(QEMU2_TARGET_TARGET) \
+    $(ANDROID_EMU_INCLUDES) \
+    $(LIBCURL_INCLUDES) \
+    $(EMULATOR_LIBUI_INCLUDES) \
+
+LOCAL_CFLAGS += -DNEED_CPU_H
+
+LOCAL_SRC_FILES += \
+    android-qemu2-glue/main.cpp \
+    $(QEMU2_TARGET_SOURCES) \
+    $(QEMU2_TARGET_$(QEMU2_TARGET_CPU)_SOURCES) \
+    $(QEMU2_TARGET_$(QEMU2_TARGET_CPU)_SOURCES_$(BUILD_TARGET_TAG))
+
+LOCAL_SRC_FILES += \
+    hw/audio/goldfish_audio.c \
+    hw/char/goldfish_tty.c \
+    hw/display/framebuffer.c \
+    hw/display/goldfish_fb.c \
+    hw/input/goldfish_events.c \
+    hw/intc/goldfish_pic.c \
+    hw/misc/android_pipe.c \
+    hw/misc/goldfish_battery.c \
+    hw/timer/goldfish_timer.c \
+    $(call qemu2-if-target,arm arm64,\
+        hw/arm/ranchu.c) \
+    $(call qemu2-if-target,mips mips64,\
+        hw/mips/mips_ranchu.c) \
+
+ifeq (arm64,$(QEMU2_TARGET))
+LOCAL_GENERATED_SOURCES += $(QEMU2_AUTO_GENERATED_DIR)/gdbstub-xml-arm64.c
+else ifeq (arm,$(QEMU2_TARGET))
+LOCAL_GENERATED_SOURCES += $(QEMU2_AUTO_GENERATED_DIR)/gdbstub-xml-arm.c
+else
+LOCAL_SRC_FILES += stubs/gdbstub.c
+endif
+
+LOCAL_SRC_FILES += \
+    $(call qemu2-if-target,arm arm64 mips mips64,\
+        stubs/dump.c \
+        stubs/pci-drive-hot-add.c \
+        stubs/qmp_pc_dimm_device_list.c \
+        ) \
+    $(call qemu2-if-target,mips mips64, \
+        stubs/arch-query-cpu-def.c)
+
+LOCAL_PREBUILTS_OBJ_FILES += \
+    $(call qemu2-if-windows,$(QEMU2_AUTO_GENERATED_DIR)/version.o)
+
+LOCAL_WHOLE_STATIC_LIBRARIES += \
+    libqemu2_common \
+    libqemu2_glue \
+    $(call qemu2-if-target,arm arm64, libqemu2_common_aarch64) \
+
+LOCAL_STATIC_LIBRARIES += \
+    emulator-libui \
+    $(EMULATOR_LIBUI_STATIC_LIBRARIES) \
+    $(ANDROID_EMU_STATIC_LIBRARIES) \
+
+LOCAL_LDFLAGS += \
+    $(QEMU2_DEPS_LDFLAGS) \
+    $(EMULATOR_LIBUI_LDFLAGS)
+
+LOCAL_LDLIBS += \
+    $(QEMU2_GLIB_LDLIBS) \
+    $(QEMU2_PIXMAN_LDLIBS) \
+    $(CXX_STD_LIB) \
+    -lfdt \
+    $(call qemu2-if-windows, -lvfw32) \
+    $(call qemu2-if-linux, -lpulse) \
+    $(ANDROID_EMU_LDLIBS) \
+    $(EMULATOR_LIBUI_LDLIBS) \
+
+LOCAL_INSTALL_DIR := qemu/$(BUILD_TARGET_TAG)
+
+$(call end-emulator-program)
diff --git a/android-qemu2-glue/build/Makefile.qemu2.mk b/android-qemu2-glue/build/Makefile.qemu2.mk
new file mode 100644
index 0000000..481f665
--- /dev/null
+++ b/android-qemu2-glue/build/Makefile.qemu2.mk
@@ -0,0 +1,244 @@
+# Rules to build QEMU2 for the Android emulator from sources.
+# This file is included from external/qemu/Makefile or one of its sub-Makefiles.
+
+# NOTE: Previous versions of the build system defined HOST_OS and HOST_ARCH
+# instead of BUILD_TARGET_OS and BUILD_TARGET_ARCH, so take care of these to
+# ensure this continues to build with both versions.
+#
+# TODO: Remove this once the external/qemu build script changes are
+#       all submitted.
+BUILD_TARGET_OS ?= $(HOST_OS)
+BUILD_TARGET_ARCH ?= $(HOST_ARCH)
+BUILD_TARGET_TAG ?= $(BUILD_TARGET_OS)-$(BUILD_TARGET_ARCH)
+BUILD_TARGET_BITS ?= $(HOST_BITS)
+
+# Same for OBJS_DIR -> BUILD_OBJS_DIR
+BUILD_OBJS_DIR ?= $(OBJS_DIR)
+
+QEMU2_OLD_LOCAL_PATH := $(LOCAL_PATH)
+
+# Assume this is under android-qemu2-glue/build/ so get up two directories
+# to find the top-level one.
+LOCAL_PATH := $(QEMU2_TOP_DIR)
+
+# If $(BUILD_TARGET_OS) is $1, then return $2, otherwise $3
+qemu2-if-os = $(if $(filter $1,$(BUILD_TARGET_OS)),$2,$3)
+
+# If $(BUILD_TARGET_ARCH) is $1, then return $2, otherwise $3
+qemu2-if-build-target-arch = $(if $(filter $1,$(BUILD_TARGET_ARCH)),$2,$3)
+
+# If $(BUILD_TARGET_OS) is not $1, then return $2, otherwise $3
+qemu2-ifnot-os = $(if $(filter-out $1,$(BUILD_TARGET_OS)),$2,$3)
+
+# If $(BUILD_TARGET_OS) is windows, return $1, otherwise $2
+qemu2-if-windows = $(call qemu2-if-os,windows,$1,$2)
+
+# If $(BUILD_TARGET_OS) is not windows, return $1, otherwise $2
+qemu2-if-posix = $(call qemu2-ifnot-os,windows,$1,$2)
+
+qemu2-if-darwin = $(call qemu2-if-os,darwin,$1,$2)
+qemu2-if-linux = $(call qemu2-if-os,linux,$1,$2)
+
+QEMU2_AUTO_GENERATED_DIR := $(BUILD_OBJS_DIR)/build/qemu2-qapi-auto-generated
+
+QEMU2_DEPS_TOP_DIR := $(QEMU2_DEPS_PREBUILTS_DIR)/$(BUILD_TARGET_TAG)
+QEMU2_DEPS_LDFLAGS := -L$(QEMU2_DEPS_TOP_DIR)/lib
+
+QEMU2_GLIB_INCLUDES := $(QEMU2_DEPS_TOP_DIR)/include/glib-2.0 \
+                       $(QEMU2_DEPS_TOP_DIR)/lib/glib-2.0/include
+
+QEMU2_GLIB_LDLIBS := \
+    -lglib-2.0 \
+    $(call qemu2-if-darwin, -liconv -lintl) \
+    $(call qemu2-if-linux, -lpthread -lrt) \
+    $(call qemu2-if-windows, -lole32) \
+
+QEMU2_PIXMAN_INCLUDES := $(QEMU2_DEPS_TOP_DIR)/include/pixman-1
+QEMU2_PIXMAN_LDLIBS := -lpixman-1
+
+# Ensure config-host.h can be found properly.
+QEMU2_INCLUDES := $(LOCAL_PATH)/android-qemu2-glue/config/$(BUILD_TARGET_TAG)
+
+# Ensure QEMU2 headers are found.
+QEMU2_INCLUDES += \
+    $(LOCAL_PATH) \
+    $(LOCAL_PATH)/include \
+    $(QEMU2_AUTO_GENERATED_DIR) \
+    $(ANDROID_EMU_INCLUDES) \
+
+QEMU2_INCLUDES += $(QEMU2_GLIB_INCLUDES) $(QEMU2_PIXMAN_INCLUDES)
+
+QEMU2_CFLAGS := \
+    $(EMULATOR_COMMON_CFLAGS) \
+    $(call qemu2-if-windows,\
+        -DWIN32_LEAN_AND_MEAN \
+        -D__USE_MINGW_ANSI_STDIO=1 \
+        -mms-bitfields) \
+    -fno-strict-aliasing \
+    -fno-common \
+    $(LIBCURL_CFLAGS) \
+    -D_GNU_SOURCE \
+    -D_FILE_OFFSET_BITS=64 \
+    -DCONFIG_ANDROID \
+    $(call qemu2-if-darwin, -Wno-initializer-overrides) \
+
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-glue.mk
+
+#include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-qt.mk
+
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-sources.mk
+
+# Custom fixes.
+QEMU2_COMMON_SOURCES += \
+    stubs/kvm.c
+
+# A static library containing target-independent code
+$(call start-emulator-library,libqemu2_common)
+
+LOCAL_CFLAGS += $(QEMU2_CFLAGS)
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_INCLUDES) \
+    $(LOCAL_PATH)/slirp \
+    $(LOCAL_PATH)/tcg \
+    $(ZLIB_INCLUDES) \
+
+LOCAL_SRC_FILES += \
+    $(QEMU2_COMMON_SOURCES) \
+    $(QEMU2_COMMON_SOURCES_$(BUILD_TARGET_TAG))
+
+LOCAL_GENERATED_SOURCES += \
+    $(QEMU2_AUTO_GENERATED_DIR)/qapi-event.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/qapi-types.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/qapi-visit.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/qmp-marshal.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/trace/generated-events.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/trace/generated-tracers.c \
+
+# Stuff from libqemuutil, order follows util/Makefile.objs
+LOCAL_SRC_FILES += \
+    qapi/qapi-visit-core.c \
+    qapi/qapi-dealloc-visitor.c \
+    qapi/qmp-input-visitor.c \
+    qapi/qmp-output-visitor.c \
+    qapi/qmp-registry.c \
+    qapi/qmp-dispatch.c \
+    qapi/string-input-visitor.c \
+    qapi/string-output-visitor.c \
+    qapi/opts-visitor.c \
+    qapi/qmp-event.c \
+    qapi/qapi-util.c \
+    qobject/qint.c \
+    qobject/qstring.c \
+    qobject/qdict.c \
+    qobject/qlist.c \
+    qobject/qfloat.c \
+    qobject/qbool.c \
+    qobject/qjson.c \
+    qobject/json-lexer.c \
+    qobject/json-streamer.c \
+    qobject/json-parser.c \
+    qobject/qerror.c \
+    trace/control.c \
+    trace/qmp.c \
+    util/osdep.c \
+    util/cutils.c \
+    util/unicode.c \
+    util/qemu-timer-common.c \
+    $(call qemu2-if-windows, \
+        util/oslib-win32.c \
+        util/qemu-thread-win32.c \
+        util/event_notifier-win32.c \
+        ) \
+    $(call qemu2-if-posix, \
+        util/oslib-posix.c \
+        util/qemu-thread-posix.c \
+        util/event_notifier-posix.c \
+        util/qemu-openpty.c \
+        ) \
+    util/envlist.c \
+    util/path.c \
+    util/module.c \
+    $(call qemu2-if-build-target-arch,x86, util/host-utils.c) \
+    util/bitmap.c \
+    util/bitops.c \
+    util/hbitmap.c \
+    util/fifo8.c \
+    util/acl.c \
+    util/error.c \
+    util/qemu-error.c \
+    $(call qemu2-if-posix, \
+        util/compatfd.c \
+        ) \
+    util/id.c \
+    util/iov.c \
+    util/aes.c \
+    util/qemu-config.c \
+    util/qemu-sockets.c \
+    util/uri.c \
+    util/notify.c \
+    util/qemu-option.c \
+    util/qemu-progress.c \
+    util/hexdump.c \
+    util/crc32c.c \
+    util/throttle.c \
+    util/getauxval.c \
+    util/readline.c \
+    util/rfifolock.c \
+    $(call qemu2-if-windows, \
+        util/shared-library-win32.c \
+        ) \
+    $(call qemu2-if-posix, \
+        util/shared-library-posix.c \
+        ) \
+
+$(call gen-hw-config-defs)
+QEMU2_INCLUDES += $(QEMU_HW_CONFIG_DEFS_INCLUDES)
+
+LOCAL_SRC_FILES += \
+    $(QEMU2_GLUE_SOURCES)
+
+$(call end-emulator-library)
+
+# Special case, the following sources are only used by the arm64
+# target but cannot be part of libqemu2_aarch64 because they need
+# to be compiled without NEED_CPU_H
+$(call start-emulator-library,libqemu2_common_aarch64)
+
+LOCAL_CPP_EXTENSION := .cc
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_INCLUDES) \
+    $(LOCAL_PATH)/target-arm \
+    $(LOCAL_PATH)/disas/libvixl
+
+LOCAL_CFLAGS += $(QEMU2_CFLAGS)
+
+LOCAL_SRC_FILES += \
+    disas/arm-a64.cc \
+    disas/libvixl/a64/decoder-a64.cc \
+    disas/libvixl/a64/disasm-a64.cc \
+    disas/libvixl/a64/instructions-a64.cc \
+    disas/libvixl/utils.cc \
+
+$(call end-emulator-library)
+
+QEMU2_TARGET := x86
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+QEMU2_TARGET := x86_64
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+QEMU2_TARGET := arm
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+QEMU2_TARGET := arm64
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+QEMU2_TARGET := mips
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+QEMU2_TARGET := mips64
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
+
+LOCAL_PATH := $(QEMU2_OLD_LOCAL_PATH)
diff --git a/android-qemu2-glue/build/configure.sh b/android-qemu2-glue/build/configure.sh
new file mode 100644
index 0000000..c258d55
--- /dev/null
+++ b/android-qemu2-glue/build/configure.sh
@@ -0,0 +1,142 @@
+# This script is sourced from the top-level Android emulator
+# configuration script, and relies on the following macro
+# definitions:
+#
+#  QEMU2_TOP_DIR: top-level QEMU2 source directory.
+#  OUT_DIR: top-level build output directory.
+
+QEMU2_AUTOGENERATED_DIR=$OUT_DIR/build/qemu2-qapi-auto-generated
+
+probe_prebuilts_dir "QEMU2 Dependencies" \
+    QEMU2_DEPS_PREBUILTS_DIR \
+    qemu-android-deps
+
+echo "QEMU2_DEPS_PREBUILTS_DIR := $QEMU2_DEPS_PREBUILTS_DIR" >> $config_mk
+
+python $QEMU2_TOP_DIR/scripts/qapi-types.py \
+    --builtins \
+    -i $QEMU2_TOP_DIR/qapi-schema.json \
+    -o $QEMU2_AUTOGENERATED_DIR
+
+python $QEMU2_TOP_DIR/scripts/qapi-visit.py \
+    --builtins \
+    -i $QEMU2_TOP_DIR/qapi-schema.json \
+    -o $QEMU2_AUTOGENERATED_DIR
+
+python $QEMU2_TOP_DIR/scripts/qapi-event.py \
+    --builtins \
+    -i $QEMU2_TOP_DIR/qapi-schema.json \
+    -o $QEMU2_AUTOGENERATED_DIR
+
+python $QEMU2_TOP_DIR/scripts/qapi-commands.py \
+    --middle \
+    -i $QEMU2_TOP_DIR/qapi-schema.json \
+    -o $QEMU2_AUTOGENERATED_DIR
+
+mkdir -p "$QEMU2_AUTOGENERATED_DIR"/trace
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=h \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-tracers.h
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=c \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-tracers.c
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=events-h \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-events.h
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=events-c \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-events.c
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=tcg-helper-h \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-helpers.h
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=tcg-helper-wrapper-h \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-helpers-wrappers.h
+
+python $QEMU2_TOP_DIR/scripts/tracetool.py \
+    --backends=nop \
+    --format=tcg-h \
+    --target-type system \
+    < $QEMU2_TOP_DIR/trace-events \
+    > $QEMU2_AUTOGENERATED_DIR/trace/generated-tcg-tracers.h
+
+bash $QEMU2_TOP_DIR/scripts/hxtool -h \
+    < $QEMU2_TOP_DIR/qemu-options.hx \
+    > $QEMU2_AUTOGENERATED_DIR/qemu-options.def
+
+bash $QEMU2_TOP_DIR/scripts/hxtool -h \
+    < $QEMU2_TOP_DIR/hmp-commands.hx \
+    > $QEMU2_AUTOGENERATED_DIR/hmp-commands.h
+
+bash $QEMU2_TOP_DIR/scripts/hxtool -h \
+    < $QEMU2_TOP_DIR/qmp-commands.hx \
+    > $QEMU2_AUTOGENERATED_DIR/qmp-commands-old.h
+
+bash $QEMU2_TOP_DIR/scripts/hxtool -h \
+    < $QEMU2_TOP_DIR/qemu-img-cmds.hx \
+    > $QEMU2_AUTOGENERATED_DIR/qemu-img-cmds.h
+
+HEX_FILES=$(find $QEMU2_TOP_DIR/hw/i386/ -name "*.hex.generated" | \
+    sed -e 's|'$QEMU2_TOP_DIR/'||g')
+mkdir -p $QEMU2_AUTOGENERATED_DIR/hw/i386
+for HEX_FILES in $HEX_FILES; do
+    cp "$QEMU2_TOP_DIR/$HEX_FILES" "$QEMU2_AUTOGENERATED_DIR/${HEX_FILES%.generated}"
+done
+
+rm -f $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm64.c
+bash $QEMU2_TOP_DIR/scripts/feature_to_c.sh \
+    $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm64.c \
+    $QEMU2_TOP_DIR/gdb-xml/aarch64-core.xml \
+    $QEMU2_TOP_DIR/gdb-xml/aarch64-fpu.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-core.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-vfp.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-vfp3.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-neon.xml
+
+rm -f $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm.c
+bash $QEMU2_TOP_DIR/scripts/feature_to_c.sh \
+    $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm.c \
+    $QEMU2_TOP_DIR/gdb-xml/arm-core.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-vfp.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-vfp3.xml \
+    $QEMU2_TOP_DIR/gdb-xml/arm-neon.xml
+
+if [ "$OPT_MINGW" ]; then
+    $OUT_DIR/objs/build/toolchain/x86_64-mingw32-windres \
+        -o $QEMU2_AUTOGENERATED_DIR/version.o \
+        $QEMU2_TOP_DIR/version.rc
+fi
+
+# Work-around for a QEMU2 bug:
+# $QEMU2/linux-headers/linux/kvm.h includes <asm/kvm.h>
+# but $QEMU2/linux-headers/asm/ doesn't exist. It is supposed
+# to be a symlink to $QEMU2/linux-headers/asm-x86/
+#
+# The end result is that the <asm/kvm.h> from the host system
+# or toolchain sysroot is being included, which ends up in a
+# conflict. Work around it by creating a symlink here
+ln -sf $QEMU2_TOP_DIR/linux-headers/asm-x86 $QEMU2_AUTOGENERATED_DIR/asm
diff --git a/android-qemu2-glue/config/darwin-x86_64/config-host.h b/android-qemu2-glue/config/darwin-x86_64/config-host.h
new file mode 100644
index 0000000..72dc9eb
--- /dev/null
+++ b/android-qemu2-glue/config/darwin-x86_64/config-host.h
@@ -0,0 +1,44 @@
+/* Automatically generated by create_config - do not modify */
+#define CONFIG_QEMU_CONFDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/etc/qemu"
+#define CONFIG_QEMU_DATADIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/qemu"
+#define CONFIG_QEMU_DOCDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/doc/qemu"
+#define CONFIG_QEMU_MODDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/lib/qemu"
+#define CONFIG_QEMU_LOCALSTATEDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/var"
+#define CONFIG_QEMU_HELPERDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/locale"
+#define HOST_X86_64 1
+#define CONFIG_POSIX 1
+#define CONFIG_DARWIN 1
+#define CONFIG_SLIRP 1
+#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
+#define CONFIG_AUDIO_DRIVERS \
+    &coreaudio_audio_driver,\
+
+#define CONFIG_COREAUDIO 1
+#define CONFIG_BDRV_RW_WHITELIST\
+    NULL
+#define CONFIG_BDRV_RO_WHITELIST\
+    NULL
+#define CONFIG_VNC 1
+#define CONFIG_FNMATCH 1
+#define CONFIG_UUID 1
+#define QEMU_VERSION "2.2.0"
+#define QEMU_PKGVERSION ""
+#define CONFIG_SDL 1
+#define CONFIG_SDLABI 2.0
+#define CONFIG_IOVEC 1
+#define CONFIG_FDT 1
+#define CONFIG_MADVISE 1
+#define CONFIG_POSIX_MADVISE 1
+#define CONFIG_BSD 1
+#define CONFIG_ZERO_MALLOC 1
+#define CONFIG_QOM_CAST_DEBUG 1
+#define CONFIG_COROUTINE_BACKEND sigaltstack
+#define CONFIG_COROUTINE_POOL 1
+#define CONFIG_CPUID_H 1
+#define CONFIG_INT128 1
+#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_FILE trace
+#define HOST_DSOSUF ".so"
+#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/linux-x86/config-host.h b/android-qemu2-glue/config/linux-x86/config-host.h
new file mode 100644
index 0000000..5de0e8b
--- /dev/null
+++ b/android-qemu2-glue/config/linux-x86/config-host.h
@@ -0,0 +1,72 @@
+/* Automatically generated by create_config - do not modify */
+#define CONFIG_QEMU_CONFDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/etc/qemu"
+#define CONFIG_QEMU_DATADIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/share/qemu"
+#define CONFIG_QEMU_DOCDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/share/doc/qemu"
+#define CONFIG_QEMU_MODDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/lib/qemu"
+#define CONFIG_QEMU_LOCALSTATEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/var"
+#define CONFIG_QEMU_HELPERDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86/share/locale"
+#define HOST_I386 1
+#define CONFIG_POSIX 1
+#define CONFIG_LINUX 1
+#define CONFIG_SLIRP 1
+#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
+#define CONFIG_AUDIO_DRIVERS \
+    &pa_audio_driver,\
+
+#define CONFIG_PA 1
+#define CONFIG_AUDIO_PT_INT 1
+#define CONFIG_BDRV_RW_WHITELIST\
+    NULL
+#define CONFIG_BDRV_RO_WHITELIST\
+    NULL
+#define CONFIG_VNC 1
+#define CONFIG_FNMATCH 1
+#define QEMU_VERSION "2.2.0"
+#define QEMU_PKGVERSION ""
+#define CONFIG_SDL 1
+#define CONFIG_SDLABI 2.0
+#define CONFIG_UTIMENSAT 1
+#define CONFIG_PIPE2 1
+#define CONFIG_ACCEPT4 1
+#define CONFIG_SPLICE 1
+#define CONFIG_EVENTFD 1
+#define CONFIG_FALLOCATE 1
+#define CONFIG_POSIX_FALLOCATE 1
+#define CONFIG_SYNC_FILE_RANGE 1
+#define CONFIG_FIEMAP 1
+#define CONFIG_DUP3 1
+#define CONFIG_PPOLL 1
+#define CONFIG_PRCTL_PR_SET_TIMERSLACK 1
+#define CONFIG_EPOLL 1
+#define CONFIG_EPOLL_CREATE1 1
+#define CONFIG_EPOLL_PWAIT 1
+#define CONFIG_SENDFILE 1
+#define CONFIG_TIMERFD 1
+#define CONFIG_INOTIFY 1
+#define CONFIG_INOTIFY1 1
+#define CONFIG_BYTESWAP_H 1
+#define CONFIG_VHOST_SCSI 1
+#define CONFIG_IOVEC 1
+#define CONFIG_PREADV 1
+#define CONFIG_FDT 1
+#define CONFIG_SIGNALFD 1
+#define CONFIG_FDATASYNC 1
+#define CONFIG_MADVISE 1
+#define CONFIG_POSIX_MADVISE 1
+#define CONFIG_SIGEV_THREAD_ID 1
+#define CONFIG_GLX 1
+#define CONFIG_ZERO_MALLOC 1
+#define CONFIG_QOM_CAST_DEBUG 1
+#define CONFIG_COROUTINE_BACKEND ucontext
+#define CONFIG_COROUTINE_POOL 1
+#define CONFIG_LINUX_MAGIC_H 1
+#define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
+#define CONFIG_HAS_ENVIRON 1
+#define CONFIG_CPUID_H 1
+#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TPM_PASSTHROUGH 1
+#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_FILE trace
+#define HOST_DSOSUF ".so"
+#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/linux-x86_64/config-host.h b/android-qemu2-glue/config/linux-x86_64/config-host.h
new file mode 100644
index 0000000..739c90a
--- /dev/null
+++ b/android-qemu2-glue/config/linux-x86_64/config-host.h
@@ -0,0 +1,73 @@
+/* Automatically generated by create_config - do not modify */
+#define CONFIG_QEMU_CONFDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/etc/qemu"
+#define CONFIG_QEMU_DATADIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/share/qemu"
+#define CONFIG_QEMU_DOCDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/share/doc/qemu"
+#define CONFIG_QEMU_MODDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/lib/qemu"
+#define CONFIG_QEMU_LOCALSTATEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/var"
+#define CONFIG_QEMU_HELPERDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/linux-x86_64/share/locale"
+#define HOST_X86_64 1
+#define CONFIG_POSIX 1
+#define CONFIG_LINUX 1
+#define CONFIG_SLIRP 1
+#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
+#define CONFIG_AUDIO_DRIVERS \
+    &pa_audio_driver,\
+
+#define CONFIG_PA 1
+#define CONFIG_AUDIO_PT_INT 1
+#define CONFIG_BDRV_RW_WHITELIST\
+    NULL
+#define CONFIG_BDRV_RO_WHITELIST\
+    NULL
+#define CONFIG_VNC 1
+#define CONFIG_FNMATCH 1
+#define QEMU_VERSION "2.2.0"
+#define QEMU_PKGVERSION ""
+#define CONFIG_SDL 1
+#define CONFIG_SDLABI 2.0
+#define CONFIG_UTIMENSAT 1
+#define CONFIG_PIPE2 1
+#define CONFIG_ACCEPT4 1
+#define CONFIG_SPLICE 1
+#define CONFIG_EVENTFD 1
+#define CONFIG_FALLOCATE 1
+#define CONFIG_POSIX_FALLOCATE 1
+#define CONFIG_SYNC_FILE_RANGE 1
+#define CONFIG_FIEMAP 1
+#define CONFIG_DUP3 1
+#define CONFIG_PPOLL 1
+#define CONFIG_PRCTL_PR_SET_TIMERSLACK 1
+#define CONFIG_EPOLL 1
+#define CONFIG_EPOLL_CREATE1 1
+#define CONFIG_EPOLL_PWAIT 1
+#define CONFIG_SENDFILE 1
+#define CONFIG_TIMERFD 1
+#define CONFIG_INOTIFY 1
+#define CONFIG_INOTIFY1 1
+#define CONFIG_BYTESWAP_H 1
+#define CONFIG_VHOST_SCSI 1
+#define CONFIG_IOVEC 1
+#define CONFIG_PREADV 1
+#define CONFIG_FDT 1
+#define CONFIG_SIGNALFD 1
+#define CONFIG_FDATASYNC 1
+#define CONFIG_MADVISE 1
+#define CONFIG_POSIX_MADVISE 1
+#define CONFIG_SIGEV_THREAD_ID 1
+#define CONFIG_GLX 1
+#define CONFIG_ZERO_MALLOC 1
+#define CONFIG_QOM_CAST_DEBUG 1
+#define CONFIG_COROUTINE_BACKEND ucontext
+#define CONFIG_COROUTINE_POOL 1
+#define CONFIG_LINUX_MAGIC_H 1
+#define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
+#define CONFIG_HAS_ENVIRON 1
+#define CONFIG_CPUID_H 1
+#define CONFIG_INT128 1
+#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TPM_PASSTHROUGH 1
+#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_FILE trace
+#define HOST_DSOSUF ".so"
+#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/target-arm/config-target.h b/android-qemu2-glue/config/target-arm/config-target.h
new file mode 100644
index 0000000..b3e53a9
--- /dev/null
+++ b/android-qemu2-glue/config/target-arm/config-target.h
@@ -0,0 +1,8 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_ARM 1
+#define TARGET_NAME "arm"
+#define TARGET_ARM 1
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_ARM_DIS 1
+#define CONFIG_ARM_A64_DIS 1
diff --git a/android-qemu2-glue/config/target-arm64/config-target.h b/android-qemu2-glue/config/target-arm64/config-target.h
new file mode 100644
index 0000000..681ee5a
--- /dev/null
+++ b/android-qemu2-glue/config/target-arm64/config-target.h
@@ -0,0 +1,8 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_AARCH64 1
+#define TARGET_NAME "aarch64"
+#define TARGET_ARM 1
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_ARM_DIS 1
+#define CONFIG_ARM_A64_DIS 1
diff --git a/android-qemu2-glue/config/target-mips/config-target.h b/android-qemu2-glue/config/target-mips/config-target.h
new file mode 100644
index 0000000..f7c37f0
--- /dev/null
+++ b/android-qemu2-glue/config/target-mips/config-target.h
@@ -0,0 +1,7 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_ABI_MIPSO32 1
+#define TARGET_MIPS 1
+#define TARGET_NAME "mipsel"
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_MIPS_DIS 1
diff --git a/android-qemu2-glue/config/target-mips64/config-target.h b/android-qemu2-glue/config/target-mips64/config-target.h
new file mode 100644
index 0000000..4492f5d
--- /dev/null
+++ b/android-qemu2-glue/config/target-mips64/config-target.h
@@ -0,0 +1,8 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_ABI_MIPSN64 1
+#define TARGET_MIPS64 1
+#define TARGET_NAME "mips64el"
+#define TARGET_MIPS 1
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_MIPS_DIS 1
diff --git a/android-qemu2-glue/config/target-x86/config-target.h b/android-qemu2-glue/config/target-x86/config-target.h
new file mode 100644
index 0000000..160b336
--- /dev/null
+++ b/android-qemu2-glue/config/target-x86/config-target.h
@@ -0,0 +1,12 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_I386 1
+#define TARGET_NAME "i386"
+#define TARGET_I386 1
+#ifdef __linux__
+#define CONFIG_KVM 1
+#else
+#define CONFIG_HAX 1
+#endif
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_I386_DIS 1
diff --git a/android-qemu2-glue/config/target-x86_64/config-target.h b/android-qemu2-glue/config/target-x86_64/config-target.h
new file mode 100644
index 0000000..7ddbe93
--- /dev/null
+++ b/android-qemu2-glue/config/target-x86_64/config-target.h
@@ -0,0 +1,12 @@
+/* Automatically generated by create_config - do not modify */
+#define TARGET_X86_64 1
+#define TARGET_NAME "x86_64"
+#define TARGET_I386 1
+#ifdef __linux__
+#define CONFIG_KVM 1
+#else
+#define CONFIG_HAX 1
+#endif
+#define CONFIG_SOFTMMU 1
+#define CONFIG_I386_DIS 1
+#define CONFIG_I386_DIS 1
diff --git a/android-qemu2-glue/config/windows-x86/config-host.h b/android-qemu2-glue/config/windows-x86/config-host.h
new file mode 100644
index 0000000..3bc3a6e
--- /dev/null
+++ b/android-qemu2-glue/config/windows-x86/config-host.h
@@ -0,0 +1,41 @@
+/* Automatically generated by create_config - do not modify */
+#define CONFIG_QEMU_CONFDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86"
+#define CONFIG_QEMU_DATADIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86"
+#define CONFIG_QEMU_DOCDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86"
+#define CONFIG_QEMU_MODDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86/lib"
+#define CONFIG_QEMU_HELPERDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86/locale"
+#define HOST_I386 1
+#define CONFIG_WIN32 1
+#define CONFIG_FILEVERSION 2,2,0,0
+#define CONFIG_PRODUCTVERSION 2,2,0,0
+#define CONFIG_SLIRP 1
+#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
+#define CONFIG_AUDIO_DRIVERS \
+    &winaudio_audio_driver,\
+    &winwave_audio_driver,\
+
+#define CONFIG_WINAUDIO 1
+#define CONFIG_WINWAVE 1
+#define CONFIG_AUDIO_WIN_INT 1
+#define CONFIG_BDRV_RW_WHITELIST\
+    NULL
+#define CONFIG_BDRV_RO_WHITELIST\
+    NULL
+#define CONFIG_VNC 1
+#define QEMU_VERSION "2.2.0"
+#define QEMU_PKGVERSION ""
+#define CONFIG_SDL 1
+#define CONFIG_SDLABI 2.0
+#define CONFIG_FDT 1
+#define CONFIG_ZERO_MALLOC 1
+#define CONFIG_QOM_CAST_DEBUG 1
+#define CONFIG_COROUTINE_BACKEND win32
+#define CONFIG_COROUTINE_POOL 1
+#define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
+#define CONFIG_CPUID_H 1
+#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_FILE trace
+#define HOST_DSOSUF ".dll"
+#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/windows-x86_64/config-host.h b/android-qemu2-glue/config/windows-x86_64/config-host.h
new file mode 100644
index 0000000..a3df876
--- /dev/null
+++ b/android-qemu2-glue/config/windows-x86_64/config-host.h
@@ -0,0 +1,42 @@
+/* Automatically generated by create_config - do not modify */
+#define CONFIG_QEMU_CONFDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64"
+#define CONFIG_QEMU_DATADIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64"
+#define CONFIG_QEMU_DOCDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64"
+#define CONFIG_QEMU_MODDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64/lib"
+#define CONFIG_QEMU_HELPERDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64/locale"
+#define HOST_X86_64 1
+#define CONFIG_WIN32 1
+#define CONFIG_FILEVERSION 2,2,0,0
+#define CONFIG_PRODUCTVERSION 2,2,0,0
+#define CONFIG_SLIRP 1
+#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
+#define CONFIG_AUDIO_DRIVERS \
+    &winaudio_audio_driver,\
+    &winwave_audio_driver,\
+
+#define CONFIG_WINAUDIO 1
+#define CONFIG_WINWAVE 1
+#define CONFIG_AUDIO_WIN_INT 1
+#define CONFIG_BDRV_RW_WHITELIST\
+    NULL
+#define CONFIG_BDRV_RO_WHITELIST\
+    NULL
+#define CONFIG_VNC 1
+#define QEMU_VERSION "2.2.0"
+#define QEMU_PKGVERSION ""
+#define CONFIG_SDL 1
+#define CONFIG_SDLABI 2.0
+#define CONFIG_FDT 1
+#define CONFIG_ZERO_MALLOC 1
+#define CONFIG_QOM_CAST_DEBUG 1
+#define CONFIG_COROUTINE_BACKEND win32
+#define CONFIG_COROUTINE_POOL 1
+#define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
+#define CONFIG_CPUID_H 1
+#define CONFIG_INT128 1
+#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_FILE trace
+#define HOST_DSOSUF ".dll"
+#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/display.cpp b/android-qemu2-glue/display.cpp
new file mode 100644
index 0000000..99a9683
--- /dev/null
+++ b/android-qemu2-glue/display.cpp
@@ -0,0 +1,164 @@
+/* Copyright (C) 2010 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.
+*/
+
+/* Initialization of the Android-specific DisplayState.
+ * Read docs/DISPLAY-STATE.TXT to understand what this
+ * is supposed to do.
+ */
+#include "android-qemu2-glue/display.h"
+
+#include "android/emulator-window.h"
+
+extern "C" {
+    #include "ui/console.h"
+}
+
+namespace {
+
+struct DCLExtra : public DisplayChangeListener {
+    DCLExtra() { memset(this, 0, sizeof(*this)); }
+
+    QFrameBuffer* fb;
+};
+
+}
+
+static DCLExtra* asDcl(DisplayChangeListener* dcl) {
+    return static_cast<DCLExtra*>(dcl);
+}
+
+/*
+
+TECHNICAL NOTE:
+
+DisplayState <--> QFrameBuffer <--> QEmulator/SDL
+
+*/
+
+/* QFrameBuffer producer callbacks */
+
+/* this is called periodically by the GUI timer to check for updates
+ * and poll user events. Use vga_hw_update().
+ */
+static void android_display_producer_check(void* opaque) {
+    /* core: call vga_hw_update(). this will eventually
+     * lead to calls to android_display_update()
+     */
+    (void)opaque;
+    graphic_hw_update(NULL);
+}
+
+static void android_display_producer_invalidate(void* opaque) {
+    (void)opaque;
+    graphic_hw_invalidate(NULL);
+}
+
+static void android_display_producer_detach(void* opaque) {
+    // the framebuffer is being deleted, clean it up in the DCL as well
+    if (const auto dcl = static_cast<DCLExtra*>(opaque)) {
+        dcl->fb = nullptr;
+    }
+}
+
+/* QFrameBuffer client callbacks */
+
+/* this is called from dpy_update() each time a hardware framebuffer
+ * rectangular update was detected. Send this to the QFrameBuffer.
+ */
+static void android_display_update(DisplayChangeListener* dcl,
+                                   int x,
+                                   int y,
+                                   int w,
+                                   int h) {
+    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
+        qframebuffer_update(qfbuff, x, y, w, h);
+    }
+}
+
+static void android_display_switch(DisplayChangeListener* dcl,
+                                   DisplaySurface* new_surface_unused) {
+    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
+        qframebuffer_rotate(qfbuff, 0);
+    }
+}
+
+static void android_display_refresh(DisplayChangeListener* dcl) {
+    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
+        qframebuffer_poll(qfbuff);
+    }
+}
+
+static QemuConsole* find_graphic_console() {
+    // find the first graphic console (Android emulator has only one usually)
+    for (int i = 0;; i++) {
+        QemuConsole* const c = qemu_console_lookup_by_index(i);
+        if (!c) {
+            break;
+        }
+        if (qemu_console_is_graphic(c)) {
+            return c;
+        }
+    }
+
+    return NULL;
+}
+
+static DisplayChangeListenerOps dclOps = {};
+
+bool android_display_init(DisplayState* ds, QFrameBuffer* qf) {
+    QemuConsole* const con = find_graphic_console();
+    if (!con) {
+        return false;
+    }
+
+    const auto dcl = new DCLExtra();
+
+    qframebuffer_set_producer(qf, dcl,
+                              android_display_producer_check,
+                              android_display_producer_invalidate,
+                              android_display_producer_detach);
+
+    /* Replace the display surface with one with the right dimensions */
+    pixman_format_code_t format =
+            qemu_default_pixman_format(qf->bits_per_pixel, true);
+
+    auto surface = qemu_create_displaysurface_from(
+            qf->width, qf->height, format, qf->pitch, (uint8_t*)qf->pixels);
+
+    dpy_gfx_replace_surface(con, surface);
+
+    /* Register a change listener for it */
+    dcl->fb = qf;
+
+    dclOps.dpy_name = "qemu2-glue";
+    dclOps.dpy_refresh = &android_display_refresh;
+    dclOps.dpy_gfx_update = &android_display_update;
+    dclOps.dpy_gfx_switch = &android_display_switch;
+    dcl->ops = &dclOps;
+    register_displaychangelistener(dcl);
+
+    return true;
+}
+
+extern "C" bool sdl_display_init(DisplayState* ds,
+                                 int full_screen,
+                                 int no_frame) {
+    (void)full_screen;
+    (void)no_frame;
+
+    EmulatorWindow* const emulator = emulator_window_get();
+    if (emulator->opts->no_window) {
+        return true;
+    }
+
+    return android_display_init(ds, qframebuffer_fifo_get());
+}
diff --git a/android-qemu2-glue/display.h b/android-qemu2-glue/display.h
new file mode 100644
index 0000000..98fc9c7
--- /dev/null
+++ b/android-qemu2-glue/display.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2010 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/utils/compiler.h"
+
+#include <stdbool.h>
+
+ANDROID_BEGIN_HEADER
+
+#include "ui/console.h"
+#include "../qemu/android/framebuffer.h"
+
+bool android_display_init(DisplayState* ds, QFrameBuffer* qfbuff);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/emulation/CharSerialLine.cpp b/android-qemu2-glue/emulation/CharSerialLine.cpp
new file mode 100644
index 0000000..6a958f6
--- /dev/null
+++ b/android-qemu2-glue/emulation/CharSerialLine.cpp
@@ -0,0 +1,38 @@
+// 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/CharSerialLine.h"
+
+extern "C" {
+#include "sysemu/char.h"
+}
+
+namespace android {
+namespace qemu2 {
+
+CharSerialLine::CharSerialLine(CharDriverState* cs) : mCs(cs) { }
+
+CharSerialLine::~CharSerialLine() {
+    if (mCs) {
+        qemu_chr_delete(mCs);
+    }
+}
+
+void CharSerialLine::addHandlers(void* opaque, CanReadFunc canReadFunc, ReadFunc readFunc) {
+    qemu_chr_add_handlers(mCs, canReadFunc, readFunc, NULL, opaque);
+}
+
+int CharSerialLine::write(const uint8_t* data, int len) {
+    return qemu_chr_fe_write(mCs, data, len);
+}
+
+}  // namespace qemu2
+}  // namespace android
diff --git a/android-qemu2-glue/emulation/CharSerialLine.h b/android-qemu2-glue/emulation/CharSerialLine.h
new file mode 100644
index 0000000..29b735b
--- /dev/null
+++ b/android-qemu2-glue/emulation/CharSerialLine.h
@@ -0,0 +1,51 @@
+// 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/base/Compiler.h"
+#include "android/emulation/SerialLine.h"
+#include "qemu/typedefs.h"
+
+// QEMU1-specific implementation of the generic SerialLine interface,
+// based on CharDriverState
+
+namespace android {
+namespace qemu2 {
+
+class CharSerialLine : public android::SerialLine {
+public:
+    // takes ownership of |cs|, deletes it in destructor
+    CharSerialLine(CharDriverState* cs);
+
+    ~CharSerialLine();
+
+    virtual void addHandlers(void* opaque, CanReadFunc canReadFunc, ReadFunc readFunc);
+
+    virtual int write(const uint8_t* data, int len);
+
+    CharDriverState* state() const { return mCs; }
+
+    CharDriverState* release() {
+        CharDriverState* cs = mCs;
+        mCs = nullptr;
+        return cs;
+    }
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(CharSerialLine);
+
+private:
+    CharDriverState* mCs;
+};
+
+}  // namespace qemu2
+}  // namespace android
diff --git a/android-qemu2-glue/emulation/VmLock.cpp b/android-qemu2-glue/emulation/VmLock.cpp
new file mode 100644
index 0000000..ece6ab3
--- /dev/null
+++ b/android-qemu2-glue/emulation/VmLock.cpp
@@ -0,0 +1,47 @@
+// Copyright 2016 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 "android-qemu2-glue/emulation/VmLock.h"
+
+#include "android/base/Log.h"
+
+extern "C" {
+#include "qemu/main-loop.h"
+}  // extern "C"
+
+namespace qemu2 {
+
+// TECHNICAL NOTE:
+//
+// This implementation needs to protect against recursive lock() calls
+// which can happen because some code in AndroidEmu calls it, without
+// knowing whether it's running in the thread that holds the BQL or not.
+//
+// What we want is to ensure that qemu_mutex_lock_iothread() is always true
+// when we leave ::lock(), and that it will be false when ::unlock() has
+// been called as often as ::lock() was.
+
+void VmLock::lock() {
+    qemu_mutex_lock_iothread();
+}
+
+void VmLock::unlock() {
+    qemu_mutex_unlock_iothread();
+}
+
+bool VmLock::isLockedBySelf() const {
+    return qemu_mutex_check_iothread();
+}
+
+}  // namespace qemu2
diff --git a/android-qemu2-glue/emulation/VmLock.h b/android-qemu2-glue/emulation/VmLock.h
new file mode 100644
index 0000000..0c52ae6
--- /dev/null
+++ b/android-qemu2-glue/emulation/VmLock.h
@@ -0,0 +1,33 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "android/emulation/VmLock.h"
+
+namespace qemu2 {
+
+// An implementation of android::VmLock tailored for QEMU2
+// Usage: install this in the current process with:
+//
+//      android::VmLock::set(new qemu2::VmLock());
+//
+class VmLock : public android::VmLock {
+public:
+    virtual void lock() override;
+    virtual void unlock() override;
+    virtual bool isLockedBySelf() const override;
+};
+
+}  // namespace qemu2
diff --git a/android-qemu2-glue/emulation/charpipe.c b/android-qemu2-glue/emulation/charpipe.c
new file mode 100644
index 0000000..c03f8ac
--- /dev/null
+++ b/android-qemu2-glue/emulation/charpipe.c
@@ -0,0 +1,470 @@
+/* Copyright (C) 2007-2008 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/utils/debug.h"
+#include "android/utils/cbuffer.h"
+#include "sysemu/char.h"
+
+#define  xxDEBUG
+
+#ifdef DEBUG
+#  include <stdio.h>
+#  define  D(...)   ( fprintf( stderr, __VA_ARGS__ ), fprintf(stderr, "\n") )
+#else
+#  define  D(...)   ((void)0)
+#endif
+
+/* we want to implement a bi-directionnal communication channel
+ * between two QEMU character drivers that merge well into the
+ * QEMU event loop.
+ *
+ * each half of the channel has its own object and buffer, and
+ * we implement communication through charpipe_poll() which
+ * must be called by the main event loop after its call to select()
+ *
+ */
+
+#define  BIP_BUFFER_SIZE  512
+
+typedef struct BipBuffer {
+    struct BipBuffer*  next;
+    CBuffer            cb[1];
+    char               buff[ BIP_BUFFER_SIZE ];
+} BipBuffer;
+
+static BipBuffer*  _free_bip_buffers;
+
+static BipBuffer*
+bip_buffer_alloc( void )
+{
+    BipBuffer*  bip = _free_bip_buffers;
+    if (bip != NULL) {
+        _free_bip_buffers = bip->next;
+    } else {
+        bip = malloc( sizeof(*bip) );
+        if (bip == NULL) {
+            derror( "%s: not enough memory", __FUNCTION__ );
+            exit(1);
+        }
+    }
+    bip->next = NULL;
+    cbuffer_reset( bip->cb, bip->buff, sizeof(bip->buff) );
+    return bip;
+}
+
+static void
+bip_buffer_free( BipBuffer*  bip )
+{
+    bip->next         = _free_bip_buffers;
+    _free_bip_buffers = bip;
+}
+
+/* this models each half of the charpipe */
+typedef struct CharPipeHalf {
+    CharDriverState       cs[1];
+    BipBuffer*            bip_first;
+    BipBuffer*            bip_last;
+    struct CharPipeHalf*  peer;         /* NULL if closed */
+} CharPipeHalf;
+
+
+
+static void
+charpipehalf_close( CharDriverState*  cs )
+{
+    CharPipeHalf*  ph = cs->opaque;
+
+    while (ph->bip_first) {
+        BipBuffer*  bip = ph->bip_first;
+        ph->bip_first = bip->next;
+        bip_buffer_free(bip);
+    }
+    ph->bip_last    = NULL;
+    ph->peer        = NULL;
+}
+
+
+static int
+charpipehalf_write( CharDriverState*  cs, const uint8_t*  buf, int  len )
+{
+    CharPipeHalf*  ph   = cs->opaque;
+    CharPipeHalf*  peer = ph->peer;
+    BipBuffer*     bip  = ph->bip_last;
+    int            ret  = 0;
+
+    D("%s: writing %d bytes to %p: '%s'", __FUNCTION__,
+      len, ph, quote_bytes( buf, len ));
+
+    if (bip == NULL && peer != NULL && peer->cs->chr_read != NULL) {
+        /* no buffered data, try to write directly to the peer */
+        while (len > 0) {
+            int  size;
+
+            if (peer->cs->chr_can_read) {
+                size = qemu_chr_be_can_write( peer->cs );
+                if (size == 0)
+                    break;
+
+                if (size > len)
+                    size = len;
+            } else
+                size = len;
+
+            qemu_chr_be_write( peer->cs, (uint8_t*)buf, size );
+            buf += size;
+            len -= size;
+            ret += size;
+        }
+    }
+
+    if (len == 0)
+        return ret;
+
+    /* buffer the remaining data */
+    if (bip == NULL) {
+        bip = bip_buffer_alloc();
+        ph->bip_first = ph->bip_last = bip;
+    }
+
+    while (len > 0) {
+        int  len2 = cbuffer_write( bip->cb, buf, len );
+
+        buf += len2;
+        ret += len2;
+        len -= len2;
+        if (len == 0)
+            break;
+
+        /* ok, we need another buffer */
+        ph->bip_last = bip_buffer_alloc();
+        bip->next = ph->bip_last;
+        bip       = ph->bip_last;
+    }
+    return  ret;
+}
+
+
+static void
+charpipehalf_poll( CharPipeHalf*  ph )
+{
+    CharPipeHalf*   peer = ph->peer;
+    int             size;
+
+    if (peer == NULL || peer->cs->chr_read == NULL)
+        return;
+
+    while (1) {
+        BipBuffer*  bip = ph->bip_first;
+        uint8_t*    base;
+        int         avail;
+
+        if (bip == NULL)
+            break;
+
+        size = cbuffer_read_avail(bip->cb);
+        if (size == 0) {
+            ph->bip_first = bip->next;
+            if (ph->bip_first == NULL)
+                ph->bip_last = NULL;
+            bip_buffer_free(bip);
+            continue;
+        }
+
+        if (ph->cs->chr_can_read) {
+            int  size2 = qemu_chr_be_can_write(peer->cs);
+
+            if (size2 == 0)
+                break;
+
+            if (size > size2)
+                size = size2;
+        }
+
+        avail = cbuffer_read_peek( bip->cb, &base );
+        if (avail > size)
+            avail = size;
+        D("%s: sending %d bytes from %p: '%s'", __FUNCTION__,
+            avail, ph, quote_bytes( base, avail ));
+
+        qemu_chr_be_write( peer->cs, base, avail );
+        cbuffer_read_step( bip->cb, avail );
+    }
+}
+
+
+static void
+charpipehalf_init( CharPipeHalf*  ph, CharPipeHalf*  peer )
+{
+    CharDriverState*  cs = ph->cs;
+
+    ph->bip_first   = NULL;
+    ph->bip_last    = NULL;
+    ph->peer        = peer;
+
+    cs->chr_write            = charpipehalf_write;
+    cs->chr_ioctl            = NULL;
+    cs->chr_fe_event         = NULL;
+    cs->chr_close            = charpipehalf_close;
+    cs->opaque               = ph;
+    qemu_mutex_init(&cs->chr_write_lock);
+}
+
+
+typedef struct CharPipeState {
+    CharPipeHalf  a[1];
+    CharPipeHalf  b[1];
+} CharPipeState;
+
+
+
+#define   MAX_CHAR_PIPES   8
+
+static CharPipeState  _s_charpipes[ MAX_CHAR_PIPES ];
+
+int
+qemu_chr_open_charpipe( CharDriverState*  *pfirst, CharDriverState*  *psecond )
+{
+    CharPipeState*  cp     = _s_charpipes;
+    CharPipeState*  cp_end = cp + MAX_CHAR_PIPES;
+
+    for ( ; cp < cp_end; cp++ ) {
+        if ( cp->a->peer == NULL && cp->b->peer == NULL )
+            break;
+    }
+
+    if (cp == cp_end) {  /* can't allocate one */
+        *pfirst  = NULL;
+        *psecond = NULL;
+        return -1;
+    }
+
+    charpipehalf_init( cp->a, cp->b );
+    charpipehalf_init( cp->b, cp->a );
+
+    *pfirst  = cp->a->cs;
+    *psecond = cp->b->cs;
+    return 0;
+}
+
+/** This models a charbuffer, an object used to buffer
+ ** the data that is sent to a given endpoint CharDriverState
+ ** object.
+ **
+ ** On the other hand, any can_read() / read() request performed
+ ** by the endpoint will be passed to the CharBuffer's corresponding
+ ** handlers.
+ **/
+
+typedef struct CharBuffer {
+    CharDriverState  cs[1];
+    BipBuffer*       bip_first;
+    BipBuffer*       bip_last;
+    CharDriverState* endpoint;  /* NULL if closed */
+    char             closing;
+} CharBuffer;
+
+
+static void
+charbuffer_close( CharDriverState*  cs )
+{
+    CharBuffer*  cbuf = cs->opaque;
+
+    while (cbuf->bip_first) {
+        BipBuffer*  bip = cbuf->bip_first;
+        cbuf->bip_first = bip->next;
+        bip_buffer_free(bip);
+    }
+    cbuf->bip_last = NULL;
+    cbuf->endpoint = NULL;
+
+    if (cbuf->endpoint != NULL) {
+        qemu_chr_delete(cbuf->endpoint);
+        cbuf->endpoint = NULL;
+    }
+}
+
+static int
+charbuffer_write( CharDriverState*  cs, const uint8_t*  buf, int  len )
+{
+    CharBuffer*       cbuf = cs->opaque;
+    CharDriverState*  peer = cbuf->endpoint;
+    BipBuffer*        bip  = cbuf->bip_last;
+    int               ret  = 0;
+
+    D("%s: writing %d bytes to %p: '%s'", __FUNCTION__,
+      len, cbuf, quote_bytes( buf, len ));
+
+    if (bip == NULL && peer != NULL) {
+        /* no buffered data, try to write directly to the peer */
+        int  size = qemu_chr_fe_write(peer, buf, len);
+
+        if (size < 0)  /* just to be safe */
+            size = 0;
+        else if (size > len)
+            size = len;
+
+        buf += size;
+        ret += size;
+        len -= size;
+    }
+
+    if (len == 0)
+        return ret;
+
+    /* buffer the remaining data */
+    if (bip == NULL) {
+        bip = bip_buffer_alloc();
+        cbuf->bip_first = cbuf->bip_last = bip;
+    }
+
+    while (len > 0) {
+        int  len2 = cbuffer_write( bip->cb, buf, len );
+
+        buf += len2;
+        ret += len2;
+        len -= len2;
+        if (len == 0)
+            break;
+
+        /* ok, we need another buffer */
+        cbuf->bip_last = bip_buffer_alloc();
+        bip->next = cbuf->bip_last;
+        bip       = cbuf->bip_last;
+    }
+    return  ret;
+}
+
+
+static void
+charbuffer_poll( CharBuffer*  cbuf )
+{
+    CharDriverState*  peer = cbuf->endpoint;
+
+    if (peer == NULL)
+        return;
+
+    while (1) {
+        BipBuffer*  bip = cbuf->bip_first;
+        uint8_t*    base;
+        int         avail;
+        int         size;
+
+        if (bip == NULL)
+            break;
+
+        avail = cbuffer_read_peek( bip->cb, &base );
+        if (avail == 0) {
+            cbuf->bip_first = bip->next;
+            if (cbuf->bip_first == NULL)
+                cbuf->bip_last = NULL;
+            bip_buffer_free(bip);
+            continue;
+        }
+
+        size = qemu_chr_fe_write( peer, base, avail );
+
+        if (size < 0)  /* just to be safe */
+            size = 0;
+        else if (size > avail)
+            size = avail;
+
+        cbuffer_read_step( bip->cb, size );
+
+        if (size < avail)
+            break;
+    }
+}
+
+
+static void
+charbuffer_update_handlers( CharDriverState*  cs )
+{
+    CharBuffer*  cbuf = cs->opaque;
+
+    qemu_chr_add_handlers( cbuf->endpoint,
+                           cs->chr_can_read,
+                           cs->chr_read,
+                           cs->chr_event,
+                           cs->handler_opaque );
+}
+
+
+static void
+charbuffer_init( CharBuffer*  cbuf, CharDriverState*  endpoint )
+{
+    CharDriverState*  cs = cbuf->cs;
+
+    cbuf->bip_first   = NULL;
+    cbuf->bip_last    = NULL;
+    cbuf->endpoint    = endpoint;
+
+    cs->chr_write               = charbuffer_write;
+    cs->chr_ioctl               = NULL;
+    cs->chr_fe_event            = NULL;
+    cs->chr_close               = charbuffer_close;
+    cs->chr_update_read_handler = charbuffer_update_handlers;
+    cs->opaque                  = cbuf;
+}
+
+#define MAX_CHAR_BUFFERS  8
+
+static CharBuffer  _s_charbuffers[ MAX_CHAR_BUFFERS ];
+
+CharDriverState*
+qemu_chr_open_buffer( CharDriverState*  endpoint )
+{
+    CharBuffer*  cbuf     = _s_charbuffers;
+    CharBuffer*  cbuf_end = cbuf + MAX_CHAR_BUFFERS;
+
+    if (endpoint == NULL)
+        return NULL;
+
+    for ( ; cbuf < cbuf_end; cbuf++ ) {
+        if (cbuf->endpoint == NULL)
+            break;
+    }
+
+    if (cbuf == cbuf_end)
+        return NULL;
+
+    charbuffer_init(cbuf, endpoint);
+    return cbuf->cs;
+}
+
+
+void
+charpipe_poll( void )
+{
+    CharPipeState*  cp     = _s_charpipes;
+    CharPipeState*  cp_end = cp + MAX_CHAR_PIPES;
+
+    CharBuffer*     cb     = _s_charbuffers;
+    CharBuffer*     cb_end = cb + MAX_CHAR_BUFFERS;
+
+    /* poll the charpipes */
+    for ( ; cp < cp_end; cp++ ) {
+        CharPipeHalf*  half;
+
+        half = cp->a;
+        if (half->peer != NULL)
+            charpipehalf_poll(half);
+
+        half = cp->b;
+        if (half->peer != NULL)
+            charpipehalf_poll(half);
+    }
+
+    /* poll the charbuffers */
+    for ( ; cb < cb_end; cb++ ) {
+        if (cb->endpoint != NULL)
+            charbuffer_poll(cb);
+    }
+}
diff --git a/android-qemu2-glue/emulation/charpipe.h b/android-qemu2-glue/emulation/charpipe.h
new file mode 100644
index 0000000..7a62487
--- /dev/null
+++ b/android-qemu2-glue/emulation/charpipe.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2007-2008 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 "qemu-common.h"
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+/* open two connected character drivers that can be used to communicate by internal
+ * QEMU components. For Android, this is used to connect an emulated serial port
+ * with the android modem
+ */
+extern int  qemu_chr_open_charpipe( CharDriverState* *pfirst, CharDriverState* *psecond );
+
+/* create a buffering character driver for a given endpoint. The result will buffer
+ * anything that is sent to it but cannot be sent to the endpoint immediately.
+ * On the other hand, if the endpoint calls can_read() or read(), these calls
+ * are passed immediately to the can_read() or read() handlers of the result.
+ */
+extern CharDriverState*  qemu_chr_open_buffer( CharDriverState*  endpoint );
+
+/* must be called from the main event loop to poll all charpipes */
+extern void charpipe_poll( void );
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/emulation/serial_line.cpp b/android-qemu2-glue/emulation/serial_line.cpp
new file mode 100644
index 0000000..0b73ac6
--- /dev/null
+++ b/android-qemu2-glue/emulation/serial_line.cpp
@@ -0,0 +1,63 @@
+// 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/serial_line.h"
+
+#include "android-qemu2-glue/emulation/charpipe.h"
+#include "android-qemu2-glue/emulation/CharSerialLine.h"
+
+using android::qemu2::CharSerialLine;
+using android::SerialLine;
+
+CSerialLine* android_serialline_from_cs(CharDriverState* cs) {
+    return new CharSerialLine(cs);
+}
+
+CharDriverState* android_serialline_get_cs(CSerialLine* sl) {
+    return static_cast<CharSerialLine*>(sl)->state();
+}
+
+CharDriverState* android_serialline_release_cs(CSerialLine* sl) {
+    CharSerialLine* csl = static_cast<CharSerialLine*>(sl);
+    CharDriverState* result = csl->release();
+    delete csl;
+    return result;
+}
+
+static SerialLine* qemu_serialline_buffer_open(SerialLine* sl) {
+    CharDriverState* cs = static_cast<CharSerialLine*>(sl)->state();
+    return new CharSerialLine(qemu_chr_open_buffer(cs));
+}
+
+static bool qemu_serialline_pipe_open(SerialLine** pfirst,
+                                      SerialLine** psecond) {
+    CharDriverState* first_cs = NULL;
+    CharDriverState* second_cs = NULL;
+
+    if (qemu_chr_open_charpipe(&first_cs, &second_cs)) {
+        *pfirst = NULL;
+        *psecond = NULL;
+        return false;
+    }
+
+    *pfirst = new CharSerialLine(first_cs);
+    *psecond = new CharSerialLine(second_cs);
+    return true;
+}
+
+void qemu2_android_serialline_init() {
+    static const android::SerialLine::Funcs kQemuSerialLineFuncs = {
+        .openBuffer = qemu_serialline_buffer_open,
+        .openPipe = qemu_serialline_pipe_open
+    };
+
+    android::SerialLine::Funcs::reset(&kQemuSerialLineFuncs);
+}
diff --git a/android-qemu2-glue/emulation/serial_line.h b/android-qemu2-glue/emulation/serial_line.h
new file mode 100644
index 0000000..f0cdebe
--- /dev/null
+++ b/android-qemu2-glue/emulation/serial_line.h
@@ -0,0 +1,39 @@
+// 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/serial_line.h"
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+// NOTE: Do not include "qemu-common.h" here because this fails
+//       to compile when included from a C++ file due to other
+//       issues in include/qemu/int28.h. Instead, use the
+typedef struct CharDriverState CharDriverState;
+
+// Call this during setup to inject QEMU2-specific SerialLine
+// implementation into the process.
+void qemu2_android_serialline_init(void);
+
+// Create a new CSerialLine instance that wraps a CharDriverState |cs|.
+CSerialLine* android_serialline_from_cs(CharDriverState* cs);
+
+// Extract the QEMU1 CharDriverState instance wrapped by a CSerialLine
+// instance |sl|.
+CharDriverState* android_serialline_get_cs(CSerialLine* sl);
+
+// Extract the CharDriverState instance wrapped by |sl|, but also
+// destroys the CSerialLine instance.
+CharDriverState* android_serialline_release_cs(CSerialLine* sl);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/looper-qemu.cpp b/android-qemu2-glue/looper-qemu.cpp
new file mode 100644
index 0000000..e990436
--- /dev/null
+++ b/android-qemu2-glue/looper-qemu.cpp
@@ -0,0 +1,23 @@
+// 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/looper-qemu.h"
+
+#include "android-qemu2-glue/base/async/Looper.h"
+#include "android/base/async/Looper.h"
+#include "android/utils/looper.h"
+
+typedef ::Looper CLooper;
+
+void qemu_looper_setForThread() {
+    looper_setForThreadToOwn(
+            reinterpret_cast<CLooper*>(::android::qemu::createLooper()));
+}
diff --git a/android-qemu2-glue/looper-qemu.h b/android-qemu2-glue/looper-qemu.h
new file mode 100644
index 0000000..9b68629
--- /dev/null
+++ b/android-qemu2-glue/looper-qemu.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 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/utils/compiler.h"
+#include "android/utils/looper.h"
+
+ANDROID_BEGIN_HEADER
+
+/* Create a new looper which is implemented on top of the QEMU main event
+ * loop. You should only use this when implementing the emulator UI and Core
+ * features in a single program executable.
+ */
+void qemu_looper_setForThread(void);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/main.cpp b/android-qemu2-glue/main.cpp
new file mode 100755
index 0000000..7ad7577
--- /dev/null
+++ b/android-qemu2-glue/main.cpp
@@ -0,0 +1,929 @@
+// 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/base/containers/StringVector.h"
+#include "android/base/files/PathUtils.h"
+#include "android/base/Log.h"
+#include "android/base/memory/ScopedPtr.h"
+#include "android/base/StringFormat.h"
+#include "android/base/system/System.h"
+
+#include "android/android.h"
+#include "android/avd/hw-config.h"
+#include "android/cmdline-option.h"
+#include "android/constants.h"
+#include "android/crashreport/crash-handler.h"
+#include "android/error-messages.h"
+#include "android/filesystems/ext4_resize.h"
+#include "android/filesystems/ext4_utils.h"
+#include "android/globals.h"
+#include "android/help.h"
+#include "android/kernel/kernel_utils.h"
+#include "android/main-common.h"
+#include "android/main-common-ui.h"
+#include "android/main-kernel-parameters.h"
+#include "android/opengl/emugl_config.h"
+#include "android/process_setup.h"
+#include "android/utils/bufprint.h"
+#include "android/utils/debug.h"
+#include "android/utils/path.h"
+#include "android/utils/lineinput.h"
+#include "android/utils/property_file.h"
+#include "android/utils/filelock.h"
+#include "android/utils/stralloc.h"
+#include "android/utils/string.h"
+#include "android/utils/tempfile.h"
+#include "android/utils/win32_cmdline_quote.h"
+
+#include "android/skin/winsys.h"
+
+#include "config-target.h"
+
+extern "C" {
+#include "android/skin/charmap.h"
+}
+
+#include "android/ui-emu-agent.h"
+#include "android-qemu2-glue/emulation/serial_line.h"
+#include "android-qemu2-glue/qemu-control-impl.h"
+
+#ifdef TARGET_AARCH64
+#define TARGET_ARM64
+#endif
+#ifdef TARGET_I386
+#define TARGET_X86
+#endif
+
+#include <algorithm>
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "android/version.h"
+#define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
+
+int android_base_port;
+int android_serial_number_port;
+
+extern bool android_op_wipe_data;
+extern bool android_op_writable_system;
+
+using namespace android::base;
+using android::base::System;
+
+namespace {
+
+enum ImageType {
+    IMAGE_TYPE_SYSTEM = 0,
+    IMAGE_TYPE_CACHE,
+    IMAGE_TYPE_USER_DATA,
+    IMAGE_TYPE_SD_CARD,
+};
+
+const int kMaxPartitions = 4;
+const int kMaxTargetQemuParams = 16;
+
+/*
+ * A structure used to model information about a given target CPU architecture.
+ * |androidArch| is the architecture name, following Android conventions.
+ * |qemuArch| is the same name, following QEMU conventions, used to locate
+ * the final qemu-system-<qemuArch> binary.
+ * |qemuCpu| is the QEMU -cpu parameter value.
+ * |ttyPrefix| is the prefix to use for TTY devices.
+ * |storageDeviceType| is the QEMU storage device type.
+ * |networkDeviceType| is the QEMU network device type.
+ * |imagePartitionTypes| defines the order of how the image partitions are
+ * listed in the command line, because the command line order determines which
+ * mount point the partition is attached to.  For x86, the first partition
+ * listed in command line is mounted first, i.e. to /dev/block/vda,
+ * the next one to /dev/block/vdb, etc. However, for arm/mips, it's reversed;
+ * the last one is mounted to /dev/block/vda. the 2nd last to /dev/block/vdb.
+ * So far, we have 4(kMaxPartitions) types defined for system, cache, userdata
+ * and sdcard images.
+ * |qemuExtraArgs| are the qemu parameters specific to the target platform.
+ * this is a NULL-terminated list of string pointers of at most
+ * kMaxTargetQemuParams(16).
+ */
+struct TargetInfo {
+    const char* androidArch;
+    const char* qemuArch;
+    const char* qemuCpu;
+    const char* ttyPrefix;
+    const char* storageDeviceType;
+    const char* networkDeviceType;
+    const ImageType imagePartitionTypes[kMaxPartitions];
+    const char* qemuExtraArgs[kMaxTargetQemuParams];
+};
+
+// The current target architecture information!
+const TargetInfo kTarget = {
+#ifdef TARGET_ARM64
+    "arm64",
+    "aarch64",
+    "cortex-a57",
+    "ttyAMA",
+    "virtio-blk-device",
+    "virtio-net-device",
+    {IMAGE_TYPE_SD_CARD, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_CACHE, IMAGE_TYPE_SYSTEM},
+    {NULL},
+#elif defined(TARGET_ARM)
+    "arm",
+    "arm",
+    "cortex-a15",
+    "ttyAMA",
+    "virtio-blk-device",
+    "virtio-net-device",
+    {IMAGE_TYPE_SD_CARD, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_CACHE, IMAGE_TYPE_SYSTEM},
+    {NULL},
+#elif defined(TARGET_MIPS64)
+    "mips64",
+    "mips64el",
+    "MIPS64R6-generic",
+    "ttyGF",
+    "virtio-blk-device",
+    "virtio-net-device",
+    {IMAGE_TYPE_SD_CARD, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_CACHE, IMAGE_TYPE_SYSTEM},
+    {NULL},
+#elif defined(TARGET_MIPS)
+    "mips",
+    "mipsel",
+    "74Kf",
+    "ttyGF",
+    "virtio-blk-device",
+    "virtio-net-device",
+    {IMAGE_TYPE_SD_CARD, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_CACHE, IMAGE_TYPE_SYSTEM},
+    {NULL},
+#elif defined(TARGET_X86_64)
+    "x86_64",
+    "x86_64",
+    "android64",
+    "ttyS",
+    "virtio-blk-pci",
+    "virtio-net-pci",
+    {IMAGE_TYPE_SYSTEM, IMAGE_TYPE_CACHE, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_SD_CARD},
+    {"-vga", "none", NULL},
+#elif defined(TARGET_I386)  // Both i386 and x86_64 targets define this macro
+    "x86",
+    "i386",
+    "android32",
+    "ttyS",
+    "virtio-blk-pci",
+    "virtio-net-pci",
+    {IMAGE_TYPE_SYSTEM, IMAGE_TYPE_CACHE, IMAGE_TYPE_USER_DATA, IMAGE_TYPE_SD_CARD},
+    {"-vga", "none", NULL},
+#else
+    #error No target platform is defined
+#endif
+};
+
+static std::string getNthParentDir(const char* path, size_t n) {
+    StringVector dir = PathUtils::decompose(path);
+    PathUtils::simplifyComponents(&dir);
+    if (dir.size() < n + 1U) {
+        return std::string("");
+    }
+    dir.resize(dir.size() - n);
+    return PathUtils::recompose(dir);
+}
+
+/* generate parameters for each partition by type.
+ * Param:
+ *  args - array to hold parameters for qemu
+ *  argsPosition - current index in the parameter array
+ *  driveIndex - a sequence number for the drive parameter
+ *  hw - the hardware configuration that conatains image info.
+ *  type - what type of partition parameter to generate
+*/
+
+static void makePartitionCmd(const char** args, int* argsPosition, int* driveIndex,
+                             AndroidHwConfig* hw, ImageType type, bool writable,
+                             int apiLevel) {
+    int n   = *argsPosition;
+    int idx = *driveIndex;
+
+#if defined(TARGET_X86_64) || defined(TARGET_I386)
+    /* for x86, 'if=none' is necessary for virtio blk*/
+    std::string driveParam("if=none,");
+#else
+    std::string driveParam;
+#endif
+    std::string deviceParam;
+
+    switch (type) {
+        case IMAGE_TYPE_SYSTEM:
+            driveParam += StringFormat("index=%d,id=system,file=%s",
+                                        idx++,
+                                        hw->disk_systemPartition_initPath);
+            // API 15 and under images need a read+write
+            // system image.
+            if (apiLevel > 15) {
+                // API > 15 uses read-only system partition.
+                // You can override this explicitly
+                // by passing -writable-system to emulator.
+                if (!writable)
+                    driveParam += ",read-only";
+            }
+            deviceParam = StringFormat("%s,drive=system",
+                                       kTarget.storageDeviceType);
+            break;
+        case IMAGE_TYPE_CACHE:
+            driveParam += StringFormat("index=%d,id=cache,file=%s",
+                                      idx++,
+                                      hw->disk_cachePartition_path);
+            deviceParam = StringFormat("%s,drive=cache",
+                                       kTarget.storageDeviceType);
+            break;
+        case IMAGE_TYPE_USER_DATA:
+            driveParam += StringFormat("index=%d,id=userdata,file=%s",
+                                      idx++,
+                                      hw->disk_dataPartition_path);
+            deviceParam = StringFormat("%s,drive=userdata",
+                                       kTarget.storageDeviceType);
+            break;
+        case IMAGE_TYPE_SD_CARD:
+            if (hw->hw_sdCard_path != NULL && strcmp(hw->hw_sdCard_path, "")) {
+               driveParam += StringFormat("index=%d,id=sdcard,file=%s",
+                                         idx++, hw->hw_sdCard_path);
+               deviceParam = StringFormat("%s,drive=sdcard",
+                                          kTarget.storageDeviceType);
+            } else {
+                /* no sdcard is defined */
+                return;
+            }
+            break;
+        default:
+            dwarning("Unknown Image type %d\n", type);
+            return;
+    }
+    args[n++] = "-drive";
+    args[n++] = ASTRDUP(driveParam.c_str());
+    args[n++] = "-device";
+    args[n++] = ASTRDUP(deviceParam.c_str());
+    /* update the index */
+    *argsPosition = n;
+    *driveIndex = idx;
+}
+
+
+}  // namespace
+
+
+extern "C" int run_qemu_main(int argc, const char **argv);
+
+static void enter_qemu_main_loop(int argc, char **argv) {
+#ifndef _WIN32
+    sigset_t set;
+    sigemptyset(&set);
+    pthread_sigmask(SIG_SETMASK, &set, NULL);
+#endif
+
+    D("Starting QEMU main loop");
+    run_qemu_main(argc, (const char**)argv);
+    D("Done with QEMU main loop");
+
+    if (android_init_error_occurred()) {
+        skin_winsys_error_dialog(android_init_error_get_message(), "Error");
+    }
+}
+
+#if defined(_WIN32)
+// On Windows, link against qtmain.lib which provides a WinMain()
+// implementation, that later calls qMain().
+#define main qt_main
+#endif
+
+extern "C" int main(int argc, char **argv) {
+    process_early_setup(argc, argv);
+
+    if (argc < 1) {
+        fprintf(stderr, "Invalid invocation (no program path)\n");
+        return 1;
+    }
+
+    /* The emulator always uses the first serial port for kernel messages
+     * and the second one for qemud. So start at the third if we need one
+     * for logcat or 'shell'
+     */
+    const char* args[128];
+    args[0] = argv[0];
+    int n = 1;  // next parameter index
+
+    AndroidHwConfig* hw = android_hw;
+    AvdInfo* avd;
+    AndroidOptions opts[1];
+    int exitStatus = 0;
+
+    if (!emulator_parseCommonCommandLineOptions(&argc,
+                                                &argv,
+                                                kTarget.androidArch,
+                                                true,  // is_qemu2
+                                                opts,
+                                                hw,
+                                                &android_avdInfo,
+                                                &exitStatus)) {
+        // Special case for QEMU positional parameters.
+        if (exitStatus == EMULATOR_EXIT_STATUS_POSITIONAL_QEMU_PARAMETER) {
+            // Copy all QEMU options to |args|, and set |n| to the number
+            // of options in |args| (|argc| must be positive here).
+            for (n = 1; n <= argc; ++n) {
+                args[n] = argv[n - 1];
+            }
+
+            // Skip the translation of command-line options and jump
+            // straight to qemu_main().
+            enter_qemu_main_loop(n, (char**)args);
+            return 0;
+        }
+
+        // Normal exit.
+        return exitStatus;
+    }
+    // just because we know that we're in the new emulator as we got here
+    opts->ranchu = 1;
+
+    avd = android_avdInfo;
+
+    if (!emulator_parseUiCommandLineOptions(opts, avd, hw)) {
+        return 1;
+    }
+
+    char boot_prop_ip[128] = {};
+    if (opts->shared_net_id) {
+        char*  end;
+        long   shared_net_id = strtol(opts->shared_net_id, &end, 0);
+        if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
+            fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
+            return 1;
+        }
+        snprintf(boot_prop_ip, sizeof(boot_prop_ip),
+                 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
+    }
+    if (boot_prop_ip[0]) {
+        args[n++] = "-boot-property";
+        args[n++] = boot_prop_ip;
+    }
+
+#ifdef CONFIG_NAND_LIMITS
+    if (opts->nand_limits) {
+        args[n++] = "-nand-limits";
+        args[n++] = opts->nand_limits;
+    }
+#endif
+
+    if (opts->timezone) {
+        args[n++] = "-timezone";
+        args[n++] = opts->timezone;
+    }
+
+    if (opts->netspeed) {
+        args[n++] = "-netspeed";
+        args[n++] = opts->netspeed;
+    }
+    if (opts->netdelay) {
+        args[n++] = "-netdelay";
+        args[n++] = opts->netdelay;
+    }
+    if (opts->netfast) {
+        args[n++] = "-netfast";
+    }
+
+    if (opts->audio && !strcmp(opts->audio, "none")) {
+        args[n++] = "-no-audio";
+    }
+
+    if (opts->cpu_delay) {
+        args[n++] = "-cpu-delay";
+        args[n++] = opts->cpu_delay;
+    }
+
+    if (opts->dns_server) {
+        args[n++] = "-dns-server";
+        args[n++] = opts->dns_server;
+    }
+
+    /** SNAPSHOT STORAGE HANDLING */
+
+    /* If we have a valid snapshot storage path */
+
+    if (opts->snapstorage) {
+        // NOTE: If QEMU2_SNAPSHOT_SUPPORT is not defined, a warning has been
+        //       already printed by emulator_parseCommonCommandLineOptions().
+#ifdef QEMU2_SNAPSHOT_SUPPORT
+        /* We still use QEMU command-line options for the following since
+        * they can change from one invokation to the next and don't really
+        * correspond to the hardware configuration itself.
+        */
+        if (!opts->no_snapshot_load) {
+            args[n++] = "-loadvm";
+            args[n++] = ASTRDUP(opts->snapshot);
+        }
+
+        if (!opts->no_snapshot_save) {
+            args[n++] = "-savevm-on-exit";
+            args[n++] = ASTRDUP(opts->snapshot);
+        }
+
+        if (opts->no_snapshot_update_time) {
+            args[n++] = "-snapshot-no-time-update";
+        }
+#endif  // QEMU2_SNAPSHOT_SUPPORT
+    }
+
+    {
+        // Always setup a single serial port, that can be connected
+        // either to the 'null' chardev, or the -shell-serial one,
+        // which by default will be either 'stdout' (Posix) or 'con:'
+        // (Windows).
+        const char* serial =
+                (opts->shell || opts->logcat || opts->show_kernel)
+                ? opts->shell_serial : "null";
+        args[n++] = "-serial";
+        args[n++] = serial;
+    }
+
+    if (opts->radio) {
+        args[n++] = "-radio";
+        args[n++] = opts->radio;
+    }
+
+    if (opts->gps) {
+        args[n++] = "-gps";
+        args[n++] = opts->gps;
+    }
+
+    if (opts->code_profile) {
+        args[n++] = "-code-profile";
+        args[n++] = opts->code_profile;
+    }
+
+    /* Pass boot properties to the core. First, those from boot.prop,
+     * then those from the command-line */
+    const FileData* bootProperties = avdInfo_getBootProperties(avd);
+    if (!fileData_isEmpty(bootProperties)) {
+        PropertyFileIterator iter[1];
+        propertyFileIterator_init(iter,
+                                  bootProperties->data,
+                                  bootProperties->size);
+        while (propertyFileIterator_next(iter)) {
+            char temp[MAX_PROPERTY_NAME_LEN + MAX_PROPERTY_VALUE_LEN + 2];
+            snprintf(temp, sizeof temp, "%s=%s", iter->name, iter->value);
+            args[n++] = "-boot-property";
+            args[n++] = ASTRDUP(temp);
+        }
+    }
+
+    if (opts->prop != NULL) {
+        ParamList*  pl = opts->prop;
+        for ( ; pl != NULL; pl = pl->next ) {
+            args[n++] = "-boot-property";
+            args[n++] = pl->param;
+        }
+    }
+
+    if (opts->ports) {
+        args[n++] = "-android-ports";
+        args[n++] = opts->ports;
+    }
+
+    if (opts->port) {
+        int console_port = -1;
+        int adb_port = -1;
+        if (!android_parse_port_option(opts->port, &console_port, &adb_port)) {
+            return 1;
+        }
+        std::string portsOption = StringFormat("%d,%d",
+                                               console_port, adb_port);
+        args[n++] = "-android-ports";
+        args[n++] = strdup(portsOption.c_str());
+    }
+
+    if (opts->report_console) {
+        args[n++] = "-android-report-console";
+        args[n++] = opts->report_console;
+    }
+
+    if (opts->http_proxy) {
+        args[n++] = "-http-proxy";
+        args[n++] = opts->http_proxy;
+    }
+
+    if (!opts->charmap) {
+        /* Try to find a valid charmap name */
+        char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
+        if (charmap != NULL) {
+            D("autoconfig: -charmap %s", charmap);
+            opts->charmap = charmap;
+        }
+    }
+
+    if (opts->charmap) {
+        char charmap_name[SKIN_CHARMAP_NAME_SIZE];
+
+        if (!path_exists(opts->charmap)) {
+            derror("Charmap file does not exist: %s", opts->charmap);
+            return 1;
+        }
+        /* We need to store the charmap name in the hardware configuration.
+         * However, the charmap file itself is only used by the UI component
+         * and doesn't need to be set to the emulation engine.
+         */
+        kcm_extract_charmap_name(opts->charmap, charmap_name,
+                                 sizeof(charmap_name));
+        reassign_string(&hw->hw_keyboard_charmap, charmap_name);
+    }
+
+// TODO: imement network
+#if 0
+    /* Set up the interfaces for inter-emulator networking */
+    if (opts->shared_net_id) {
+        unsigned int shared_net_id = atoi(opts->shared_net_id);
+        char nic[37];
+
+        args[n++] = "-net";
+        args[n++] = "nic,vlan=0";
+        args[n++] = "-net";
+        args[n++] = "user,vlan=0";
+
+        args[n++] = "-net";
+        snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
+        args[n++] = strdup(nic);
+        args[n++] = "-net";
+        args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
+    }
+#endif
+
+    // Create userdata file from init version if needed.
+    if (android_op_wipe_data || !path_exists(hw->disk_dataPartition_path)) {
+        if (!path_exists(hw->disk_dataPartition_initPath)) {
+            derror("Missing initial data partition file: %s",
+                   hw->disk_dataPartition_initPath);
+            return 1;
+        }
+        D("Creating: %s\n", hw->disk_dataPartition_path);
+
+        if (path_copy_file(hw->disk_dataPartition_path,
+                           hw->disk_dataPartition_initPath) < 0) {
+            derror("Could not create %s: %s", hw->disk_dataPartition_path,
+                   strerror(errno));
+            return 1;
+        }
+
+        resizeExt4Partition(android_hw->disk_dataPartition_path,
+                            android_hw->disk_dataPartition_size);
+    }
+    else {
+        // Resize userdata-qemu.img if the size is smaller than what config.ini
+        // says.
+        // This can happen as user wants a larger data partition without wiping
+        // it.
+        // b.android.com/196926
+        System::FileSize current_data_size;
+        if (System::get()->pathFileSize(hw->disk_dataPartition_path,
+                                        &current_data_size)) {
+            System::FileSize partition_size = static_cast<System::FileSize>(
+                    android_hw->disk_dataPartition_size);
+            if (android_hw->disk_dataPartition_size > 0 &&
+                    current_data_size < partition_size) {
+                dwarning("userdata partition is resized from %d M to %d M\n",
+                         (int)(current_data_size / (1024 * 1024)),
+                         (int)(partition_size / (1024 * 1024)));
+                resizeExt4Partition(android_hw->disk_dataPartition_path,
+                                    android_hw->disk_dataPartition_size);
+            }
+        }
+    }
+
+    bool createEmptyCacheFile = false;
+
+    // Make sure there's a temp cache partition if there wasn't a permanent one
+    if (!hw->disk_cachePartition_path ||
+        strcmp(hw->disk_cachePartition_path, "") == 0) {
+        str_reset(&hw->disk_cachePartition_path,
+                  tempfile_path(tempfile_create()));
+        createEmptyCacheFile = true;
+    }
+
+    createEmptyCacheFile |= !path_exists(hw->disk_cachePartition_path);
+
+    if (createEmptyCacheFile) {
+        D("Creating empty ext4 cache partition: %s",
+          hw->disk_cachePartition_path);
+        int ret = android_createEmptyExt4Image(
+                hw->disk_cachePartition_path,
+                hw->disk_cachePartition_size,
+                "cache");
+        if (ret < 0) {
+            derror("Could not create %s: %s", hw->disk_cachePartition_path,
+                   strerror(-ret));
+            return 1;
+        }
+    }
+
+    // Make sure we always use the custom Android CPU definition.
+    args[n++] = "-cpu";
+    args[n++] = kTarget.qemuCpu;
+
+#if defined(TARGET_X86_64) || defined(TARGET_I386)
+    char* accel_status = NULL;
+    CpuAccelMode accel_mode = ACCEL_AUTO;
+    const bool accel_ok = handleCpuAcceleration(opts, avd,
+                                                &accel_mode, &accel_status);
+
+    if (accel_mode == ACCEL_ON) {  // 'accel on' is specified'
+        if (!accel_ok) {
+            derror("CPU acceleration is not supported on this machine!");
+            derror("Reason: %s", accel_status);
+            return 1;
+        }
+        args[n++] = ASTRDUP(kEnableAccelerator);
+    } else if (accel_mode == ACCEL_AUTO) {
+        if (accel_ok) {
+            args[n++] = ASTRDUP(kEnableAccelerator);
+        }
+    } // else accel is off and we don't need to add anything else
+
+    AFREE(accel_status);
+#else   // !TARGET_X86_64 && !TARGET_I386
+    args[n++] = "-machine";
+    args[n++] = "type=ranchu";
+#endif  // !TARGET_X86_64 && !TARGET_I386
+
+#if defined(TARGET_X86_64) || defined(TARGET_I386)
+    // SMP Support.
+    std::string ncores;
+    if (hw->hw_cpu_ncore > 1) {
+        args[n++] = "-smp";
+
+#ifdef _WIN32
+        if (hw->hw_cpu_ncore > 16) {
+            dwarning("HAXM does not support more than 16 cores. Number of cores set to 16");
+            hw->hw_cpu_ncore = 16;
+        }
+#endif
+        ncores = StringFormat("cores=%ld", hw->hw_cpu_ncore);
+        args[n++] = ncores.c_str();
+    }
+#endif  // !TARGET_X86_64 && !TARGET_I386
+
+    // Memory size
+    args[n++] = "-m";
+    std::string memorySize = StringFormat("%ld", hw->hw_ramSize);
+    args[n++] = memorySize.c_str();
+
+    // Kernel command-line parameters.
+    AndroidGlesEmulationMode glesMode = kAndroidGlesEmulationOff;
+    if (hw->hw_gpu_enabled) {
+        if (!strcmp(hw->hw_gpu_mode, "guest")) {
+            glesMode = kAndroidGlesEmulationGuest;
+        } else {
+            glesMode = kAndroidGlesEmulationHost;
+        }
+    }
+
+    uint64_t glesFramebufferCMA = 0ULL;
+    if ((glesMode == kAndroidGlesEmulationGuest) ||
+        (opts->gpu && !strcmp(opts->gpu, "guest")) ||
+        !hw->hw_gpu_enabled) {
+        // Set CMA (continguous memory allocation) to values that depend on
+        // the desired resolution.
+        // We will assume a double buffered 32-bit framebuffer
+        // in the calculation.
+        int framebuffer_width = hw->hw_lcd_width;
+        int framebuffer_height = hw->hw_lcd_height;
+        uint64_t bytes = framebuffer_width * framebuffer_height * 4;
+        const uint64_t one_MB = 1024ULL * 1024;
+        glesFramebufferCMA = (2 * bytes + one_MB - 1) / one_MB;
+        VERBOSE_PRINT(init, "Adjusting Contiguous Memory Allocation "
+                            "of %dx%d framebuffer for software renderer to %"
+                            PRIu64 "MB.", framebuffer_width, framebuffer_height,
+                            glesFramebufferCMA);
+    } else {
+        VERBOSE_PRINT(init, "Using default value for kernel "
+                            "Contiguous Memory Allocation.");
+    }
+
+
+    int apiLevel = avd ? avdInfo_getApiLevel(avd) : 1000;
+
+    char* kernel_parameters = emulator_getKernelParameters(
+            opts, kTarget.androidArch, apiLevel, kTarget.ttyPrefix,
+            hw->kernel_parameters, glesMode, glesFramebufferCMA,
+            true  // isQemu2
+            );
+    if (!kernel_parameters) {
+        return 1;
+    }
+
+    args[n++] = "-append";
+    args[n++] = kernel_parameters;
+
+    // Support for changing default lcd-density
+    std::string lcd_density;
+    if (hw->hw_lcd_density) {
+        args[n++] = "-lcd-density";
+        lcd_density = StringFormat("%d", hw->hw_lcd_density);
+        args[n++] = lcd_density.c_str();
+    }
+
+    // Kernel image
+    args[n++] = "-kernel";
+    args[n++] = hw->kernel_path;
+
+    // Ramdisk
+    args[n++] = "-initrd";
+    args[n++] = hw->disk_ramdisk_path;
+
+    /*
+     * add partition parameters with the sequence
+     * pre-defined in targetInfo.imagePartitionTypes
+     */
+    int s;
+    int drvIndex = 0;
+    for (s = 0; s < kMaxPartitions; s++) {
+        bool writable = (kTarget.imagePartitionTypes[s] == IMAGE_TYPE_SYSTEM) ?
+                    android_op_writable_system : true;
+        makePartitionCmd(args, &n, &drvIndex, hw,
+                         kTarget.imagePartitionTypes[s], writable, apiLevel);
+    }
+
+    // Network
+    args[n++] = "-netdev";
+    args[n++] = "user,id=mynet";
+    args[n++] = "-device";
+    std::string netDevice =
+            StringFormat("%s,netdev=mynet", kTarget.networkDeviceType);
+    args[n++] = netDevice.c_str();
+    args[n++] = "-show-cursor";
+
+    // TODO: the following *should* re-enable -tcpdump in QEMU2 when we have
+    // rebased to at least QEMU 2.5 - the standard -tcpdump flag
+    // See http://wiki.qemu.org/ChangeLog/2.5#Network_2 and
+    // http://wiki.qemu.org/download/qemu-doc.html#index-_002dobject
+//    std::string tcpdumpArg;
+//    if (opts->tcpdump) {
+//        args[n++] = "-object";
+//        tcpdumpArg = StringFormat("filter-dump,id=mytcpdump,netdev=mynet,file=%s",
+//                                  opts->tcpdump);
+//        args[n++] = tcpdumpArg.c_str();
+//    }
+
+    if (opts->tcpdump) {
+        dwarning("The -tcpdump flag is not supported in QEMU2 yet and will "
+                 "be ignored.");
+    }
+
+    // Graphics
+    if (opts->no_window) {
+        args[n++] = "-nographic";
+        // also disable the qemu monitor which will otherwise grab stdio
+        args[n++] = "-monitor";
+        args[n++] = "none";
+    }
+
+    // Data directory (for keymaps and PC Bios).
+    args[n++] = "-L";
+    std::string dataDir = getNthParentDir(args[0], 3U);
+    if (dataDir.empty()) {
+        dataDir = "lib/pc-bios";
+    } else {
+        dataDir += "/lib/pc-bios";
+    }
+    args[n++] = dataDir.c_str();
+
+    // Audio enable hda by default for x86 and x64 platforms
+#if defined(TARGET_X86_64) || defined(TARGET_I386)
+    args[n++] = "-soundhw";
+    args[n++] = "hda";
+#endif
+
+    /* append extra qemu parameters if any */
+    for (int idx = 0; kTarget.qemuExtraArgs[idx] != NULL; idx++) {
+        args[n++] = kTarget.qemuExtraArgs[idx];
+    }
+
+    /* append the options after -qemu */
+    for (int i = 0; i < argc; ++i) {
+        args[n++] = argv[i];
+    }
+
+    /* Generate a hardware-qemu.ini for this AVD. The real hardware
+     * configuration is ususally stored in several files, e.g. the AVD's
+     * config.ini plus the skin-specific hardware.ini.
+     *
+     * The new file will group all definitions and will be used to
+     * launch the core with the -android-hw <file> option.
+     */
+    {
+        const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
+        const auto hwIni = android::base::makeCustomScopedPtr(
+                         iniFile_newEmpty(NULL), iniFile_free);
+        androidHwConfig_write(hw, hwIni.get());
+
+        if (filelock_create(coreHwIniPath) == NULL) {
+            // The AVD is already in use
+            derror("There's another emulator instance running with "
+                   "the current AVD '%s'. Exiting...\n", avdInfo_getName(avd));
+            return 1;
+        }
+
+        /* While saving HW config, ignore valueless entries. This will not break
+         * anything, but will significantly simplify comparing the current HW
+         * config with the one that has been associated with a snapshot (in case
+         * VM starts from a snapshot for this instance of emulator). */
+        if (iniFile_saveToFileClean(hwIni.get(), coreHwIniPath) < 0) {
+            derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
+            return 2;
+        }
+        args[n++] = "-android-hw";
+        args[n++] = strdup(coreHwIniPath);
+
+        crashhandler_copy_attachment(CRASH_AVD_HARDWARE_INFO, coreHwIniPath);
+
+        /* In verbose mode, dump the file's content */
+        if (VERBOSE_CHECK(init)) {
+            FILE* file = fopen(coreHwIniPath, "rt");
+            if (file == NULL) {
+                derror("Could not open hardware configuration file: %s\n",
+                       coreHwIniPath);
+            } else {
+                LineInput* input = lineInput_newFromStdFile(file);
+                const char* line;
+                printf("Content of hardware configuration file:\n");
+                while ((line = lineInput_getLine(input)) !=  NULL) {
+                    printf("  %s\n", line);
+                }
+                printf(".\n");
+                lineInput_free(input);
+                fclose(file);
+            }
+        }
+    }
+
+    args[n] = NULL;
+    // Check if we had enough slots in |args|.
+    assert(n < (int)(sizeof(args)/sizeof(args[0])));
+
+    if(VERBOSE_CHECK(init)) {
+        int i;
+        printf("QEMU options list:\n");
+        for(i = 0; i < n; i++) {
+            printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
+        }
+        /* Dump final command-line option to make debugging the core easier */
+        printf("Concatenated QEMU options:\n");
+        for (i = 0; i < n; i++) {
+            /* To make it easier to copy-paste the output to a command-line,
+             * quote anything that contains spaces.
+             */
+            if (strchr(args[i], ' ') != NULL) {
+                printf(" '%s'", args[i]);
+            } else {
+                printf(" %s", args[i]);
+            }
+        }
+        printf("\n");
+    }
+
+    qemu2_android_serialline_init();
+
+    static UiEmuAgent uiEmuAgent;
+    uiEmuAgent.battery = gQAndroidBatteryAgent;
+    uiEmuAgent.cellular = gQAndroidCellularAgent;
+    uiEmuAgent.finger = gQAndroidFingerAgent;
+    uiEmuAgent.location = gQAndroidLocationAgent;
+    uiEmuAgent.sensors = gQAndroidSensorsAgent;
+    uiEmuAgent.telephony = gQAndroidTelephonyAgent;
+    uiEmuAgent.userEvents = gQAndroidUserEventAgent;
+    uiEmuAgent.window = gQAndroidEmulatorWindowAgent;
+
+    // for now there's no uses of SettingsAgent, so we don't set it
+    uiEmuAgent.settings = NULL;
+
+    /* Setup SDL UI just before calling the code */
+#ifndef _WIN32
+    sigset_t set;
+    sigfillset(&set);
+    pthread_sigmask(SIG_SETMASK, &set, NULL);
+#endif  // !_WIN32
+
+    if (!emulator_initUserInterface(opts, &uiEmuAgent)) {
+        return 1;
+    }
+
+    skin_winsys_spawn_thread(opts->no_window, enter_qemu_main_loop, n, (char**)args);
+    skin_winsys_enter_main_loop(opts->no_window, argc, argv);
+
+    emulator_finiUserInterface();
+
+    process_late_teardown();
+    return 0;
+}
diff --git a/android-qemu2-glue/net-android.cpp b/android-qemu2-glue/net-android.cpp
new file mode 100644
index 0000000..d557089
--- /dev/null
+++ b/android-qemu2-glue/net-android.cpp
@@ -0,0 +1,91 @@
+// 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 "net-android.h"
+#include "android/android.h"
+#include "android/network/constants.h"
+#include "android/network/globals.h"
+#include "android/telephony/modem_driver.h"
+#include "android/shaper.h"
+
+extern "C" {
+#include "net/net.h"
+}
+
+#if defined(CONFIG_SLIRP)
+static void* s_slirp_state = nullptr;
+static void* s_net_client_state = nullptr;
+static Slirp* s_slirp = nullptr;
+
+static void
+android_net_delay_in_cb(void* data, size_t size, void* opaque)
+{
+    slirp_input(s_slirp, static_cast<const uint8_t*>(data), size);
+}
+
+static void
+android_net_shaper_in_cb(void* data, size_t size, void* opaque)
+{
+    netdelay_send_aux(android_net_delay_in, data, size, opaque);
+}
+
+static void
+android_net_shaper_out_cb(void* data, size_t size, void* opaque)
+{
+    qemu_send_packet(static_cast<NetClientState*>(s_net_client_state),
+                     static_cast<const uint8_t*>(data),
+                     size);
+}
+
+void
+slirp_init_shapers(void* slirp_state, void* net_client_state, Slirp* slirp)
+{
+    s_slirp_state = slirp_state;
+    s_net_client_state = net_client_state;
+    s_slirp = slirp;
+    android_net_delay_in = netdelay_create(android_net_delay_in_cb);
+    android_net_shaper_in = netshaper_create(1, android_net_shaper_in_cb);
+    android_net_shaper_out = netshaper_create(1, android_net_shaper_out_cb);
+
+    netdelay_set_latency(android_net_delay_in, android_net_min_latency,
+                         android_net_max_latency);
+    netshaper_set_rate(android_net_shaper_out, android_net_download_speed);
+    netshaper_set_rate(android_net_shaper_in, android_net_upload_speed);
+}
+#endif  // CONFIG_SLIRP
+
+int
+android_parse_network_speed(const char*  speed)
+{
+    double upload = 0., download = 0.;
+    if (!android_network_speed_parse(speed, &upload, &download)) {
+        return -1;
+    }
+
+    android_net_upload_speed = upload;
+    android_net_download_speed = download;
+
+    return 0;
+}
+
+
+int
+android_parse_network_latency(const char*  delay)
+{
+    double min_delay_ms = 0., max_delay_ms = 0.;
+    if (!android_network_latency_parse(delay, &min_delay_ms, &max_delay_ms)) {
+        return -1;
+    }
+    android_net_min_latency = (int)min_delay_ms;
+    android_net_max_latency = (int)max_delay_ms;
+
+    return 0;
+}
diff --git a/android-qemu2-glue/net-android.h b/android-qemu2-glue/net-android.h
new file mode 100644
index 0000000..693d87e
--- /dev/null
+++ b/android-qemu2-glue/net-android.h
@@ -0,0 +1,27 @@
+// 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 "config-host.h"
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+#if defined(CONFIG_SLIRP)
+#include "libslirp.h"
+
+void slirp_init_shapers(void* slirp_state,
+                        void* net_client_state,
+                        Slirp *slirp);
+#endif  // CONFIG_SLIRP
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/qemu-battery-agent-impl.c b/android-qemu2-glue/qemu-battery-agent-impl.c
new file mode 100644
index 0000000..bf713c5
--- /dev/null
+++ b/android-qemu2-glue/qemu-battery-agent-impl.c
@@ -0,0 +1,130 @@
+/* Copyright (C) 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/qemu-control-impl.h"
+
+#include "android/emulation/control/battery_agent.h"
+#include "qemu/typedefs.h"
+#include "hw/misc/goldfish_battery.h"
+
+static void battery_setIsBatteryPresent(bool isPresent) {
+    goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, isPresent);
+}
+
+static bool battery_present() {
+    return (bool)goldfish_battery_read_prop(POWER_SUPPLY_PROP_PRESENT);
+}
+
+static void battery_setIsCharging(bool isCharging) {
+    goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, isCharging);
+}
+
+static bool battery_charging() {
+    return (bool)goldfish_battery_read_prop(POWER_SUPPLY_PROP_ONLINE);
+}
+
+static void battery_setCharger(enum BatteryCharger charger) {
+    battery_setIsCharging( charger != BATTERY_CHARGER_NONE );
+
+    // TODO: Need to save the full enum and convey it to the AVD
+}
+
+static enum BatteryCharger battery_charger() {
+    return ( battery_charging() ? BATTERY_CHARGER_AC : BATTERY_CHARGER_NONE );
+    // TODO: Need to get the full enum from the AVD
+}
+
+static void battery_setChargeLevel(int percentFull) {
+    goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, percentFull);
+}
+
+static int battery_chargeLevel() {
+    return goldfish_battery_read_prop(POWER_SUPPLY_PROP_CAPACITY);
+}
+
+static void battery_setHealth(enum BatteryHealth health) {
+    int value;
+
+    switch (health) {
+        case BATTERY_HEALTH_GOOD:          value = POWER_SUPPLY_HEALTH_GOOD;            break;
+        case BATTERY_HEALTH_FAILED:        value = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;  break;
+        case BATTERY_HEALTH_DEAD:          value = POWER_SUPPLY_HEALTH_DEAD;            break;
+        case BATTERY_HEALTH_OVERVOLTAGE:   value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;     break;
+        case BATTERY_HEALTH_OVERHEATED:    value = POWER_SUPPLY_HEALTH_OVERHEAT;        break;
+        case BATTERY_HEALTH_UNKNOWN:       value = POWER_SUPPLY_HEALTH_UNKNOWN;         break;
+
+        default:                           value = POWER_SUPPLY_HEALTH_UNKNOWN;         break;
+    }
+
+    goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, value);
+}
+
+static enum BatteryHealth battery_health() {
+    switch ( goldfish_battery_read_prop(POWER_SUPPLY_PROP_HEALTH) ) {
+        case POWER_SUPPLY_HEALTH_GOOD:           return BATTERY_HEALTH_GOOD;
+        case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: return BATTERY_HEALTH_FAILED;
+        case POWER_SUPPLY_HEALTH_DEAD:           return BATTERY_HEALTH_DEAD;
+        case POWER_SUPPLY_HEALTH_OVERVOLTAGE:    return BATTERY_HEALTH_OVERVOLTAGE;
+        case POWER_SUPPLY_HEALTH_OVERHEAT:       return BATTERY_HEALTH_OVERHEATED;
+        case POWER_SUPPLY_HEALTH_UNKNOWN:        return BATTERY_HEALTH_UNKNOWN;
+
+        default:                                 return BATTERY_HEALTH_UNKNOWN;
+    }
+}
+
+static void battery_setStatus(enum BatteryStatus status) {
+    int value;
+
+    switch (status) {
+        case BATTERY_STATUS_UNKNOWN:       value = POWER_SUPPLY_STATUS_UNKNOWN;       break;
+        case BATTERY_STATUS_CHARGING:      value = POWER_SUPPLY_STATUS_CHARGING;      break;
+        case BATTERY_STATUS_DISCHARGING:   value = POWER_SUPPLY_STATUS_DISCHARGING;   break;
+        case BATTERY_STATUS_NOT_CHARGING:  value = POWER_SUPPLY_STATUS_NOT_CHARGING;  break;
+        case BATTERY_STATUS_FULL:          value = POWER_SUPPLY_STATUS_FULL;          break;
+
+        default:                           value = POWER_SUPPLY_STATUS_UNKNOWN;       break;
+    }
+
+    goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, value);
+}
+
+static enum BatteryStatus battery_status() {
+    switch ( goldfish_battery_read_prop(POWER_SUPPLY_PROP_STATUS) ) {
+        case POWER_SUPPLY_STATUS_UNKNOWN:       return BATTERY_STATUS_UNKNOWN;
+        case POWER_SUPPLY_STATUS_CHARGING:      return BATTERY_STATUS_CHARGING;
+        case POWER_SUPPLY_STATUS_DISCHARGING:   return BATTERY_STATUS_DISCHARGING;
+        case POWER_SUPPLY_STATUS_NOT_CHARGING:  return BATTERY_STATUS_NOT_CHARGING;
+        case POWER_SUPPLY_STATUS_FULL:          return BATTERY_STATUS_FULL;
+
+        default:                                return BATTERY_STATUS_UNKNOWN;
+    }
+}
+
+typedef void (*BatteryDisplayCb)(void* opaque, LineConsumerCallback outputCallback);
+
+static const QAndroidBatteryAgent sQAndroidBatteryAgent = {
+        .setIsBatteryPresent = battery_setIsBatteryPresent,
+        .present = battery_present,
+        .setIsCharging = battery_setIsCharging,
+        .charging = battery_charging,
+        .setCharger = battery_setCharger,
+        .charger = battery_charger,
+        .setChargeLevel = battery_setChargeLevel,
+        .chargeLevel = battery_chargeLevel,
+        .setHealth = battery_setHealth,
+        .health = battery_health,
+        .setStatus = battery_setStatus,
+        .status = battery_status,
+        .batteryDisplay = (BatteryDisplayCb)goldfish_battery_display_cb
+};
+const QAndroidBatteryAgent* const gQAndroidBatteryAgent =
+        &sQAndroidBatteryAgent;
diff --git a/android-qemu2-glue/qemu-cellular-agent-impl.c b/android-qemu2-glue/qemu-cellular-agent-impl.c
new file mode 100644
index 0000000..94e9295
--- /dev/null
+++ b/android-qemu2-glue/qemu-cellular-agent-impl.c
@@ -0,0 +1,133 @@
+/* Copyright (C) 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/qemu-control-impl.h"
+
+#include "android/android.h"
+#include "android/emulation/control/cellular_agent.h"
+#include "android/network/globals.h"
+#include "android/shaper.h"
+#include "android/telephony/modem_driver.h"
+
+static void cellular_setSignalStrength(int zeroTo31)
+{
+    // (See do_gsm_signal() in android-qemu1-glue/console.c)
+
+    if (android_modem) {
+        if (zeroTo31 <  0) zeroTo31 =  0;
+        if (zeroTo31 > 31) zeroTo31 = 31;
+
+        amodem_set_signal_strength(android_modem, zeroTo31, 99);
+    }
+}
+
+static void cellular_setSignalStrengthProfile(enum CellularSignal signal)
+{
+    // (See do_gsm_signal_profile() in android-qemu1-glue/console.c)
+    if (android_modem) {
+        int signalQuality = -1;
+        switch (signal) {
+            case Cellular_Signal_None: signalQuality = 0; break;
+            case Cellular_Signal_Poor: signalQuality = 1; break;
+            case Cellular_Signal_Moderate: signalQuality = 2; break;
+            case Cellular_Signal_Good: signalQuality = 3; break;
+            case Cellular_Signal_Great: signalQuality = 4; break;
+        }
+        if (signalQuality >= 0) {
+            amodem_set_signal_strength_profile(android_modem, signalQuality);
+        }
+    }
+}
+
+static void cellular_setVoiceStatus(enum CellularStatus voiceStatus)
+{
+    // (See do_gsm_voice() in android-qemu1-glue/console.c)
+    ARegistrationState  state = A_REGISTRATION_UNKNOWN;
+
+    if (android_modem) {
+        switch (voiceStatus) {
+            case Cellular_Stat_Home:          state = A_REGISTRATION_HOME;          break;
+            case Cellular_Stat_Roaming:       state = A_REGISTRATION_ROAMING;       break;
+            case Cellular_Stat_Searching:     state = A_REGISTRATION_SEARCHING;     break;
+            case Cellular_Stat_Denied:        state = A_REGISTRATION_DENIED;        break;
+            case Cellular_Stat_Unregistered:  state = A_REGISTRATION_UNREGISTERED;  break;
+        }
+
+        amodem_set_voice_registration(android_modem, state);
+    }
+}
+
+static void cellular_setDataStatus(enum CellularStatus dataStatus)
+{
+    // (See do_gsm_data() in android-qemu1-glue/console.c)
+    ARegistrationState  state = A_REGISTRATION_UNKNOWN;
+
+    switch (dataStatus) {
+        case Cellular_Stat_Home:          state = A_REGISTRATION_HOME;          break;
+        case Cellular_Stat_Roaming:       state = A_REGISTRATION_ROAMING;       break;
+        case Cellular_Stat_Searching:     state = A_REGISTRATION_SEARCHING;     break;
+        case Cellular_Stat_Denied:        state = A_REGISTRATION_DENIED;        break;
+        case Cellular_Stat_Unregistered:  state = A_REGISTRATION_UNREGISTERED;  break;
+    }
+
+    if (android_modem) {
+        amodem_set_data_registration(android_modem, state);
+    }
+
+    android_net_disable = (state != A_REGISTRATION_HOME    &&
+                        state != A_REGISTRATION_ROAMING );
+}
+
+static void cellular_setStandard(enum CellularStandard cStandard)
+{
+    // (See do_network_speed() in android-qemu1-glue/console.c)
+    char *speedName;
+
+    switch (cStandard) {
+        case Cellular_Std_GSM:    speedName = "gsm";    break;
+        case Cellular_Std_HSCSD:  speedName = "hscsd";  break;
+        case Cellular_Std_GPRS:   speedName = "gprs";   break;
+        case Cellular_Std_EDGE:   speedName = "edge";   break;
+        case Cellular_Std_UMTS:   speedName = "umts";   break;
+        case Cellular_Std_HSDPA:  speedName = "hsdpa";  break;
+        case Cellular_Std_LTE:    speedName = "lte";    break;
+        case Cellular_Std_full:   speedName = "full";   break;
+
+        default:
+            return; // Error
+    }
+
+    // Find this entry in the speed table and set
+    // android_net_download_speed and android_net_upload_speed
+    if (android_parse_network_speed(speedName) < 0) {
+        return;
+    }
+
+    // Tell the network shaper the new rates
+    netshaper_set_rate(android_net_shaper_in,  android_net_download_speed);
+    netshaper_set_rate(android_net_shaper_out, android_net_upload_speed);
+
+    if (android_modem) {
+        // Tell the guest about the new network type.
+        amodem_set_data_network_type(android_modem,
+                                     android_parse_network_type(speedName));
+    }
+}
+
+static const QAndroidCellularAgent sQAndroidCellularAgent = {
+    .setSignalStrength = cellular_setSignalStrength,
+    .setSignalStrengthProfile = cellular_setSignalStrengthProfile,
+    .setVoiceStatus = cellular_setVoiceStatus,
+    .setDataStatus = cellular_setDataStatus,
+    .setStandard = cellular_setStandard};
+const QAndroidCellularAgent* const gQAndroidCellularAgent =
+        &sQAndroidCellularAgent;
diff --git a/android-qemu2-glue/qemu-control-impl.h b/android-qemu2-glue/qemu-control-impl.h
new file mode 100644
index 0000000..a45704f
--- /dev/null
+++ b/android-qemu2-glue/qemu-control-impl.h
@@ -0,0 +1,74 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "android/emulation/control/battery_agent.h"
+#include "android/emulation/control/cellular_agent.h"
+#include "android/emulation/control/display_agent.h"
+#include "android/emulation/control/finger_agent.h"
+#include "android/emulation/control/location_agent.h"
+#include "android/emulation/control/net_agent.h"
+#include "android/emulation/control/sensors_agent.h"
+#include "android/emulation/control/telephony_agent.h"
+#include "android/emulation/control/user_event_agent.h"
+#include "android/emulation/control/vm_operations.h"
+#include "android/emulation/control/window_agent.h"
+
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+// This file contains handles to globally allocated objects implementing various
+// interfaces required by AndroidEmu library in emulation/control/*.
+
+// Defined in .../emulation/control/batter_agent.h
+extern const QAndroidBatteryAgent* const gQAndroidBatteryAgent;
+
+// Defined in android/qemu-cellular-agent.c
+extern const QAndroidCellularAgent* const gQAndroidCellularAgent;
+
+// Defined in android/qemu-finger-agent.c
+extern const QAndroidFingerAgent* const gQAndroidFingerAgent;
+
+// Defined in android/qemu-location-agent.c
+extern const QAndroidLocationAgent* const gQAndroidLocationAgent;
+
+// Defined in android/qemu-sensors-agent.c
+extern const QAndroidSensorsAgent* const gQAndroidSensorsAgent;
+
+// Defined in android/qemu-telephony-agent.c
+extern const QAndroidTelephonyAgent* const gQAndroidTelephonyAgent;
+
+// Defined in android-qemu1-glue/qemu-user-event-agent-impl.c
+extern const QAndroidUserEventAgent* const gQAndroidUserEventAgent;
+
+// Defined in android-qemu1-glue/qemu-net-agent-impl.c
+extern const QAndroidNetAgent* const gQAndroidNetAgent;
+
+// Defined in android-qemu1-glue/qemu-display-agent-impl.cpp
+extern const QAndroidDisplayAgent* const gQAndroidDisplayAgent;
+
+extern const QAndroidEmulatorWindowAgent* const gQAndroidEmulatorWindowAgent;
+
+// Called by hw/android/goldfish/events_device.c to initialize generic event
+// handling.
+// In this QEMU1 specific implementation, we stash away an |opaque| handle the
+// and call a function on the device directly.
+extern void qemu_control_setEventDevice(void* opaque);
+
+// Defined in android/qemu-android-vm-operations.c
+extern const QAndroidVmOperations* const gQAndroidVmOperations;
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/qemu-display-agent-impl.cpp b/android-qemu2-glue/qemu-display-agent-impl.cpp
new file mode 100644
index 0000000..8559da5
--- /dev/null
+++ b/android-qemu2-glue/qemu-display-agent-impl.cpp
@@ -0,0 +1,91 @@
+// Copyright 2015 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 "android-qemu2-glue/qemu-control-impl.h"
+
+extern "C" {
+    #include "ui/console.h"
+}
+
+static void getFrameBuffer(int* w, int* h, int* lineSize, int* bytesPerPixel,
+                           uint8_t** frameBufferData) {
+    // find the first graphics console
+    QemuConsole* con = nullptr;
+    for (int i = 0;; i++) {
+        QemuConsole* c = qemu_console_lookup_by_index(i);
+        if (!c) {
+            break;
+        }
+        if (qemu_console_is_graphic(c)) {
+            con = c;
+            break;
+        }
+    }
+    if (!con) {
+        return;
+    }
+
+    DisplaySurface* const ds = qemu_console_surface(con);
+
+    if (w) {
+        *w = surface_width(ds);
+    }
+    if (h) {
+        *h = surface_height(ds);
+    }
+    if (lineSize) {
+        *lineSize = surface_stride(ds);
+    }
+    if (bytesPerPixel) {
+        *bytesPerPixel = surface_bytes_per_pixel(ds);
+    }
+    if (frameBufferData) {
+        *frameBufferData = (uint8_t*)surface_data(ds);
+    }
+}
+
+namespace {
+    struct dul_data {
+        AndroidDisplayUpdateCallback callback;
+        void* opaque;
+    };
+}
+
+static void on_display_update(DisplayUpdateListener* dul,
+        int x, int y, int w, int h) {
+    dul_data* data = static_cast<dul_data*>(dul->opaque);
+    data->callback(data->opaque, x, y, w, h);
+}
+
+static void registerUpdateListener(AndroidDisplayUpdateCallback callback,
+                                   void* opaque) {
+    const auto listener = new DisplayUpdateListener();
+    *listener = DisplayUpdateListener();
+    listener->dpy_gfx_update = &on_display_update;
+
+    auto data = new dul_data();
+    data->callback = callback;
+    data->opaque = opaque;
+    listener->opaque = data;
+
+    register_displayupdatelistener(listener);
+}
+
+
+static const QAndroidDisplayAgent displayAgent = {
+        .getFrameBuffer = &getFrameBuffer,
+        .registerUpdateListener = &registerUpdateListener
+};
+
+const QAndroidDisplayAgent* const gQAndroidDisplayAgent = &displayAgent;
diff --git a/android-qemu2-glue/qemu-finger-agent-impl.c b/android-qemu2-glue/qemu-finger-agent-impl.c
new file mode 100644
index 0000000..1c32e47
--- /dev/null
+++ b/android-qemu2-glue/qemu-finger-agent-impl.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 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-qemu1-glue/qemu-control-impl.h"
+
+#include "android/emulation/control/finger_agent.h"
+#include "android/hw-fingerprint.h"
+
+static void finger_setTouch(bool isTouching, int touchId)
+{
+    if (isTouching) {
+        android_hw_fingerprint_touch(touchId);
+    } else {
+        android_hw_fingerprint_remove();
+    }
+}
+
+static const QAndroidFingerAgent sQAndroidFingerAgent = {
+    .setTouch = finger_setTouch
+};
+const QAndroidFingerAgent* const gQAndroidFingerAgent = &sQAndroidFingerAgent;
diff --git a/android-qemu2-glue/qemu-location-agent-impl.c b/android-qemu2-glue/qemu-location-agent-impl.c
new file mode 100644
index 0000000..b362272
--- /dev/null
+++ b/android-qemu2-glue/qemu-location-agent-impl.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 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/qemu-control-impl.h"
+
+#include "android/emulation/control/location_agent.h"
+#include "android/gps.h"
+
+#include <stdbool.h>
+
+static bool location_gpsIsSupported() {
+    return android_gps_serial_line != NULL;
+}
+
+static const QAndroidLocationAgent sQAndroidLocationAgent = {
+        .gpsIsSupported = location_gpsIsSupported,
+        .gpsSendLoc = android_gps_send_location,
+        .gpsGetLoc = android_gps_get_location,
+        .gpsSendNmea = android_gps_send_nmea};
+const QAndroidLocationAgent* const gQAndroidLocationAgent =
+        &sQAndroidLocationAgent;
diff --git a/android-qemu2-glue/qemu-net-agent-impl.c b/android-qemu2-glue/qemu-net-agent-impl.c
new file mode 100644
index 0000000..8297ba9
--- /dev/null
+++ b/android-qemu2-glue/qemu-net-agent-impl.c
@@ -0,0 +1,53 @@
+// Copyright 2015 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 "android/emulation/control/net_agent.h"
+
+#include "android/utils/sockets.h"
+#include "qemu/sockets.h"
+#include "net/slirp.h"
+
+#ifdef CONFIG_SLIRP
+#include "libslirp.h"
+
+static bool isSlirpInited() {
+    return net_slirp_is_inited() != 0;
+}
+
+static bool slirpRedir(bool isUdp, int hostPort,
+                      uint32_t guestAddr, int guestPort) {
+    struct in_addr host = { .s_addr = htonl(SOCK_ADDRESS_INET_LOOPBACK) };
+    struct in_addr guest = { .s_addr = guestAddr };
+    return slirp_add_hostfwd(net_slirp_lookup(NULL, NULL, NULL), isUdp,
+                             host, hostPort, guest, guestPort) == 0;
+}
+
+bool slirpUnredir(bool isUdp, int hostPort) {
+    struct in_addr host = { .s_addr = htonl(SOCK_ADDRESS_INET_LOOPBACK) };
+    return slirp_remove_hostfwd(net_slirp_lookup(NULL, NULL, NULL), isUdp,
+                                host, hostPort) == 0;
+}
+
+
+static const QAndroidNetAgent netAgent = {
+        .isSlirpInited = &isSlirpInited,
+        .slirpRedir = &slirpRedir,
+        .slirpUnredir = &slirpUnredir
+};
+const QAndroidNetAgent* const gQAndroidNetAgent = &netAgent;
+
+#else
+const QAndroidNetAgent* const gQAndroidNetAgent = NULL;
+
+#endif
diff --git a/android-qemu2-glue/qemu-sensors-agent-impl.c b/android-qemu2-glue/qemu-sensors-agent-impl.c
new file mode 100644
index 0000000..21aefdd
--- /dev/null
+++ b/android-qemu2-glue/qemu-sensors-agent-impl.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 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/emulation/control/sensors_agent.h"
+
+#include "android/hw-sensors.h"
+
+int sensor_set(int sensorId, float a, float b, float c) {
+    return android_sensors_set(sensorId, a, b, c);
+}
+
+int sensor_get(int sensorId, float *a, float *b, float *c) {
+    return android_sensors_get(sensorId, a, b, c);
+}
+
+static const QAndroidSensorsAgent sQAndroidSensorsAgent = {
+    .setSensor = sensor_set,
+    .getSensor = sensor_get};
+const QAndroidSensorsAgent* const gQAndroidSensorsAgent =
+    &sQAndroidSensorsAgent;
diff --git a/android-qemu2-glue/qemu-setup.cpp b/android-qemu2-glue/qemu-setup.cpp
new file mode 100644
index 0000000..bca9add
--- /dev/null
+++ b/android-qemu2-glue/qemu-setup.cpp
@@ -0,0 +1,48 @@
+// Copyright 2015 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 "android-qemu2-glue/qemu-setup.h"
+
+#include "android/android.h"
+#include "android/base/Log.h"
+#include "android/console.h"
+#include "android/emulation/AndroidPipe.h"
+#include "android-qemu2-glue/qemu-control-impl.h"
+#include "android-qemu2-glue/emulation/VmLock.h"
+
+extern "C" {
+#include "qemu/main-loop.h"
+}  // extern "C"
+
+using android::VmLock;
+
+bool qemu_android_emulation_setup() {
+    static const AndroidConsoleAgents consoleAgents = {
+            gQAndroidBatteryAgent,
+            gQAndroidFingerAgent,
+            gQAndroidLocationAgent,
+            gQAndroidTelephonyAgent,
+            gQAndroidUserEventAgent,
+            gQAndroidVmOperations,
+            gQAndroidNetAgent
+    };
+
+    VmLock* vmLock = new qemu2::VmLock();
+    VmLock* prevVmLock = VmLock::set(vmLock);
+    CHECK(prevVmLock == nullptr) << "Another VmLock was already installed!";
+
+    android::AndroidPipe::initThreading(vmLock);
+
+    return android_emulation_setup(&consoleAgents);
+}
diff --git a/android-qemu2-glue/qemu-setup.h b/android-qemu2-glue/qemu-setup.h
new file mode 100644
index 0000000..1be84b4
--- /dev/null
+++ b/android-qemu2-glue/qemu-setup.h
@@ -0,0 +1,25 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "android/utils/compiler.h"
+
+#include <stdbool.h>
+
+ANDROID_BEGIN_HEADER
+
+extern bool qemu_android_emulation_setup(void);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/qemu-telephony-agent-impl.c b/android-qemu2-glue/qemu-telephony-agent-impl.c
new file mode 100644
index 0000000..0d7bb0a
--- /dev/null
+++ b/android-qemu2-glue/qemu-telephony-agent-impl.c
@@ -0,0 +1,115 @@
+/* Copyright (C) 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/qemu-control-impl.h"
+
+#include "android/telephony/modem_driver.h"
+#include "android-qemu2-glue/telephony/modem_init.h"
+
+#include <ctype.h>
+#include <stdio.h>
+
+static int gsm_number_is_bad(const char*);
+
+static TelephonyResponse telephony_telephonyCmd(TelephonyOperation op,
+                                                const char *phoneNumber)
+{
+    int resp;
+    int holdCommand;
+
+    switch (op) {
+        case Tel_Op_Init_Call:
+            if (gsm_number_is_bad(phoneNumber)) {
+                return Tel_Resp_Bad_Number;
+            }
+
+            if (!android_modem) {
+                printf("%s: Do not have an Android modem\n", __FILE__);
+                return Tel_Resp_Action_Failed;
+            }
+
+            amodem_add_inbound_call(android_modem, phoneNumber);
+            return Tel_Resp_OK;
+
+        case Tel_Op_Accept_Call:
+        case Tel_Op_Reject_Call_Explicit:
+        case Tel_Op_Reject_Call_Busy:
+            printf("===== telephony-agents-impl.c: Operation is not implemented\n"); // ??
+
+        case Tel_Op_Disconnect_Call:
+            if (gsm_number_is_bad(phoneNumber)) {
+                return Tel_Resp_Bad_Number;
+            }
+
+            if (!android_modem) {
+                printf("%s: Do not have an Android modem\n", __FILE__);
+                return Tel_Resp_Action_Failed;
+            }
+
+            resp = amodem_disconnect_call(android_modem, phoneNumber);
+            return (resp < 0) ? Tel_Resp_Invalid_Action : Tel_Resp_OK;
+
+        case Tel_Op_Place_Call_On_Hold:
+        case Tel_Op_Take_Call_Off_Hold:
+            if (gsm_number_is_bad(phoneNumber)) {
+                return Tel_Resp_Bad_Number;
+            }
+
+            if (!android_modem) {
+                printf("%s: Do not have an Android modem\n", __FILE__);
+                return Tel_Resp_Action_Failed;
+            }
+
+            holdCommand = (op == Tel_Op_Place_Call_On_Hold) ? A_CALL_HELD : A_CALL_ACTIVE;
+            resp = amodem_update_call(android_modem, phoneNumber, holdCommand);
+
+            return (resp < 0) ? Tel_Resp_Invalid_Action : Tel_Resp_OK;
+
+        default:
+            return Tel_Resp_Bad_Operation;
+    }
+}
+
+
+// TODO: This is very similar to 'gsm_check_number' in android-qemu1-glue/console.c
+//       I should probably instead use sms_address_from_str() in telephony/sms.c
+static int
+gsm_number_is_bad(const char* numStr)
+{
+    int  idx;
+    int  nDigits = 0;
+
+    if (!numStr) return 1;
+
+    for (idx = 0; numStr[idx] != 0; idx++) {
+        int  c = numStr[idx];
+        if ( isdigit(c) ) {
+            nDigits++;
+        } else if (c != '+' && c != '#') {
+            return 1;
+        }
+    }
+
+    return (nDigits <= 0);
+}
+
+static AModem telephony_getModem() {
+    return android_modem;
+}
+
+static const QAndroidTelephonyAgent sQAndroidTelephonyAgent = {
+    .telephonyCmd = &telephony_telephonyCmd,
+    .initModem = &qemu_android_modem_init,
+    .getModem = &telephony_getModem
+};
+const QAndroidTelephonyAgent* const gQAndroidTelephonyAgent =
+        &sQAndroidTelephonyAgent;
diff --git a/android-qemu2-glue/qemu-user-event-agent-impl.c b/android-qemu2-glue/qemu-user-event-agent-impl.c
new file mode 100644
index 0000000..a19f1e1
--- /dev/null
+++ b/android-qemu2-glue/qemu-user-event-agent-impl.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2010-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-qemu1-glue/qemu-control-impl.h"
+
+#include "android/multitouch-screen.h"
+#include "android/utils/debug.h"
+#include "hw/input/goldfish_events.h"
+#include "ui/console.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+
+static void user_event_keycodes(int* kcodes, int count) {
+    int nn;
+    for (nn = 0; nn < count; nn++) {
+        kbd_put_keycode(kcodes[nn] & 0x3ff, (kcodes[nn] & 0x400) != 0);
+    }
+}
+
+static void user_event_key(unsigned code, bool down) {
+    if (code == 0) {
+        return;
+    }
+    if (VERBOSE_CHECK(keys))
+        printf(">> KEY [0x%03x,%s]\n", (code & 0x3ff), down ? "down" : " up ");
+
+    goldfish_event_send(0x01, code, down);
+}
+
+static void user_event_keycode(int code) {
+    kbd_put_keycode(code & 0x3ff, (code & 0x400) != 0);
+}
+
+static void user_event_generic(int type, int code, int value) {
+    goldfish_event_send(type, code, value);
+}
+
+static void user_event_mouse(int dx, int dy, int dz, int buttonsState) {
+    if (VERBOSE_CHECK(keys)) {
+        printf(">> MOUSE [%d %d %d : 0x%04x]\n", dx, dy, dz, buttonsState);
+    }
+
+    kbd_mouse_event(dx, dy, dz, buttonsState);
+}
+
+static void on_new_event(void) {
+    dpy_run_update(NULL);
+}
+
+static const QAndroidUserEventAgent sQAndroidUserEventAgent = {
+        .sendKey = user_event_key,
+        .sendKeyCode = user_event_keycode,
+        .sendKeyCodes = user_event_keycodes,
+        .sendMouseEvent = user_event_mouse,
+        .sendGenericEvent = user_event_generic,
+        .onNewUserEvent = on_new_event
+};
+
+const QAndroidUserEventAgent* const gQAndroidUserEventAgent =
+        &sQAndroidUserEventAgent;
+
+static void translate_mouse_event(int x,
+                                  int y,
+                                  int buttons_state) {
+    int pressure = multitouch_is_touch_down(buttons_state) ? 0x81 : 0;
+    int finger = multitouch_is_second_finger(buttons_state);
+    multitouch_update_pointer(MTES_DEVICE, finger, x, y, pressure,
+                              multitouch_should_skip_sync(buttons_state));
+}
+
+const GoldfishEventMultitouchFuncs qemu2_goldfish_event_multitouch_funcs = {
+    .get_max_slot = multitouch_get_max_slot,
+    .translate_mouse_event = translate_mouse_event,
+};
diff --git a/android-qemu2-glue/qemu-vm-operations-impl.c b/android-qemu2-glue/qemu-vm-operations-impl.c
new file mode 100644
index 0000000..8cf1587
--- /dev/null
+++ b/android-qemu2-glue/qemu-vm-operations-impl.c
@@ -0,0 +1,97 @@
+// Copyright 2015 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 "android-qemu2-glue/qemu-control-impl.h"
+
+#include "android/emulation/control/callbacks.h"
+#include "android/emulation/control/vm_operations.h"
+//#include "cpu.h"
+//#include "monitor/monitor.h"
+#include "sysemu/sysemu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+// TODO(zyy@): implement the VM snapshots support
+
+static bool qemu_vm_stop() {
+    vm_stop(RUN_STATE_DEBUG);
+    return true;
+}
+
+static bool qemu_vm_start() {
+    vm_start();
+    return true;
+}
+
+static bool qemu_vm_is_running() {
+    return runstate_is_running() != 0;
+}
+
+static bool qemu_snapshot_list(void* opaque,
+                               LineConsumerCallback outConsumer,
+                               LineConsumerCallback errConsumer) {
+//    Monitor* out = monitor_fake_new(opaque, outConsumer);
+//    Monitor* err = monitor_fake_new(opaque, errConsumer);
+//    do_info_snapshots(out, err);
+//    int ret = monitor_fake_get_bytes(err);
+//    monitor_fake_free(err);
+//    monitor_fake_free(out);
+//    return !ret;
+    return false;
+}
+
+static bool qemu_snapshot_save(const char* name,
+                               void* opaque,
+                               LineConsumerCallback errConsumer) {
+    //Monitor* err = monitor_fake_new(opaque, errConsumer);
+    //do_savevm(err, name);
+    //int ret = monitor_fake_get_bytes(err);
+    //monitor_fake_free(err);
+    //return !ret;
+    return false;
+}
+
+static bool qemu_snapshot_load(const char* name,
+                               void* opaque,
+                               LineConsumerCallback errConsumer) {
+    //Monitor* err = monitor_fake_new(opaque, errConsumer);
+    //do_loadvm(err, name);
+    //int ret = monitor_fake_get_bytes(err);
+    //monitor_fake_free(err);
+    //return !ret;
+    return false;
+}
+
+static bool qemu_snapshot_delete(const char* name,
+                                 void* opaque,
+                                 LineConsumerCallback errConsumer) {
+    //Monitor* err = monitor_fake_new(opaque, errConsumer);
+    //do_delvm(err, name);
+    //int ret = monitor_fake_get_bytes(err);
+    //monitor_fake_free(err);
+    //return !ret;
+    return false;
+}
+
+static const QAndroidVmOperations sQAndroidVmOperations = {
+    .vmStop = qemu_vm_stop,
+    .vmStart = qemu_vm_start,
+    .vmIsRunning = qemu_vm_is_running,
+    .snapshotList = qemu_snapshot_list,
+    .snapshotLoad = qemu_snapshot_load,
+    .snapshotSave = qemu_snapshot_save,
+    .snapshotDelete = qemu_snapshot_delete
+};
+const QAndroidVmOperations * const gQAndroidVmOperations = &sQAndroidVmOperations;
diff --git a/android-qemu2-glue/qemu-window-agent-impl.c b/android-qemu2-glue/qemu-window-agent-impl.c
new file mode 100644
index 0000000..9687956
--- /dev/null
+++ b/android-qemu2-glue/qemu-window-agent-impl.c
@@ -0,0 +1,24 @@
+// Copyright 2015 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 "android/emulation/control/window_agent.h"
+#include "android/skin/ui.h"
+
+static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
+    .getEmulatorWindow = emulator_window_get
+};
+
+const QAndroidEmulatorWindowAgent* const gQAndroidEmulatorWindowAgent =
+    &sQAndroidEmulatorWindowAgent;
+
diff --git a/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py b/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py
new file mode 100755
index 0000000..0404ba8
--- /dev/null
+++ b/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+
+# This script is used to generate Makefile.qemu2-sources.mk from
+# the build output of build-qemu-android.sh. To use it:
+#
+#  rm -rf /tmp/qemu2-build
+#  external/qemu/android/scripts/build-qemu-android.sh \
+#      --darwin-ssh=<hostname> \
+#      --install-dir=/tmp/qemu2-build
+#
+#  external/qemu-android/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py \
+#      /tmp/qemu2-build \
+#      > external/qemu-android/android-qemu2-glue/build/Makefile.qemu2-sources.mk
+#
+import os
+import sys
+
+TARGET_SUFFIX="-softmmu"
+
+EXPECTED_HOSTS = set([
+    'linux-x86_64',
+    'windows-x86',
+    'windows-x86_64',
+    'darwin-x86_64'])
+
+LINK_QEMU_PREFIX = 'LINK-qemu-system-'
+IGNORED_OBJECTS = [
+    '../audio/sdlaudio.o',
+    '../disas/arm-a64.o',
+    '../disas/libvixl/a64/decoder-a64.o',
+    '../disas/libvixl/a64/disasm-a64.o',
+    '../disas/libvixl/a64/instructions-a64.o',
+    '../disas/libvixl/utils.o',
+    'gdbstub-xml.o',
+    '../hw/display/framebuffer.o',
+    'hw/misc/android_boot_properties.o',
+    'hw/misc/android_pipe_opengles.o',
+    '../qmp-marshal.o',
+    'trace/generated-helpers.o',
+    '../ui/sdl_zoom.o',
+    '../ui/sdl.o',
+    '../ui/sdl2.o',
+    '/version.o',   # something from the Windows build
+    ]
+
+CC_OBJECTS = [
+    'disas/arm-a64.o',
+    'disas/libvixl/a64/decoder-a64.o',
+    'disas/libvixl/a64/disasm-a64.o',
+    'disas/libvixl/a64/instructions-a64.o',
+    'disas/libvixl/utils.o',
+    ]
+
+# objects which have to be moved to *TARGET files,
+# even if they could've been common (e.g. to fix some linking issues)
+FORCE_TARGET_OBJECTS = [
+    '../vl.o'
+    ]
+
+def find_target_lists(build_path, hosts):
+    """Return a set of QEMU cpu architectures targetted by the binaries
+       found under |build_path|. |hosts| is a set of hosts to probe for"""
+    result = set()
+    for host in hosts:
+        for subdir, dirs, files in os.walk(os.path.join(build_path,host)):
+            for efile in files:
+                if efile.startswith(LINK_QEMU_PREFIX):
+                    arch = efile[len(LINK_QEMU_PREFIX):]
+                    if arch[-5:] == 'w.exe':
+                        arch = arch[:-5]
+                    result.add(arch)
+            dirs = []
+    return sorted(result)
+
+def find_link_map(build_path, host):
+    """Return a map of target architecture -> set of object file names
+       as they appear in LINK-qemu-system-* files. |build_path| is the
+       top-level build path, and |host| is the host to probe."""
+    result = {}
+    build_path = os.path.join(build_path, host)
+    link_prefix = 'LINK-qemu-system-'
+    for subdir, dirs, files in os.walk(build_path):
+        for efile in files:
+            if efile.startswith(link_prefix):
+                target = efile[len(link_prefix):]
+                # Remove w.exe suffix for Windows binaries.
+                if target[-5:] == 'w.exe':
+                    target = target[:-5]
+                result[target] = set()
+                with open(os.path.join(subdir,efile)) as lfile:
+                    for line in lfile:
+                        line = line.strip()
+                        if line[-2:] in [ '.o', '.a' ]:
+                            result[target].add(line)
+        dirs = []
+    return result
+
+def list_files(name, files):
+    print "%s := \\" % name
+
+    for f in sorted(source_list_from_objects(files)):
+        print "    %s \\" % f
+    print ""
+
+
+def source_list_from_objects(objects):
+    result = set()
+    for obj in objects:
+        if obj in IGNORED_OBJECTS:
+            continue
+        if obj.startswith('@BUILD_DIR@/'):
+            continue
+        if obj.endswith('.a'):
+            continue
+        if obj.startswith('../'):
+            obj = obj[3:]
+        if obj in CC_OBJECTS:
+            obj = obj[:-2] + '.cc'
+        else:
+            obj = obj[:-2] + '.c'
+        result.add(obj)
+    return sorted(result)
+
+def main(args):
+    """\
+A small script used to generate the sub-Makefiles
+describing the common and target-specific sources
+for the QEMU2 build performed with the emulator's
+build system. This is done by looking at the output
+of a regular QEMU2 build, and finding which files
+were built and where.
+
+Usage: <program-name> <path-to-build-dir>
+
+"""
+    if len(args) != 2:
+        print "ERROR: This script takes a single argument."
+        sys.exit(1)
+    build_dir = args[1]
+
+    print "# Auto-generated by %s - DO NOT EDIT !!" % os.path.basename(args[0])
+    print ""
+
+    target_list = find_target_lists(build_dir, EXPECTED_HOSTS)
+    #print "# Found targets: %s" % repr(target_list)
+
+    host_link_map = {}
+    for host in EXPECTED_HOSTS:
+        host_link_map[host] = find_link_map(build_dir, host)
+
+    host_list = sorted(host_link_map.keys())
+    # The set of all objects
+    all_objects = set()
+    for host in host_list:
+        for target in host_link_map[host]:
+            all_objects |= host_link_map[host][target]
+
+    # The set of all objects whose path begins with ../
+    # this corresponds to objects that will end up in the qemu2_common
+    # static library.
+    common_all_objects = set([x for x in all_objects if x.startswith('../')])
+
+    # move the forced target object out of common
+    common_all_objects -= set(FORCE_TARGET_OBJECTS)
+
+    # The set of common objects that are shared by all hosts.
+    common_objects = common_all_objects.copy()
+    for host in host_list:
+        for target in host_link_map[host]:
+            common_objects &= host_link_map[host][target]
+
+    list_files('QEMU2_COMMON_SOURCES', common_objects)
+
+    # For each host, the specific common objects that are not shared with
+    # all other hosts, but still shared by all targets.
+    host_common_map = {}
+    for host in host_list:
+        host_common_map[host] = common_all_objects - common_objects
+        for target in host_link_map[host]:
+            host_common_map[host] &= host_link_map[host][target]
+        list_files('QEMU2_COMMON_SOURCES_%s' % host, host_common_map[host])
+
+    # The set of all target-specifc objects.
+    all_target_objects = all_objects - common_objects
+    for host in host_list:
+        all_target_objects -= host_common_map[host]
+
+    # Find the list of target files that are shared by all targets and all
+    # hosts at the same time.
+    target_common_map = {}
+    for target in target_list:
+        target_common_map[target] = all_target_objects.copy()
+        for host in host_list:
+            target_common_map[target] &= host_link_map[host][target]
+
+    target_common_objects = all_target_objects.copy()
+    for target in target_common_map:
+        target_common_objects &= target_common_map[target]
+
+    list_files('QEMU2_TARGET_SOURCES', target_common_objects)
+
+    # For each target, find the files shared by all hosts, that only
+    # belong to this target.
+    for target in target_list:
+        target_objects = target_common_map[target] - target_common_objects
+        list_files('QEMU2_TARGET_%s_SOURCES' % target, target_objects)
+
+    # Finally, the target- and host- specific objects.
+    for target in target_list:
+        for host in host_list:
+            objects = host_link_map[host][target] - target_common_map[target] - \
+                      target_common_objects - common_all_objects
+            list_files('QEMU2_TARGET_%s_SOURCES_%s' % (target, host), objects)
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/android-qemu2-glue/telephony/modem_init.c b/android-qemu2-glue/telephony/modem_init.c
new file mode 100644
index 0000000..0377c25
--- /dev/null
+++ b/android-qemu2-glue/telephony/modem_init.c
@@ -0,0 +1,53 @@
+// 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/telephony/modem_init.h"
+
+#include "android/telephony/modem_driver.h"
+#include "android-qemu2-glue/utils/stream.h"
+
+#include "hw/hw.h"
+
+#define MODEM_DEV_STATE_SAVE_VERSION 1
+
+static void modem_state_save(QEMUFile* file, void* opaque)
+{
+    Stream* const s = stream_from_qemufile(file);
+    amodem_state_save((AModem)opaque, (SysFile*)s);
+    stream_free(s);
+}
+
+static int modem_state_load(QEMUFile* file, void* opaque, int version_id)
+{
+    if (version_id != MODEM_DEV_STATE_SAVE_VERSION)
+        return -1;
+
+    Stream* const s = stream_from_qemufile(file);
+    const int res = amodem_state_load((AModem)opaque, (SysFile*)s);
+    stream_free(s);
+
+    return res;
+}
+
+
+void qemu_android_modem_init(int base_port) {
+    android_modem_init(base_port);
+
+    if (android_modem_serial_line != NULL) {
+        register_savevm(NULL,
+                        "android_modem",
+                        0,
+                        MODEM_DEV_STATE_SAVE_VERSION,
+                        modem_state_save,
+                        modem_state_load,
+                        android_modem);
+    }
+}
diff --git a/android-qemu2-glue/telephony/modem_init.h b/android-qemu2-glue/telephony/modem_init.h
new file mode 100644
index 0000000..688c911
--- /dev/null
+++ b/android-qemu2-glue/telephony/modem_init.h
@@ -0,0 +1,20 @@
+// 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/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+/* must be called before the VM runs if there is a modem to emulate */
+extern void qemu_android_modem_init(int base_port);
+
+ANDROID_END_HEADER
diff --git a/android-qemu2-glue/utils/stream.cpp b/android-qemu2-glue/utils/stream.cpp
new file mode 100644
index 0000000..0802e9b
--- /dev/null
+++ b/android-qemu2-glue/utils/stream.cpp
@@ -0,0 +1,25 @@
+// 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/utils/stream.h"
+
+#include "android/base/files/Stream.h"
+#include "android-qemu2-glue/base/files/QemuFileStream.h"
+
+using android::qemu::QemuFileStream;
+typedef ::Stream CStream;
+
+CStream* stream_from_qemufile(QEMUFile* file) {
+    if (!file) {
+        return NULL;
+    }
+    return reinterpret_cast<CStream*>(new QemuFileStream(file));
+}
diff --git a/android-qemu2-glue/utils/stream.h b/android-qemu2-glue/utils/stream.h
new file mode 100644
index 0000000..712ce0e
--- /dev/null
+++ b/android-qemu2-glue/utils/stream.h
@@ -0,0 +1,28 @@
+// 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/utils/compiler.h"
+#include "android/utils/stream.h"
+
+ANDROID_BEGIN_HEADER
+
+// this pure C header has to be under 'extern "C"' for a C++ code
+#include "qemu/typedefs.h"
+
+// Create a new Stream instance that wraps a QEMUFile instance.
+// This allows one to use it with other stream_xxx() functions
+// defined in "android/utils/stream.h"
+// |file| is a QEMUFile instance. Returns a new Stream instance.
+Stream* stream_from_qemufile(QEMUFile* file);
+
+ANDROID_END_HEADER