blob: 0ca27841df20cbdc474029207bf8ceb78de68618 [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
12#include "VNCFlinger.h"
13
14using namespace android;
15
16EventQueue *VNCFlinger::sQueue = new EventQueue();
17
18status_t VNCFlinger::start() {
19 Mutex::Autolock _l(mMutex);
20
21 status_t err = setup_l();
22 if (err != NO_ERROR) {
23 ALOGE("Failed to start VNCFlinger: err=%d", err);
24 return err;
25 }
26
27 ALOGD("VNCFlinger is running!");
28
29 rfbRunEventLoop(mVNCScreen, -1, true);
30 sQueue->await();
31
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
58 sQueue->addListener(this);
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;
77 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 Kondik55db0532017-06-12 11:27:18 -070081
82 rfbInitServer(mVNCScreen);
83
84 /* Mark as dirty since we haven't sent any updates at all yet. */
85 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
86
Steve Kondikdda11002017-06-13 08:20:27 -070087
88 mVirtualDisplay = new VirtualDisplay(mVNCScreen);
89
Steve Kondik55db0532017-06-12 11:27:18 -070090 return err;
91}
92
93void VNCFlinger::release_l() {
94 sQueue->removeListener(this);
95 mVirtualDisplay.clear();
96
97 ALOGD("VNCFlinger released");
98}
99
100status_t VNCFlinger::stop() {
101 Mutex::Autolock _l(mMutex);
102 sQueue->shutdown();
103
104 return NO_ERROR;
105}
106
107void VNCFlinger::onEvent(const Event& event) {
108
109 ALOGV("onEvent: mId=%d mData=%p", event.mId, event.mData);
110
111 switch(event.mId) {
112 case EVENT_CLIENT_CONNECT:
113 if (mClientCount == 0) {
114 mVirtualDisplay->start(mMainDpyInfo, sQueue);
115 }
116 mClientCount++;
117
118 ALOGI("Client connected (%zu)", mClientCount);
119 break;
120
121 case EVENT_CLIENT_GONE:
122 if (mClientCount > 0) {
123 mClientCount--;
124 if (mClientCount == 0) {
125 mVirtualDisplay->stop();
126 }
127 }
128
129 ALOGI("Client disconnected (%zu)", mClientCount);
130 break;
131
Steve Kondikdda11002017-06-13 08:20:27 -0700132 /*
Steve Kondik55db0532017-06-12 11:27:18 -0700133 case EVENT_BUFFER_READY:
Steve Kondikdda11002017-06-13 08:20:27 -0700134 int64_t startWhenNsec, endWhenNsec;
135 startWhenNsec = systemTime(CLOCK_MONOTONIC);
136 if (event.mData == NULL) {
137 break;
138 }
139 //memcpy(mVNCBuf, (uint8_t *) event.mData, mWidth * mHeight * 4);
Steve Kondik55db0532017-06-12 11:27:18 -0700140 //mVNCScreen->frameBuffer = (char *) event.mData;
Steve Kondik55db0532017-06-12 11:27:18 -0700141 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
Steve Kondikdda11002017-06-13 08:20:27 -0700142 endWhenNsec = systemTime(CLOCK_MONOTONIC);
143 ALOGV("got pixels (mark=%.3fms)",
144 (endWhenNsec - startWhenNsec) / 1000000.0);
Steve Kondik55db0532017-06-12 11:27:18 -0700145 break;
Steve Kondikdda11002017-06-13 08:20:27 -0700146 */
Steve Kondik55db0532017-06-12 11:27:18 -0700147
148 default:
149 ALOGE("Unhandled event: %d", event.mId);
150 break;
151 }
152}
153
154ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr /* cl */) {
155 ALOGV("onClientGone");
156 sQueue->enqueue(Event(EVENT_CLIENT_GONE));
157 return 0;
158}
159
160enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
161 ALOGV("onNewClient");
162 cl->clientGoneHook = (ClientGoneHookPtr) VNCFlinger::onClientGone;
163 sQueue->enqueue(Event(EVENT_CLIENT_CONNECT));
164 return RFB_CLIENT_ACCEPT;
165}
166
167void VNCFlinger::rfbLogger(const char *format, ...) {
168 va_list args;
169 char buf[256];
170
171 va_start(args, format);
172 vsprintf(buf, format, args);
173 ALOGI("%s", buf);
174 va_end(args);
175}