diff --git a/src/AndroidDesktop.cpp b/src/AndroidDesktop.cpp
new file mode 100644
index 0000000..a37500c
--- /dev/null
+++ b/src/AndroidDesktop.cpp
@@ -0,0 +1,340 @@
+#define LOG_TAG "AndroidDesktop"
+#include <utils/Log.h>
+
+#include <fcntl.h>
+#include <sys/eventfd.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <ui/DisplayInfo.h>
+
+#include <rfb/PixelFormat.h>
+#include <rfb/Rect.h>
+#include <rfb/ScreenSet.h>
+#include <rfb/VNCServerST.h>
+
+#include "AndroidDesktop.h"
+#include "InputDevice.h"
+
+using namespace vncflinger;
+using namespace android;
+
+const rfb::PixelFormat AndroidDesktop::sRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16);
+
+AndroidDesktop::AndroidDesktop() {
+    mListener = new FrameListener(this);
+    mInputDevice = new InputDevice();
+
+    mEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+    if (mEventFd < 0) {
+        ALOGE("Failed to create event notifier");
+        return;
+    }
+}
+
+AndroidDesktop::~AndroidDesktop() {
+    mInputDevice->stop();
+    close(mEventFd);
+}
+
+void AndroidDesktop::start(rfb::VNCServer* vs) {
+    Mutex::Autolock _l(mMutex);
+
+    sp<ProcessState> self = ProcessState::self();
+    self->startThreadPool();
+
+    mMainDpy = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+    if (updateDisplayProjection() == NO_INIT) {
+        ALOGE("Failed to query display!");
+        return;
+    }
+    mProjectionChanged = false;
+
+    status_t err = createVirtualDisplay();
+    if (err != NO_ERROR) {
+        ALOGE("Failed to create virtual display: err=%d", err);
+        return;
+    }
+
+    mInputDevice->start_async(mWidth, mHeight);
+
+    mServer = (rfb::VNCServerST*)vs;
+
+    updateFBSize(mWidth, mHeight);
+
+    mServer->setPixelBuffer(mPixels.get());
+
+    ALOGV("Desktop is running");
+}
+
+void AndroidDesktop::stop() {
+    Mutex::Autolock _L(mMutex);
+
+    ALOGV("Shutting down");
+
+    mServer->setPixelBuffer(0);
+    destroyVirtualDisplay();
+    mWidth = 0;
+    mHeight = 0;
+}
+
+status_t AndroidDesktop::createVirtualDisplay() {
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&mProducer, &consumer);
+    mCpuConsumer = new CpuConsumer(consumer, 1);
+    mCpuConsumer->setName(String8("vds-to-cpu"));
+    mCpuConsumer->setDefaultBufferSize(mWidth, mHeight);
+    mProducer->setMaxDequeuedBufferCount(4);
+    consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBX_8888);
+
+    mCpuConsumer->setFrameAvailableListener(mListener);
+
+    mDpy = SurfaceComposerClient::createDisplay(String8("VNC-VirtualDisplay"), false /*secure*/);
+
+    // aspect ratio
+    float displayAspect = (float) mSourceHeight / (float) mSourceWidth;
+
+    uint32_t outWidth, outHeight;
+    if (mWidth > (uint32_t)(mWidth * displayAspect)) {
+        // limited by narrow width; reduce height
+        outWidth = mWidth;
+        outHeight = (uint32_t)(mWidth * displayAspect);
+    } else {
+        // limited by short height; restrict width
+        outHeight = mHeight;
+        outWidth = (uint32_t)(mHeight / displayAspect);
+    }
+
+    // position the desktop in the viewport while preserving
+    // the source aspect ratio. we do this in case the client
+    // has resized the window and to deal with orientation
+    // changes set up by updateDisplayProjection
+    uint32_t offX, offY;
+    offX = (mWidth - outWidth) / 2;
+    offY = (mHeight - outHeight) / 2;
+    mDisplayRect = Rect(offX, offY, offX + outWidth, offY + outHeight);
+    Rect sourceRect(0, 0, mSourceWidth, mSourceHeight);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
+    SurfaceComposerClient::setDisplayProjection(mDpy, 0, sourceRect, mDisplayRect);
+    SurfaceComposerClient::setDisplayLayerStack(mDpy, 0);  // default stack
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    mVDSActive = true;
+
+    ALOGV("Virtual display (%lux%lu [viewport=%ux%u] created", mWidth, mHeight,
+            outWidth, outHeight);
+
+    return NO_ERROR;
+}
+
+status_t AndroidDesktop::destroyVirtualDisplay() {
+    if (!mVDSActive) {
+        return NO_INIT;
+    }
+
+    mCpuConsumer.clear();
+    mProducer.clear();
+    SurfaceComposerClient::destroyDisplay(mDpy);
+
+    mVDSActive = false;
+
+    ALOGV("Virtual display destroyed");
+
+    return NO_ERROR;
+}
+
+void AndroidDesktop::processDesktopResize() {
+    if (mProjectionChanged) {
+        destroyVirtualDisplay();
+        createVirtualDisplay();
+        updateFBSize(mWidth, mHeight);
+        mInputDevice->reconfigure(mDisplayRect.getWidth(), mDisplayRect.getHeight());
+        rfb::ScreenSet screens;
+        screens.add_screen(rfb::Screen(0, 0, 0, mWidth, mHeight, 0));
+        mServer->setScreenLayout(screens);
+
+        mProjectionChanged = false;
+    }
+}
+
+void AndroidDesktop::processFrames() {
+    Mutex::Autolock _l(mMutex);
+
+    // do any pending resize
+    processDesktopResize();
+
+    if (!mFrameAvailable) {
+        return;
+    }
+
+    // get a frame from the virtual display
+    CpuConsumer::LockedBuffer imgBuffer;
+    status_t res = mCpuConsumer->lockNextBuffer(&imgBuffer);
+    if (res != OK) {
+        ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
+        return;
+    }
+
+    mFrameNumber = imgBuffer.frameNumber;
+    ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
+          imgBuffer.width, imgBuffer.height, imgBuffer.stride);
+
+    // we don't know if there was a stride change until we get
+    // a buffer from the queue. if it changed, we need to resize
+
+    rfb::Rect bufRect(0, 0, imgBuffer.width, imgBuffer.height);
+
+    // performance is extremely bad if the gpu memory is used
+    // directly without copying because it is likely uncached
+    mPixels->imageRect(bufRect, imgBuffer.data, imgBuffer.stride);
+
+    mCpuConsumer->unlockBuffer(imgBuffer);
+
+    // update clients
+    mServer->add_changed(bufRect);
+    mFrameAvailable = false;
+}
+
+// notifies the server loop that we have changes
+void AndroidDesktop::notify() {
+    static uint64_t notify = 1;
+    write(mEventFd, &notify, sizeof(notify));
+}
+
+// called when a client resizes the window
+unsigned int AndroidDesktop::setScreenLayout(int reqWidth, int reqHeight,
+                                             const rfb::ScreenSet& layout) {
+    Mutex::Autolock _l(mMutex);
+
+    char* dbg = new char[1024];
+    layout.print(dbg, 1024);
+
+    ALOGD("setScreenLayout: cur: %lux%lu  new: %dx%d %s", mWidth, mHeight, reqWidth, reqHeight, dbg);
+    delete[] dbg;
+
+    if (reqWidth == (int)mWidth && reqHeight == (int)mHeight) {
+        return rfb::resultInvalid;
+    }
+
+    if (reqWidth > 0 && reqHeight > 0) {
+        mWidth = reqWidth;
+        mHeight = reqHeight;
+
+        if (updateDisplayProjection() == NO_ERROR) {
+            // resize immediately
+            processDesktopResize();
+            notify();
+            return rfb::resultSuccess;
+        }
+    }
+    return rfb::resultInvalid;
+}
+
+// updates the pixelbuffer dimensions
+bool AndroidDesktop::updateFBSize(uint64_t width, uint64_t height) {
+    if (mPixels == nullptr || mPixels->height() != (int)height || mPixels->width() != (int)width) {
+        if (mPixels != nullptr) {
+            ALOGD("updateFBSize: old=[%dx%d] new=[%lux%lu]", mPixels->width(), mPixels->height(),
+                  width, height);
+        }
+        if (mPixels != nullptr && (int)width <= mPixels->width() &&
+            (int)height <= mPixels->height()) {
+            mPixels->setSize(width, height);
+        } else {
+            mPixels = new AndroidPixelBuffer(width, height);
+            mServer->setPixelBuffer(mPixels.get());
+        }
+        return true;
+    }
+    return false;
+}
+
+// cpuconsumer frame listener, called from binder thread
+void AndroidDesktop::FrameListener::onFrameAvailable(const BufferItem& item) {
+    Mutex::Autolock _l(mDesktop->mMutex);
+    mDesktop->updateDisplayProjection();
+    mDesktop->mFrameAvailable = true;
+    mDesktop->notify();
+    ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
+}
+
+rfb::Point AndroidDesktop::getFbSize() {
+    return rfb::Point(mPixels->width(), mPixels->height());
+}
+
+void AndroidDesktop::keyEvent(rdr::U32 key, bool down) {
+    mInputDevice->keyEvent(down, key);
+}
+
+void AndroidDesktop::pointerEvent(const rfb::Point& pos, int buttonMask) {
+    if (pos.x < mDisplayRect.left || pos.x > mDisplayRect.right ||
+            pos.y < mDisplayRect.top || pos.y > mDisplayRect.bottom) {
+        // outside viewport
+        return;
+    }
+    uint32_t x = pos.x * ((float)(mDisplayRect.getWidth()) / (float)mWidth);
+    uint32_t y = pos.y * ((float)(mDisplayRect.getHeight()) / (float)mHeight);
+
+    ALOGD("pointer xlate x1=%d y1=%d x2=%d y2=%d", pos.x, pos.y, x, y);
+
+    mServer->setCursorPos(rfb::Point(x, y));
+    mInputDevice->pointerEvent(buttonMask, x, y);
+}
+
+// figure out the dimensions of the display. deal with orientation
+// changes, client-side window resize, server-side scaling, and
+// maintaining aspect ratio.
+status_t AndroidDesktop::updateDisplayProjection() {
+    DisplayInfo info;
+    status_t err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &info);
+    if (err != NO_ERROR) {
+        ALOGE("Failed to get display characteristics\n");
+        return err;
+    }
+
+    bool deviceRotated =
+        info.orientation != DISPLAY_ORIENTATION_0 && info.orientation != DISPLAY_ORIENTATION_180;
+
+    // if orientation changed, swap width/height
+    uint32_t sourceWidth, sourceHeight;
+    if (!deviceRotated) {
+        sourceWidth = info.w;
+        sourceHeight = info.h;
+    } else {
+        sourceHeight = info.w;
+        sourceWidth = info.h;
+    }
+
+    if (mWidth == 0 && mHeight == 0) {
+        mWidth = sourceWidth;
+        mHeight = sourceHeight;
+    }
+
+    if (deviceRotated != mRotated) {
+        std::swap(mWidth, mHeight);
+        mRotated = deviceRotated;
+    }
+
+    // if nothing changed, we're done
+    if (mSourceWidth == sourceWidth && mSourceHeight == sourceHeight &&
+        (int)mWidth == mPixels->width() && (int)mHeight == mPixels->height()) {
+        return NO_ERROR;
+    }
+
+    // update all the values and flag for an update
+    mSourceWidth = sourceWidth;
+    mSourceHeight = sourceHeight;
+    mProjectionChanged = true;
+
+    ALOGV("Dimensions: %lux%lu [out: %lux%lu] rotated=%d", mSourceWidth, mSourceHeight, mWidth,
+          mHeight, mRotated);
+
+    return NO_ERROR;
+}
