diff --git a/Android.mk b/Android.mk
index 2f0f786aa34a0f5631903e4620423883c3dc3cb5..2d9707638e7d30cc7392cf86b59a32bc1500cff5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,7 +4,6 @@ include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
     src/InputDevice.cpp \
-    src/VirtualDisplay.cpp \
     src/VNCFlinger.cpp \
     src/main.cpp
 
diff --git a/src/README b/src/README
deleted file mode 100644
index e6cbb2b5ac9f258c93de42592b4469c3d24ecb65..0000000000000000000000000000000000000000
--- a/src/README
+++ /dev/null
@@ -1,2 +0,0 @@
-- The surfaceflinger method is present from version 2.3.X and should be supported by all devices.
-- It connects with the surfaceflinger service through a Binder interface.
diff --git a/src/VNCFlinger.cpp b/src/VNCFlinger.cpp
index efd6cbc9f7c44459951a35daf31a0c8d9223343b..4775d0bdd5d5becd9e32c220e3f92859b2a3186a 100644
--- a/src/VNCFlinger.cpp
+++ b/src/VNCFlinger.cpp
@@ -12,14 +12,26 @@
 #include "InputDevice.h"
 #include "VNCFlinger.h"
 
-using namespace android;
 
-Mutex VNCFlinger::sUpdateMutex;
+using namespace android;
 
 status_t VNCFlinger::start() {
-    Mutex::Autolock _l(mMutex);
+    sp<ProcessState> self = ProcessState::self();
+    self->startThreadPool();
+
+    status_t err = NO_ERROR;
+
+    mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
+            ISurfaceComposer::eDisplayIdMain);
+    err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
+    if (err != NO_ERROR) {
+        ALOGE("Failed to get display characteristics\n");
+        return err;
+    }
+    mHeight = mMainDpyInfo.h;
+    mWidth = mMainDpyInfo.w;
 
