blob: efd6cbc9f7c44459951a35daf31a0c8d9223343b [file] [log] [blame]
Steve Kondik55db0532017-06-12 11:27:18 -07001#define LOG_TAG "VNCFlinger"
2#include <utils/Log.h>
3
4#include <binder/IPCThreadState.h>
5#include <binder/ProcessState.h>
6#include <binder/IServiceManager.h>
7
8#include <gui/ISurfaceComposer.h>
9#include <gui/SurfaceComposerClient.h>
10#include <gui/IGraphicBufferProducer.h>
11
Steve Kondik107d2e52017-06-13 17:34:56 -070012#include "InputDevice.h"
Steve Kondik55db0532017-06-12 11:27:18 -070013#include "VNCFlinger.h"
14
15using namespace android;
16
Steve Kondikef4e8652017-06-14 15:07:54 -070017Mutex VNCFlinger::sUpdateMutex;
18
Steve Kondik55db0532017-06-12 11:27:18 -070019status_t VNCFlinger::start() {
20 Mutex::Autolock _l(mMutex);
21
22 status_t err = setup_l();
23 if (err != NO_ERROR) {
24 ALOGE("Failed to start VNCFlinger: err=%d", err);
25 return err;
26 }
27
28 ALOGD("VNCFlinger is running!");
29
30 rfbRunEventLoop(mVNCScreen, -1, true);
Steve Kondik7225c7f2017-06-14 00:06:16 -070031
32 mCondition.wait(mMutex);
Steve Kondik55db0532017-06-12 11:27:18 -070033
34 release_l();
35 return NO_ERROR;
36}
37
38status_t VNCFlinger::setup_l() {
39
40 status_t err = NO_ERROR;
41
42 mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
43 ISurfaceComposer::eDisplayIdMain);
44 err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
45 if (err != NO_ERROR) {
46 ALOGE("Unable to get display characteristics\n");
47 return err;
48 }
49
50 bool rotated = VirtualDisplay::isDeviceRotated(mMainDpyInfo.orientation);
51 if (mWidth == 0) {
52 mWidth = rotated ? mMainDpyInfo.h : mMainDpyInfo.w;
53 }
54 if (mHeight == 0) {
55 mHeight = rotated ? mMainDpyInfo.w : mMainDpyInfo.h;
56 }
57
58 ALOGD("Display dimensions: %dx%d rotated=%d", mWidth, mHeight, rotated);
59
Steve Kondik55db0532017-06-12 11:27:18 -070060 rfbLog = VNCFlinger::rfbLogger;
61 rfbErr = VNCFlinger::rfbLogger;
62
63 // 32-bit color
64 mVNCScreen = rfbGetScreen(&mArgc, mArgv, mWidth, mHeight, 8, 3, 4);
65 if (mVNCScreen == NULL) {
66 ALOGE("Unable to create VNCScreen");
67 return NO_INIT;
68 }
69
Steve Kondikdda11002017-06-13 08:20:27 -070070 mVNCBuf = new uint8_t[mWidth * mHeight * 4];
71 mVNCScreen->frameBuffer = (char *) mVNCBuf;
Steve Kondik55db0532017-06-12 11:27:18 -070072 mVNCScreen->desktopName = "VNCFlinger";
Steve Kondik55db0532017-06-12 11:27:18 -070073 mVNCScreen->alwaysShared = TRUE;
74 mVNCScreen->httpDir = NULL;
75 mVNCScreen->port = VNC_PORT;
76 mVNCScreen->newClientHook = (rfbNewClientHookPtr) VNCFlinger::onNewClient;
Steve Kondik107d2e52017-06-13 17:34:56 -070077 mVNCScreen->kbdAddEvent = InputDevice::keyEvent;
78 mVNCScreen->ptrAddEvent = InputDevice::pointerEvent;
Steve Kondikef4e8652017-06-14 15:07:54 -070079 mVNCScreen->displayHook = (rfbDisplayHookPtr) VNCFlinger::onFrameStart;
80 mVNCScreen->displayFinishedHook = (rfbDisplayFinishedHookPtr) VNCFlinger::onFrameDone;
Steve Kondik55db0532017-06-12 11:27:18 -070081 mVNCScreen->serverFormat.trueColour = true;
82 mVNCScreen->serverFormat.bitsPerPixel = 32;
83 mVNCScreen->handleEventsEagerly = true;
Steve Kondikef4e8652017-06-14 15:07:54 -070084 mVNCScreen->deferUpdateTime = 0;
Steve Kondik7225c7f2017-06-14 00:06:16 -070085 mVNCScreen->screenData = this;
Steve Kondik55db0532017-06-12 11:27:18 -070086 rfbInitServer(mVNCScreen);
87
88 /* Mark as dirty since we haven't sent any updates at all yet. */
89 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
90
Steve Kondikdda11002017-06-13 08:20:27 -070091
Steve Kondikef4e8652017-06-14 15:07:54 -070092 mVirtualDisplay = new VirtualDisplay(mVNCScreen, &sUpdateMutex);
Steve Kondikdda11002017-06-13 08:20:27 -070093
Steve Kondik55db0532017-06-12 11:27:18 -070094 return err;
95}
96
97void VNCFlinger::release_l() {
Steve Kondik55db0532017-06-12 11:27:18 -070098 mVirtualDisplay.clear();
99
100 ALOGD("VNCFlinger released");
101}
102
103status_t VNCFlinger::stop() {
104 Mutex::Autolock _l(mMutex);
Steve Kondik7225c7f2017-06-14 00:06:16 -0700105 mCondition.signal();
Steve Kondik55db0532017-06-12 11:27:18 -0700106
107 return NO_ERROR;
108}
109
Steve Kondik7225c7f2017-06-14 00:06:16 -0700110size_t VNCFlinger::addClient() {
111 Mutex::Autolock _l(mMutex);
112 if (mClientCount == 0) {
113 InputDevice::start(mWidth, mHeight);
114 mVirtualDisplay->start(mMainDpyInfo);
Steve Kondik55db0532017-06-12 11:27:18 -0700115 }
Steve Kondik7225c7f2017-06-14 00:06:16 -0700116 mClientCount++;
117
118 ALOGI("Client connected (%zu)", mClientCount);
119
120 return mClientCount;
Steve Kondik55db0532017-06-12 11:27:18 -0700121}
122
Steve Kondik7225c7f2017-06-14 00:06:16 -0700123size_t VNCFlinger::removeClient() {
124 Mutex::Autolock _l(mMutex);
125 if (mClientCount > 0) {
126 mClientCount--;
127 if (mClientCount == 0) {
128 mVirtualDisplay->stop();
129 InputDevice::stop();
130 }
131 }
132
133 ALOGI("Client disconnected (%zu)", mClientCount);
134
135 return mClientCount;
136}
137
138ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr cl) {
Steve Kondik55db0532017-06-12 11:27:18 -0700139 ALOGV("onClientGone");
Steve Kondik7225c7f2017-06-14 00:06:16 -0700140 VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
141 vf->removeClient();
Steve Kondik55db0532017-06-12 11:27:18 -0700142 return 0;
143}
144
145enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
146 ALOGV("onNewClient");
147 cl->clientGoneHook = (ClientGoneHookPtr) VNCFlinger::onClientGone;
Steve Kondik7225c7f2017-06-14 00:06:16 -0700148 VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
149 vf->addClient();
Steve Kondik55db0532017-06-12 11:27:18 -0700150 return RFB_CLIENT_ACCEPT;
151}
152
Steve Kondikef4e8652017-06-14 15:07:54 -0700153void VNCFlinger::onFrameStart(rfbClientPtr /* cl */) {
154 sUpdateMutex.lock();
155 ALOGV("frame start");
156}
157
158void VNCFlinger::onFrameDone(rfbClientPtr /* cl */, int status) {
159 sUpdateMutex.unlock();
160 ALOGV("frame done! %d", status);
161}
162
163void VNCFlinger::markFrame(void* frame, size_t stride) {
164 Mutex::Autolock _l(sUpdateMutex);
165 mVNCScreen->frameBuffer = (char *)frame;
166 mVNCScreen->paddedWidthInBytes = stride * 4;
167 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
168}
169
Steve Kondik55db0532017-06-12 11:27:18 -0700170void VNCFlinger::rfbLogger(const char *format, ...) {
171 va_list args;
172 char buf[256];
173
174 va_start(args, format);
175 vsprintf(buf, format, args);
176 ALOGI("%s", buf);
177 va_end(args);
178}