blob: a55b8684311549eb18e8db0e3de8c71b88eb719c [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
60 mVirtualDisplay = new VirtualDisplay();
61
62 mVNCBuf = new uint8_t[mWidth * mHeight * 4];
63
64 rfbLog = VNCFlinger::rfbLogger;
65 rfbErr = VNCFlinger::rfbLogger;
66
67 // 32-bit color
68 mVNCScreen = rfbGetScreen(&mArgc, mArgv, mWidth, mHeight, 8, 3, 4);
69 if (mVNCScreen == NULL) {
70 ALOGE("Unable to create VNCScreen");
71 return NO_INIT;
72 }
73
74 mVNCScreen->desktopName = "VNCFlinger";
75 mVNCScreen->frameBuffer = (char *)mVNCBuf;
76 mVNCScreen->alwaysShared = TRUE;
77 mVNCScreen->httpDir = NULL;
78 mVNCScreen->port = VNC_PORT;
79 mVNCScreen->newClientHook = (rfbNewClientHookPtr) VNCFlinger::onNewClient;
80 mVNCScreen->serverFormat.trueColour = true;
81 mVNCScreen->serverFormat.bitsPerPixel = 32;
82 mVNCScreen->handleEventsEagerly = true;
83 mVNCScreen->deferUpdateTime = 5;
84
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
90 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
132 case EVENT_BUFFER_READY:
133 //mVNCScreen->frameBuffer = (char *) event.mData;
134 memcpy(mVNCBuf, (uint8_t *) event.mData, mWidth * mHeight * 4);
135 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
136 break;
137
138 default:
139 ALOGE("Unhandled event: %d", event.mId);
140 break;
141 }
142}
143
144ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr /* cl */) {
145 ALOGV("onClientGone");
146 sQueue->enqueue(Event(EVENT_CLIENT_GONE));
147 return 0;
148}
149
150enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
151 ALOGV("onNewClient");
152 cl->clientGoneHook = (ClientGoneHookPtr) VNCFlinger::onClientGone;
153 sQueue->enqueue(Event(EVENT_CLIENT_CONNECT));
154 return RFB_CLIENT_ACCEPT;
155}
156
157void VNCFlinger::rfbLogger(const char *format, ...) {
158 va_list args;
159 char buf[256];
160
161 va_start(args, format);
162 vsprintf(buf, format, args);
163 ALOGI("%s", buf);
164 va_end(args);
165}