blob: dfb1a38cec0d8f1be73a1f0f3085fd36d05a93ef [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
17EventQueue *VNCFlinger::sQueue = new EventQueue();
18
19status_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);
31 sQueue->await();
32
33 release_l();
34 return NO_ERROR;
35}
36
37status_t VNCFlinger::setup_l() {
38
39 status_t err = NO_ERROR;
40
41 mMainDpy = SurfaceComposerClient::getBuiltInDisplay(
42 ISurfaceComposer::eDisplayIdMain);
43 err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mMainDpyInfo);
44 if (err != NO_ERROR) {
45 ALOGE("Unable to get display characteristics\n");
46 return err;
47 }
48
49 bool rotated = VirtualDisplay::isDeviceRotated(mMainDpyInfo.orientation);
50 if (mWidth == 0) {
51 mWidth = rotated ? mMainDpyInfo.h : mMainDpyInfo.w;
52 }
53 if (mHeight == 0) {
54 mHeight = rotated ? mMainDpyInfo.w : mMainDpyInfo.h;
55 }
56
57 ALOGD("Display dimensions: %dx%d rotated=%d", mWidth, mHeight, rotated);
58
59 sQueue->addListener(this);
60
Steve Kondik55db0532017-06-12 11:27:18 -070061 rfbLog = VNCFlinger::rfbLogger;
62 rfbErr = VNCFlinger::rfbLogger;
63
64 // 32-bit color
65 mVNCScreen = rfbGetScreen(&mArgc, mArgv, mWidth, mHeight, 8, 3, 4);
66 if (mVNCScreen == NULL) {
67 ALOGE("Unable to create VNCScreen");
68 return NO_INIT;
69 }
70
Steve Kondikdda11002017-06-13 08:20:27 -070071 mVNCBuf = new uint8_t[mWidth * mHeight * 4];
72 mVNCScreen->frameBuffer = (char *) mVNCBuf;
Steve Kondik55db0532017-06-12 11:27:18 -070073 mVNCScreen->desktopName = "VNCFlinger";
Steve Kondik55db0532017-06-12 11:27:18 -070074 mVNCScreen->alwaysShared = TRUE;
75 mVNCScreen->httpDir = NULL;
76 mVNCScreen->port = VNC_PORT;
77 mVNCScreen->newClientHook = (rfbNewClientHookPtr) VNCFlinger::onNewClient;
Steve Kondik107d2e52017-06-13 17:34:56 -070078 mVNCScreen->kbdAddEvent = InputDevice::keyEvent;
79 mVNCScreen->ptrAddEvent = InputDevice::pointerEvent;
Steve Kondik55db0532017-06-12 11:27:18 -070080 mVNCScreen->serverFormat.trueColour = true;
81 mVNCScreen->serverFormat.bitsPerPixel = 32;
82 mVNCScreen->handleEventsEagerly = true;
Steve Kondikdda11002017-06-13 08:20:27 -070083 mVNCScreen->deferUpdateTime = 16;
Steve Kondik55db0532017-06-12 11:27:18 -070084
85 rfbInitServer(mVNCScreen);
86
87 /* Mark as dirty since we haven't sent any updates at all yet. */
88 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
89
Steve Kondikdda11002017-06-13 08:20:27 -070090
91 mVirtualDisplay = new VirtualDisplay(mVNCScreen);
92
Steve Kondik55db0532017-06-12 11:27:18 -070093 return err;
94}
95
96void VNCFlinger::release_l() {
97 sQueue->removeListener(this);
98 mVirtualDisplay.clear();
99
100 ALOGD("VNCFlinger released");
101}
102
103status_t VNCFlinger::stop() {
104 Mutex::Autolock _l(mMutex);
105 sQueue->shutdown();
106
107 return NO_ERROR;
108}
109
110void VNCFlinger::onEvent(const Event& event) {
111
112 ALOGV("onEvent: mId=%d mData=%p", event.mId, event.mData);
113
114 switch(event.mId) {
115 case EVENT_CLIENT_CONNECT:
116 if (mClientCount == 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700117 InputDevice::start(mWidth, mHeight);
Steve Kondik55db0532017-06-12 11:27:18 -0700118 mVirtualDisplay->start(mMainDpyInfo, sQueue);
119 }
120 mClientCount++;
121
122 ALOGI("Client connected (%zu)", mClientCount);
123 break;
124
125 case EVENT_CLIENT_GONE:
126 if (mClientCount > 0) {
127 mClientCount--;
128 if (mClientCount == 0) {
129 mVirtualDisplay->stop();
Steve Kondik107d2e52017-06-13 17:34:56 -0700130 InputDevice::stop();
Steve Kondik55db0532017-06-12 11:27:18 -0700131 }
132 }
133
134 ALOGI("Client disconnected (%zu)", mClientCount);
135 break;
136
Steve Kondikdda11002017-06-13 08:20:27 -0700137 /*
Steve Kondik55db0532017-06-12 11:27:18 -0700138 case EVENT_BUFFER_READY:
Steve Kondikdda11002017-06-13 08:20:27 -0700139 int64_t startWhenNsec, endWhenNsec;
140 startWhenNsec = systemTime(CLOCK_MONOTONIC);
141 if (event.mData == NULL) {
142 break;
143 }
144 //memcpy(mVNCBuf, (uint8_t *) event.mData, mWidth * mHeight * 4);
Steve Kondik55db0532017-06-12 11:27:18 -0700145 //mVNCScreen->frameBuffer = (char *) event.mData;
Steve Kondik55db0532017-06-12 11:27:18 -0700146 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
Steve Kondikdda11002017-06-13 08:20:27 -0700147 endWhenNsec = systemTime(CLOCK_MONOTONIC);
148 ALOGV("got pixels (mark=%.3fms)",
149 (endWhenNsec - startWhenNsec) / 1000000.0);
Steve Kondik55db0532017-06-12 11:27:18 -0700150 break;
Steve Kondikdda11002017-06-13 08:20:27 -0700151 */
Steve Kondik55db0532017-06-12 11:27:18 -0700152
153 default:
154 ALOGE("Unhandled event: %d", event.mId);
155 break;
156 }
157}
158
159ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr /* cl */) {
160 ALOGV("onClientGone");
161 sQueue->enqueue(Event(EVENT_CLIENT_GONE));
162 return 0;
163}
164
165enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
166 ALOGV("onNewClient");
167 cl->clientGoneHook = (ClientGoneHookPtr) VNCFlinger::onClientGone;
168 sQueue->enqueue(Event(EVENT_CLIENT_CONNECT));
169 return RFB_CLIENT_ACCEPT;
170}
171
172void VNCFlinger::rfbLogger(const char *format, ...) {
173 va_list args;
174 char buf[256];
175
176 va_start(args, format);
177 vsprintf(buf, format, args);
178 ALOGI("%s", buf);
179 va_end(args);
180}