-    status_t err = setup_l();
+    err = createVNCServer();
     if (err != NO_ERROR) {
         ALOGE("Failed to start VNCFlinger: err=%d", err);
         return err;
@@ -29,33 +41,77 @@ status_t VNCFlinger::start() {
 
     rfbRunEventLoop(mVNCScreen, -1, true);
 
-    mCondition.wait(mMutex);
+    eventLoop();
 
-    release_l();
     return NO_ERROR;
 }
 
-status_t VNCFlinger::setup_l() {
+void VNCFlinger::eventLoop() {
+    mRunning = true;
 
-    status_t err = NO_ERROR;
+    Mutex::Autolock _l(mEventMutex);
+    while (mRunning) {
+        mEventCond.wait(mEventMutex);
 
-    mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
-            ISurfaceComposer::eDisplayIdMain);
-    err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
-    if (err != NO_ERROR) {
-        ALOGE("Unable to get display characteristics\n");
-        return err;
-    }
+        // spurious wakeup? never.
+        if (mClientCount == 0) {
+            continue;
+        }
 
-    bool rotated = VirtualDisplay::isDeviceRotated(mMainDpyInfo.orientation);
-    if (mWidth == 0) {
-        mWidth = rotated ? mMainDpyInfo.h : mMainDpyInfo.w;
-    }
-    if (mHeight == 0) {
-        mHeight = rotated ? mMainDpyInfo.w : mMainDpyInfo.h;
+        // this is a new client, so fire everything up
+        status_t err = createVirtualDisplay();
+        if (err != NO_ERROR) {
+            ALOGE("Failed to create virtual display: err=%d", err);
+        }
+
+        // loop while clients are connected and process frames
+        // on the main thread when signalled
+        while (mClientCount > 0) {
+            mEventCond.wait(mEventMutex);
+            if (mFrameAvailable) {
+                processFrame();
+                mFrameAvailable = false;
+            }
+        }
+
+        destroyVirtualDisplay();
     }
+}
+
+status_t VNCFlinger::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);
+
+    mListener = new FrameListener(this);
+    mCpuConsumer->setFrameAvailableListener(mListener);
 
-    ALOGD("Display dimensions: %dx%d rotated=%d", mWidth, mHeight, rotated);
+    mDpy = SurfaceComposerClient::createDisplay(
+            String8("VNC-VirtualDisplay"), false /*secure*/);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
+    //setDisplayProjection(mDpy, mainDpyInfo);
+    SurfaceComposerClient::setDisplayLayerStack(mDpy, 0);    // default stack
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    ALOGV("Virtual display created");
+    return NO_ERROR;
+}
+
+status_t VNCFlinger::destroyVirtualDisplay() {
+    mCpuConsumer.clear();
+    mProducer.clear();
+    SurfaceComposerClient::destroyDisplay(mDpy);
+    return NO_ERROR;
+}
+
+status_t VNCFlinger::createVNCServer() {
+
+    status_t err = NO_ERROR;
 
     rfbLog = VNCFlinger::rfbLogger;
     rfbErr = VNCFlinger::rfbLogger;
@@ -88,32 +144,27 @@ status_t VNCFlinger::setup_l() {
     /* Mark as dirty since we haven't sent any updates at all yet. */
     rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
 
-
-    mVirtualDisplay = new VirtualDisplay(mVNCScreen, &sUpdateMutex);
-
     return err;
 }
 
-void VNCFlinger::release_l() {
-    mVirtualDisplay.clear();
+status_t VNCFlinger::stop() {
+    Mutex::Autolock _L(mEventMutex);
 
-    ALOGD("VNCFlinger released");
-}
+    mClientCount = 0;
+    mRunning = false;
 
-status_t VNCFlinger::stop() {
-    Mutex::Autolock _l(mMutex);
-    mCondition.signal();
+    mEventCond.signal();
 
     return NO_ERROR;
 }
 
 size_t VNCFlinger::addClient() {
-    Mutex::Autolock _l(mMutex);
+    Mutex::Autolock _l(mEventMutex);
     if (mClientCount == 0) {
+        mClientCount++;
         InputDevice::start(mWidth, mHeight);
-        mVirtualDisplay->start(mMainDpyInfo);
+        mEventCond.signal();
     }
-    mClientCount++;
 
     ALOGI("Client connected (%zu)", mClientCount);
 
@@ -121,12 +172,12 @@ size_t VNCFlinger::addClient() {
 }
 
 size_t VNCFlinger::removeClient() {
-    Mutex::Autolock _l(mMutex);
+    Mutex::Autolock _l(mEventMutex);
     if (mClientCount > 0) {
         mClientCount--;
         if (mClientCount == 0) {
-            mVirtualDisplay->stop();
             InputDevice::stop();
+            mEventCond.signal();
         }
     }
 
@@ -150,23 +201,18 @@ enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
     return RFB_CLIENT_ACCEPT;
 }
 
-void VNCFlinger::onFrameStart(rfbClientPtr /* cl */) {
-    sUpdateMutex.lock();
+void VNCFlinger::onFrameStart(rfbClientPtr cl) {
+    VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
+    vf->mUpdateMutex.lock();
     ALOGV("frame start");
 }
 
-void VNCFlinger::onFrameDone(rfbClientPtr /* cl */, int status) {
-    sUpdateMutex.unlock();
+void VNCFlinger::onFrameDone(rfbClientPtr cl, int status) {
+    VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
+    vf->mUpdateMutex.unlock();
     ALOGV("frame done! %d", status);
 }
 
-void VNCFlinger::markFrame(void* frame, size_t stride) {
-    Mutex::Autolock _l(sUpdateMutex);
-    mVNCScreen->frameBuffer = (char *)frame;
-    mVNCScreen->paddedWidthInBytes = stride * 4;
-    rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
-}
-
 void VNCFlinger::rfbLogger(const char *format, ...) {
     va_list args;
     char buf[256];
@@ -176,3 +222,51 @@ void VNCFlinger::rfbLogger(const char *format, ...) {
     ALOGI("%s", buf);
     va_end(args);
 }
+
+void VNCFlinger::FrameListener::onFrameAvailable(const BufferItem& item) {
+    Mutex::Autolock _l(mVNC->mEventMutex);
+    mVNC->mFrameAvailable = true;
+    mVNC->mEventCond.signal();
+    ALOGV("onFrameAvailable: mTimestamp=%ld mFrameNumber=%ld",
+            item.mTimestamp, item.mFrameNumber);
+}
+
+void VNCFlinger::processFrame() {
+    ALOGV("processFrame\n");
+
+    // Take the update mutex. This ensures that we don't dequeue
+    // a new buffer and blow away the one being sent to a client.
+    // The BufferQueue is self-regulating and will drop frames
+    // automatically for us.
+    Mutex::Autolock _l(mUpdateMutex);
+
+    CpuConsumer::LockedBuffer imgBuffer;
+    status_t res = mCpuConsumer->lockNextBuffer(&imgBuffer);
+    if (res != OK) {
+        ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
+        return;
+    }
+
+    ALOGV("processFrame: ptr: %p format: %x (%dx%d, stride=%d)",
+            imgBuffer.data, imgBuffer.format, imgBuffer.width,
+            imgBuffer.height, imgBuffer.stride);
+
+    void* vncbuf = mVNCScreen->frameBuffer;
+    void* imgbuf = imgBuffer.data;
+
+    // Copy the frame to the server's buffer
+    if (imgBuffer.stride > mWidth) {
+        // Image has larger stride, so we need to copy row by row
+        for (size_t y = 0; y < mHeight; y++) {
+            memcpy(vncbuf, imgbuf, mWidth * 4);
+            vncbuf = (void *)((char *)vncbuf + mWidth * 4);
+            imgbuf = (void *)((char *)imgbuf + imgBuffer.stride * 4);
+        }
+    } else {
+        memcpy(vncbuf, imgbuf, mWidth * mHeight * 4);
+    }
+
+    rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
+
+    mCpuConsumer->unlockBuffer(imgBuffer);
+}
diff --git a/src/VNCFlinger.h b/src/VNCFlinger.h
index 8c026b9c562cce4225e3b28338f661c53d350da8..4535fb670bf82bb699e1fe30ce4acacd8f961985 100644
--- a/src/VNCFlinger.h
+++ b/src/VNCFlinger.h
@@ -1,8 +1,7 @@
 #ifndef VNCFLINGER_H
 #define VNCFLINGER_H
 
-#include "VirtualDisplay.h"
-
+#include <gui/CpuConsumer.h>
 #include <ui/DisplayInfo.h>
 
 #include "rfb/rfb.h"
@@ -27,39 +26,67 @@ public:
     virtual size_t addClient();
     virtual size_t removeClient();
 
-    virtual void markFrame(void* frame, size_t stride);
 
 private:
 
-    virtual status_t setup_l();
-    virtual void release_l();
+    class FrameListener : public CpuConsumer::FrameAvailableListener {
+    public:
+        FrameListener(VNCFlinger *vnc) : mVNC(vnc) {}
+
+        virtual void onFrameAvailable(const BufferItem& item);
+
+    private:
+        FrameListener(FrameListener&) {}
+        VNCFlinger *mVNC;
+    };
+
+    virtual void eventLoop();
 
+    virtual status_t createVirtualDisplay();
+    virtual status_t destroyVirtualDisplay();
+    virtual status_t createVNCServer();
+
+    virtual void processFrame();
+
+    // vncserver callbacks
     static ClientGoneHookPtr onClientGone(rfbClientPtr cl);
     static enum rfbNewClientAction onNewClient(rfbClientPtr cl);
     static void onFrameStart(rfbClientPtr cl);
     static void onFrameDone(rfbClientPtr cl, int result);
     static void rfbLogger(const char *format, ...);
 
-    Condition mCondition;
+    bool mRunning;
+    bool mFrameAvailable;
+
+    Mutex mEventMutex;
+    Mutex mUpdateMutex;
+
+    Condition mEventCond;
 
     rfbScreenInfoPtr mVNCScreen;
     uint8_t *mVNCBuf;
 
     uint32_t mWidth, mHeight;
-    bool mRotate;
 
     sp<IBinder> mMainDpy;
     DisplayInfo mMainDpyInfo;
-    
-    Mutex mMutex;
-    static Mutex sUpdateMutex;
-
-    sp<VirtualDisplay> mVirtualDisplay;
 
     int mArgc;
     char **mArgv;
 
     size_t mClientCount;
+
+    sp<FrameListener> mListener;
+
+    // Producer side of queue, passed into the virtual display.
+    sp<IGraphicBufferProducer> mProducer;
+
+    // This receives frames from the virtual display and makes them available
+    sp<CpuConsumer> mCpuConsumer;
+
+    // The virtual display instance
+    sp<IBinder> mDpy;
+
 };
 
 };
diff --git a/src/VirtualDisplay.cpp b/src/VirtualDisplay.cpp
deleted file mode 100644
index 27cc00e195880173d797f3397d8b63648be92ba9..0000000000000000000000000000000000000000
--- a/src/VirtualDisplay.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2014 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.
- */
-
-#define LOG_TAG "VNC-VirtualDisplay"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-
-#include <gui/SurfaceComposerClient.h>
-
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-#include <GLES2/gl2ext.h>
-
-#include <ui/Rect.h>
-
-#include "VirtualDisplay.h"
-
-using namespace android;
-
-static const int kGlBytesPerPixel = 4;      // GL_RGBA
-
-
-/*
- * Returns "true" if the device is rotated 90 degrees.
- */
-bool VirtualDisplay::isDeviceRotated(int orientation) {
-    return orientation != DISPLAY_ORIENTATION_0 &&
-            orientation != DISPLAY_ORIENTATION_180;
-}
-
-/*
- * Sets the display projection, based on the display dimensions, video size,
- * and device orientation.
- */
-status_t VirtualDisplay::setDisplayProjection(const sp<IBinder>& dpy,
-        const DisplayInfo& mMainDpyInfo) {
-    status_t err;
-
-    // Set the region of the layer stack we're interested in, which in our
-    // case is "all of it".  If the app is rotated (so that the width of the
-    // app is based on the height of the display), reverse width/height.
-    bool deviceRotated = isDeviceRotated(mMainDpyInfo.orientation);
-    uint32_t sourceWidth, sourceHeight;
-    if (!deviceRotated) {
-        sourceWidth = mMainDpyInfo.w;
-        sourceHeight = mMainDpyInfo.h;
-    } else {
-        ALOGV("using rotated width/height");
-        sourceHeight = mMainDpyInfo.w;
-        sourceWidth = mMainDpyInfo.h;
-    }
-    Rect layerStackRect(sourceWidth, sourceHeight);
-
-    // We need to preserve the aspect ratio of the display.
-    float displayAspect = (float) sourceHeight / (float) sourceWidth;
-
-
-    // Set the way we map the output onto the display surface (which will
-    // be e.g. 1280x720 for a 720p video).  The rect is interpreted
-    // post-rotation, so if the display is rotated 90 degrees we need to
-    // "pre-rotate" it by flipping width/height, so that the orientation
-    // adjustment changes it back.
-    //
-    // We might want to encode a portrait display as landscape to use more
-    // of the screen real estate.  (If players respect a 90-degree rotation
-    // hint, we can essentially get a 720x1280 video instead of 1280x720.)
-    // In that case, we swap the configured video width/height and then
-    // supply a rotation value to the display projection.
-    uint32_t videoWidth, videoHeight;
-    uint32_t outWidth, outHeight;
-   if (!mRotate) {
-        videoWidth = mWidth;
-        videoHeight = mHeight;
-    } else {
-        videoWidth = mHeight;
-        videoHeight = mWidth;
-    }
-    if (videoHeight > (uint32_t)(videoWidth * displayAspect)) {
-        // limited by narrow width; reduce height
-        outWidth = videoWidth;
-        outHeight = (uint32_t)(videoWidth * displayAspect);
-    } else {
-        // limited by short height; restrict width
-        outHeight = videoHeight;
-        outWidth = (uint32_t)(videoHeight / displayAspect);
-    }
-    uint32_t offX, offY;
-    offX = (videoWidth - outWidth) / 2;
-    offY = (videoHeight - outHeight) / 2;
-    Rect displayRect(offX, offY, offX + outWidth, offY + outHeight);
-
-    if (mRotate) {
-        ALOGV("Rotated content area is %ux%u at offset x=%d y=%d\n",
-                outHeight, outWidth, offY, offX);
-    } else {
-        ALOGV("Content area is %ux%u at offset x=%d y=%d\n",
-                outWidth, outHeight, offX, offY);
-    }
-
-    SurfaceComposerClient::setDisplayProjection(dpy,
-            mRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0,
-            layerStackRect, displayRect);
-    return NO_ERROR;
-}
-
-status_t VirtualDisplay::start(const DisplayInfo& mainDpyInfo) {
-
-    Mutex::Autolock _l(mMutex);
-
-    ALOGV("Orientation: %d", mainDpyInfo.orientation);
-    mRotate = isDeviceRotated(mainDpyInfo.orientation);
-    mWidth = mRotate ? mainDpyInfo.h : mainDpyInfo.w;
-    mHeight = mRotate ? mainDpyInfo.w : mainDpyInfo.h;
-
-    sp<ProcessState> self = ProcessState::self();
-    self->startThreadPool();
-
-    run("vnc-virtualdisplay");
-    
-    mState = INIT;
-    while (mState == INIT) {
-        mStartCond.wait(mMutex);
-    }
-  
-    if (mThreadResult != NO_ERROR) {
-        ALOGE("Failed to start VDS thread: err=%d", mThreadResult);
-        return mThreadResult;
-    }
-    assert(mState == RUNNING);
-  
-    mDpy = SurfaceComposerClient::createDisplay(
-            String8("VNCFlinger"), false /*secure*/);
-
-    SurfaceComposerClient::openGlobalTransaction();
-    SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
-    setDisplayProjection(mDpy, mainDpyInfo);
-    SurfaceComposerClient::setDisplayLayerStack(mDpy, 0);    // default stack
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    ALOGV("VirtualDisplay::start successful");
-    return NO_ERROR;
-}
-
-status_t VirtualDisplay::stop() {
-    Mutex::Autolock _l(mMutex);
-    mState = STOPPING;
-    mEventCond.signal();
-    return NO_ERROR;
-}
-  
-bool VirtualDisplay::threadLoop() {
-    Mutex::Autolock _l(mMutex);
-
-    mThreadResult = setup_l();
-
-    if (mThreadResult != NO_ERROR) {
-        ALOGW("Aborting VDS thread");
-        mState = STOPPED;
-        release_l();
-        mStartCond.broadcast();
-        return false;
-    }
-
-    ALOGV("VDS thread running");
-    mState = RUNNING;
-    mStartCond.broadcast();
-
-    while (mState == RUNNING) {
-        mEventCond.wait(mMutex);
-        ALOGD("Awake, frame available");
-        processFrame_l();
-    }
-
-    ALOGV("VDS thread stopping");
-    release_l();
-    mState = STOPPED;
-    return false;       // stop
-}
-
-status_t VirtualDisplay::setup_l() {
-    status_t err;
-
-    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);
-
-    mCpuConsumer->setFrameAvailableListener(this);
-
-    ALOGD("VirtualDisplay::setup_l OK");
-    return NO_ERROR;
-}
-
-void* VirtualDisplay::processFrame_l() {
-    ALOGD("processFrame_l\n");
-
-    mUpdateMutex->lock();
-
-    CpuConsumer::LockedBuffer imgBuffer;
-    status_t res = mCpuConsumer->lockNextBuffer(&imgBuffer);
-    if (res != OK) {
-        ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
-        return nullptr;
-    }
-
-    ALOGV("imgBuffer ptr: %p format: %x (%dx%d, stride=%d)", imgBuffer.data, imgBuffer.format, imgBuffer.width, imgBuffer.height, imgBuffer.stride);
-
-    void* vncbuf = mVNCScreen->frameBuffer;
-    void* imgbuf = imgBuffer.data;
-
-    for (size_t y = 0; y < mHeight; y++) {
-        memcpy(vncbuf, imgbuf, mWidth * 4);
-        vncbuf = (void *)((char *)vncbuf + mWidth * 4);
-        imgbuf = (void *)((char *)imgbuf + imgBuffer.stride * 4);
-    }
-    ALOGD("buf copied");
-    
-    mVNCScreen->frameBuffer = (char *)imgBuffer.data;
-    mVNCScreen->paddedWidthInBytes = imgBuffer.stride * 4;
-    rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
-
-
-    mCpuConsumer->unlockBuffer(imgBuffer);
-    mUpdateMutex->unlock();
-
-    return nullptr;
-}
-
-void VirtualDisplay::release_l() {
-    ALOGD("release_l");
-    mCpuConsumer.clear();
-    mProducer.clear();
-    SurfaceComposerClient::destroyDisplay(mDpy);
-}
-
-// Callback; executes on arbitrary thread.
-void VirtualDisplay::onFrameAvailable(const BufferItem& item) {
-    Mutex::Autolock _l(mMutex);
-    mEventCond.signal();
-    ALOGD("mTimestamp=%ld mFrameNumber=%ld", item.mTimestamp, item.mFrameNumber);
-}
diff --git a/src/VirtualDisplay.h b/src/VirtualDisplay.h
deleted file mode 100644
index 57c2c928bcb7aac8ef8233338c1205cbad3b3cd9..0000000000000000000000000000000000000000
--- a/src/VirtualDisplay.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2014 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.
- */
-
-#ifndef VDS_H
-#define VDS_H
-
-#include <gui/BufferQueue.h>
-#include <gui/CpuConsumer.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <ui/DisplayInfo.h>
-#include <utils/Thread.h>
-
-#include <rfb/rfb.h>
-
-#define NUM_PBO 2
-
-namespace android {
-
-/*
- * Support for "frames" output format.
- */
-class VirtualDisplay : public CpuConsumer::FrameAvailableListener, Thread {
-public:
-    VirtualDisplay(rfbScreenInfoPtr vncScreen, Mutex *updateMutex) : Thread(false),
-        mVNCScreen(vncScreen),
-        mUpdateMutex(updateMutex),
-        mThreadResult(UNKNOWN_ERROR),
-        mState(UNINITIALIZED)
-        {}
-
-    // Create an "input surface", similar in purpose to a MediaCodec input
-    // surface, that the virtual display can send buffers to.  Also configures
-    // EGL with a pbuffer surface on the current thread.
-    virtual status_t start(const DisplayInfo& mainDpyInfo);
-
-    virtual status_t stop();
-
-    static bool isDeviceRotated(int orientation);
-
-private:
-    VirtualDisplay(const VirtualDisplay&);
-    VirtualDisplay& operator=(const VirtualDisplay&);
-
-    // Destruction via RefBase.
-    virtual ~VirtualDisplay() {
-        assert(mState == UNINITIALIZED || mState == STOPPED);
-    }
-
-    virtual status_t setDisplayProjection(const sp<IBinder>& dpy,
-            const DisplayInfo& mainDpyInfo);
-
-    // (overrides GLConsumer::FrameAvailableListener method)
-    virtual void onFrameAvailable(const BufferItem& item);
-
-    // (overrides Thread method)
-    virtual bool threadLoop();
-
-    // One-time setup (essentially object construction on the overlay thread).
-    status_t setup_l();
-
-    // Release all resources held.
-    void release_l();
-
-    // Process a frame received from the virtual display.
-    void* processFrame_l();
-
-    rfbScreenInfoPtr mVNCScreen;
-    Mutex *mUpdateMutex;
-
-    uint32_t mHeight, mWidth;
-    bool mRotate;
-
-    // Used to wait for the FrameAvailableListener callback.
-    Mutex mMutex;
-
-    // Initialization gate.
-    Condition mStartCond;
-
-    // Thread status, mostly useful during startup.
-    status_t mThreadResult;
-
-    // Overlay thread state.  States advance from left to right; object may
-    // not be restarted.
-    enum { UNINITIALIZED, INIT, RUNNING, STOPPING, STOPPED } mState;
-
-    // Event notification.  Overlay thread sleeps on this until a frame
-    // arrives or it's time to shut down.
-    Condition mEventCond;
-
-    // Producer side of queue, passed into the virtual display.
-    // The consumer end feeds into our GLConsumer.
-    sp<IGraphicBufferProducer> mProducer;
-
-    // This receives frames from the virtual display and makes them available
-    sp<CpuConsumer> mCpuConsumer;
-
-    sp<IBinder> mDpy;
-};
-
-}; // namespace android
-
-#endif /* VDS_H */