vnc: Simplify everything
Previous design was using extra threads needlessly and had some
hacky data sharing going on. Slim this down to just two classes
and utilize threads appropriately.
diff --git a/src/README b/src/README
deleted file mode 100644
index e6cbb2b..0000000
--- 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 efd6cbc..4775d0b 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;
-
status_t VNCFlinger::start() {
- Mutex::Autolock _l(mMutex);
+ sp<ProcessState> self = ProcessState::self();
+ self->startThreadPool();
- status_t err = setup_l();
+ 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;
+
+ err = createVNCServer();
if (err != NO_ERROR) {
ALOGE("Failed to start VNCFlinger: err=%d", err);
return err;
@@ -29,34 +41,78 @@
rfbRunEventLoop(mVNCScreen, -1, true);
- mCondition.wait(mMutex);
+ eventLoop();
- release_l();
return NO_ERROR;
}
-status_t VNCFlinger::setup_l() {
+void VNCFlinger::eventLoop() {
+ mRunning = true;
+
+ Mutex::Autolock _l(mEventMutex);
+ while (mRunning) {
+ mEventCond.wait(mEventMutex);
+
+ // spurious wakeup? never.
+ if (mClientCount == 0) {
+ continue;
+ }
+
+ // 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);
+
+ 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;
- mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain);
- err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
- if (err != NO_ERROR) {
- ALOGE("Unable to get display characteristics\n");
- return err;
- }
-
- bool rotated = VirtualDisplay::isDeviceRotated(mMainDpyInfo.orientation);
- if (mWidth == 0) {
- mWidth = rotated ? mMainDpyInfo.h : mMainDpyInfo.w;
- }
- if (mHeight == 0) {
- mHeight = rotated ? mMainDpyInfo.w : mMainDpyInfo.h;
- }
-
- ALOGD("Display dimensions: %dx%d rotated=%d", mWidth, mHeight, rotated);
-
rfbLog = VNCFlinger::rfbLogger;
rfbErr = VNCFlinger::rfbLogger;
@@ -88,32 +144,27 @@
/* 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();
-
- ALOGD("VNCFlinger released");
-}
-
status_t VNCFlinger::stop() {
- Mutex::Autolock _l(mMutex);
- mCondition.signal();
+ Mutex::Autolock _L(mEventMutex);
+
+ mClientCount = 0;
+ mRunning = false;
+
+ 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::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 @@
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 @@
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 8c026b9..4535fb6 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 @@
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 27cc00e..0000000
--- 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 57c2c92..0000000
--- 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 */