blob: 70f741aff4fecd0dba362c350e0e5878a2627704 [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 Kondik55db0532017-06-12 11:27:18 -070017status_t VNCFlinger::start() {
18 Mutex::Autolock _l(mMutex);
19
20 status_t err = setup_l();
21 if (err != NO_ERROR) {
22 ALOGE("Failed to start VNCFlinger: err=%d", err);
23 return err;
24 }
25
26 ALOGD("VNCFlinger is running!");
27
28 rfbRunEventLoop(mVNCScreen, -1, true);
Steve Kondik7225c7f2017-06-14 00:06:16 -070029
30 mCondition.wait(mMutex);
Steve Kondik55db0532017-06-12 11:27:18 -070031
32 release_l();
33 return NO_ERROR;
34}
35
36status_t VNCFlinger::setup_l() {
37
38 status_t err = NO_ERROR;
39
40 mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
41 ISurfaceComposer::eDisplayIdMain);
42 err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
43 if (err != NO_ERROR) {
44 ALOGE("Unable to get display characteristics\n");
45 return err;
46 }
47
48 bool rotated = VirtualDisplay::isDeviceRotated(mMainDpyInfo.orientation);
49 if (mWidth == 0) {
50 mWidth = rotated ? mMainDpyInfo.h : mMainDpyInfo.w;
51 }
52 if (mHeight == 0) {
53 mHeight = rotated ? mMainDpyInfo.w : mMainDpyInfo.h;
54 }
55
56 ALOGD("Display dimensions: %dx%d rotated=%d", mWidth, mHeight, rotated);
57
Steve Kondik55db0532017-06-12 11:27:18 -070058 rfbLog = VNCFlinger::rfbLogger;
59 rfbErr = VNCFlinger::rfbLogger;
60
61 // 32-bit color
62 mVNCScreen = rfbGetScreen(&mArgc, mArgv, mWidth, mHeight, 8, 3, 4);
63 if (mVNCScreen == NULL) {
64 ALOGE("Unable to create VNCScreen");
65 return NO_INIT;
66 }
67
Steve Kondikdda11002017-06-13 08:20:27 -070068 mVNCBuf = new uint8_t[mWidth * mHeight * 4];
69 mVNCScreen->frameBuffer = (char *) mVNCBuf;
Steve Kondik55db0532017-06-12 11:27:18 -070070 mVNCScreen->desktopName = "VNCFlinger";
Steve Kondik55db0532017-06-12 11:27:18 -070071 mVNCScreen->alwaysShared = TRUE;
72 mVNCScreen->httpDir = NULL;
73 mVNCScreen->port = VNC_PORT;
74 mVNCScreen->newClientHook = (rfbNewClientHookPtr) VNCFlinger::onNewClient;
Steve Kondik107d2e52017-06-13 17:34:56 -070075 mVNCScreen->kbdAddEvent = InputDevice::keyEvent;
76 mVNCScreen->ptrAddEvent = InputDevice::pointerEvent;
Steve Kondik55db0532017-06-12 11:27:18 -070077 mVNCScreen->serverFormat.trueColour = true;
78 mVNCScreen->serverFormat.bitsPerPixel = 32;
79 mVNCScreen->handleEventsEagerly = true;
Steve Kondikdda11002017-06-13 08:20:27 -070080 mVNCScreen->deferUpdateTime = 16;
Steve Kondik7225c7f2017-06-14 00:06:16 -070081 mVNCScreen->screenData = this;
Steve Kondik55db0532017-06-12 11:27:18 -070082
83 rfbInitServer(mVNCScreen);
84
85 /* Mark as dirty since we haven't sent any updates at all yet. */
86 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
87
Steve Kondikdda11002017-06-13 08:20:27 -070088
89 mVirtualDisplay = new VirtualDisplay(mVNCScreen);
90
Steve Kondik55db0532017-06-12 11:27:18 -070091 return err;
92}
93
94void VNCFlinger::release_l() {
Steve Kondik55db0532017-06-12 11:27:18 -070095 mVirtualDisplay.clear();
96
97 ALOGD("VNCFlinger released");
98}
99
100status_t VNCFlinger::stop() {
101 Mutex::Autolock _l(mMutex);
Steve Kondik7225c7f2017-06-14 00:06:16 -0700102 mCondition.signal();
Steve Kondik55db0532017-06-12 11:27:18 -0700103
104 return NO_ERROR;
105}
106
Steve Kondik7225c7f2017-06-14 00:06:16 -0700107size_t VNCFlinger::addClient() {
108 Mutex::Autolock _l(mMutex);
109 if (mClientCount == 0) {
110 InputDevice::start(mWidth, mHeight);
111 mVirtualDisplay->start(mMainDpyInfo);
Steve Kondik55db0532017-06-12 11:27:18 -0700112 }
Steve Kondik7225c7f2017-06-14 00:06:16 -0700113 mClientCount++;
114
115 ALOGI("Client connected (%zu)", mClientCount);
116
117 return mClientCount;
Steve Kondik55db0532017-06-12 11:27:18 -0700118}
119
Steve Kondik7225c7f2017-06-14 00:06:16 -0700120size_t VNCFlinger::removeClient() {
121 Mutex::Autolock _l(mMutex);
122 if (mClientCount > 0) {
123 mClientCount--;
124 if (mClientCount == 0) {
125 mVirtualDisplay->stop();
126 InputDevice::stop();
127 }
128 }
129
130 ALOGI("Client disconnected (%zu)", mClientCount);
131
132 return mClientCount;
133}
134
135ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr cl) {
Steve Kondik55db0532017-06-12 11:27:18 -0700136 ALOGV("onClientGone");
Steve Kondik7225c7f2017-06-14 00:06:16 -0700137 VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
138 vf->removeClient();
Steve Kondik55db0532017-06-12 11:27:18 -0700139 return 0;
140}
141
142enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
143 ALOGV("onNewClient");
144 cl->clientGoneHook = (ClientGoneHookPtr) VNCFlinger::onClientGone;
Steve Kondik7225c7f2017-06-14 00:06:16 -0700145 VNCFlinger *vf = (VNCFlinger *)cl->screen->screenData;
146 vf->addClient();
Steve Kondik55db0532017-06-12 11:27:18 -0700147 return RFB_CLIENT_ACCEPT;
148}
149
150void VNCFlinger::rfbLogger(const char *format, ...) {
151 va_list args;
152 char buf[256];
153
154 va_start(args, format);
155 vsprintf(buf, format, args);
156 ALOGI("%s", buf);
157 va_end(args);
158}