blob: b910453f725140fec0b935b01b9ce19b0e2b1586 [file] [log] [blame]
Steve Kondik95027ea2017-06-14 17:22:58 -07001//
2// vncflinger - Copyright (C) 2017 Steve Kondik
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17
Steve Kondik55db0532017-06-12 11:27:18 -070018#define LOG_TAG "VNCFlinger"
19#include <utils/Log.h>
20
Steve Kondik66bedf32017-06-20 09:17:35 -070021#include <fstream>
22
Steve Kondik55db0532017-06-12 11:27:18 -070023#include <binder/IPCThreadState.h>
Steve Kondik55db0532017-06-12 11:27:18 -070024#include <binder/IServiceManager.h>
Steve Kondik2c9d0cf2017-06-15 23:39:29 -070025#include <binder/ProcessState.h>
Steve Kondik55db0532017-06-12 11:27:18 -070026
Steve Kondik2c9d0cf2017-06-15 23:39:29 -070027#include <gui/IGraphicBufferProducer.h>
Steve Kondik55db0532017-06-12 11:27:18 -070028#include <gui/ISurfaceComposer.h>
29#include <gui/SurfaceComposerClient.h>
Steve Kondik55db0532017-06-12 11:27:18 -070030
Steve Kondik59104ea2017-06-20 08:30:07 -070031#include <ui/PixelFormat.h>
32
Steve Kondik107d2e52017-06-13 17:34:56 -070033#include "InputDevice.h"
Steve Kondik55db0532017-06-12 11:27:18 -070034#include "VNCFlinger.h"
35
36using namespace android;
37
Steve Kondik5c8655c2017-06-19 00:28:47 -070038VNCFlinger::VNCFlinger() {
39 mOrientation = -1;
Steve Kondik59104ea2017-06-20 08:30:07 -070040 mScale = 1.0f;
Steve Kondik5c8655c2017-06-19 00:28:47 -070041 mMainDpy = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
42 updateDisplayProjection();
43
44 createVNCServer();
45
46 String8 v4("127.0.0.1");
47 String8 v6("::1");
48
Steve Kondik3db07472017-06-19 22:13:45 -070049 setV4Address(v4);
50 setV6Address(v6);
Steve Kondik5c8655c2017-06-19 00:28:47 -070051}
52
Steve Kondik3db07472017-06-19 22:13:45 -070053status_t VNCFlinger::setV4Address(const String8& address) {
Steve Kondik5c8655c2017-06-19 00:28:47 -070054 if (!rfbStringToAddr(const_cast<char *>(address.string()), &(mVNCScreen->listenInterface))) {
55 return BAD_VALUE;
56 }
57 return NO_ERROR;
58}
59
Steve Kondik3db07472017-06-19 22:13:45 -070060status_t VNCFlinger::setV6Address(const String8& address) {
Steve Kondik3db07472017-06-19 22:13:45 -070061 mVNCScreen->listen6Interface = const_cast<char *>(address.string());
62 return NO_ERROR;
63}
64
Steve Kondik5c8655c2017-06-19 00:28:47 -070065status_t VNCFlinger::setPort(unsigned int port) {
66 if (port > 65535) {
67 port = 0;
68 }
69 if (port == 0) {
70 mVNCScreen->autoPort = 1;
71 } else {
72 mVNCScreen->autoPort = 0;
73 mVNCScreen->port = port;
74 mVNCScreen->ipv6port = port;
75 }
76 return NO_ERROR;
77}
78
Steve Kondik59104ea2017-06-20 08:30:07 -070079status_t VNCFlinger::setScale(float scale) {
80 if (scale <= 0.0f || scale > 2.0f) {
81 return BAD_VALUE;
82 }
83 mScale = scale;
84 updateDisplayProjection();
85 return NO_ERROR;
86}
87
Steve Kondik5c8655c2017-06-19 00:28:47 -070088status_t VNCFlinger::clearPassword() {
89 std::remove(VNC_AUTH_FILE);
90 ALOGW("Password authentication disabled");
Steve Kondik66bedf32017-06-20 09:17:35 -070091 mVNCScreen->authPasswdData = NULL;
Steve Kondik5c8655c2017-06-19 00:28:47 -070092 return OK;
93}
94
Steve Kondik3db07472017-06-19 22:13:45 -070095status_t VNCFlinger::setPassword(const String8& passwd) {
Steve Kondik5c8655c2017-06-19 00:28:47 -070096 String8 path(VNC_AUTH_FILE);
97 if (rfbEncryptAndStorePasswd(const_cast<char *>(passwd.string()),
98 const_cast<char *>(path.string())) != 0) {
99 ALOGE("Failed to set password");
100 return BAD_VALUE;
101 }
102 ALOGI("Password has been set");
Steve Kondik66bedf32017-06-20 09:17:35 -0700103 mVNCScreen->authPasswdData = (void *)VNC_AUTH_FILE;
Steve Kondik5c8655c2017-06-19 00:28:47 -0700104 return OK;
105}
106
Steve Kondik55db0532017-06-12 11:27:18 -0700107status_t VNCFlinger::start() {
Steve Kondik77754522017-06-14 17:00:33 -0700108 sp<ProcessState> self = ProcessState::self();
109 self->startThreadPool();
Steve Kondik55db0532017-06-12 11:27:18 -0700110
Steve Kondik5c8655c2017-06-19 00:28:47 -0700111 status_t err = startVNCServer();
Steve Kondik55db0532017-06-12 11:27:18 -0700112 if (err != NO_ERROR) {
113 ALOGE("Failed to start VNCFlinger: err=%d", err);
114 return err;
115 }
116
Steve Kondik55db0532017-06-12 11:27:18 -0700117 rfbRunEventLoop(mVNCScreen, -1, true);
Steve Kondik7225c7f2017-06-14 00:06:16 -0700118
Steve Kondik46798992017-06-15 23:58:54 -0700119 ALOGD("VNCFlinger ready to fling");
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700120
Steve Kondik77754522017-06-14 17:00:33 -0700121 eventLoop();
Steve Kondik55db0532017-06-12 11:27:18 -0700122
Steve Kondik46798992017-06-15 23:58:54 -0700123 ALOGI("VNCFlinger has left the building");
124
125 return NO_ERROR;
126}
127
128status_t VNCFlinger::stop() {
129 Mutex::Autolock _L(mEventMutex);
Steve Kondik46798992017-06-15 23:58:54 -0700130 ALOGV("Shutting down");
131
Steve Kondik59104ea2017-06-20 08:30:07 -0700132 rfbShutdownServer(mVNCScreen, false);
Steve Kondik5c8655c2017-06-19 00:28:47 -0700133
Steve Kondik46798992017-06-15 23:58:54 -0700134 destroyVirtualDisplayLocked();
Steve Kondik59104ea2017-06-20 08:30:07 -0700135
Steve Kondik46798992017-06-15 23:58:54 -0700136 mClientCount = 0;
137 mRunning = false;
138
139 mEventCond.signal();
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700140 delete[] mVNCScreen->frameBuffer;
Steve Kondik55db0532017-06-12 11:27:18 -0700141 return NO_ERROR;
142}
143
Steve Kondik77754522017-06-14 17:00:33 -0700144void VNCFlinger::eventLoop() {
145 mRunning = true;
146
147 Mutex::Autolock _l(mEventMutex);
148 while (mRunning) {
149 mEventCond.wait(mEventMutex);
150
151 // spurious wakeup? never.
152 if (mClientCount == 0) {
153 continue;
154 }
155
156 // this is a new client, so fire everything up
157 status_t err = createVirtualDisplay();
158 if (err != NO_ERROR) {
159 ALOGE("Failed to create virtual display: err=%d", err);
160 }
161
162 // loop while clients are connected and process frames
163 // on the main thread when signalled
164 while (mClientCount > 0) {
165 mEventCond.wait(mEventMutex);
166 if (mFrameAvailable) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700167 if (!updateDisplayProjection()) {
168 processFrame();
169 }
Steve Kondik77754522017-06-14 17:00:33 -0700170 mFrameAvailable = false;
171 }
172 }
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700173 Mutex::Autolock _l(mUpdateMutex);
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700174 memset(mVNCScreen->frameBuffer, 0, mFrameSize);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700175 destroyVirtualDisplayLocked();
Steve Kondik77754522017-06-14 17:00:33 -0700176 }
177}
178
179status_t VNCFlinger::createVirtualDisplay() {
180 sp<IGraphicBufferConsumer> consumer;
181 BufferQueue::createBufferQueue(&mProducer, &consumer);
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700182 mCpuConsumer = new CpuConsumer(consumer, NUM_BUFS);
Steve Kondik77754522017-06-14 17:00:33 -0700183 mCpuConsumer->setName(String8("vds-to-cpu"));
184 mCpuConsumer->setDefaultBufferSize(mWidth, mHeight);
Steve Kondik59104ea2017-06-20 08:30:07 -0700185 mProducer->setMaxDequeuedBufferCount(1);
186 consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBX_8888);
Steve Kondik77754522017-06-14 17:00:33 -0700187
188 mListener = new FrameListener(this);
189 mCpuConsumer->setFrameAvailableListener(mListener);
190
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700191 mDpy = SurfaceComposerClient::createDisplay(String8("VNC-VirtualDisplay"), false /*secure*/);
Steve Kondik77754522017-06-14 17:00:33 -0700192
193 SurfaceComposerClient::openGlobalTransaction();
194 SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
Steve Kondik59104ea2017-06-20 08:30:07 -0700195 Rect displayRect(0, 0, mSourceWidth, mSourceHeight);
196 Rect outRect(0, 0, mWidth, mHeight);
197 SurfaceComposerClient::setDisplayProjection(mDpy, 0, displayRect, outRect);
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700198 SurfaceComposerClient::setDisplayLayerStack(mDpy, 0); // default stack
Steve Kondik77754522017-06-14 17:00:33 -0700199 SurfaceComposerClient::closeGlobalTransaction();
200
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700201 mVDSActive = true;
202
203 ALOGV("Virtual display (%dx%d) created", mWidth, mHeight);
204
Steve Kondik77754522017-06-14 17:00:33 -0700205 return NO_ERROR;
206}
207
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700208status_t VNCFlinger::destroyVirtualDisplayLocked() {
Steve Kondik46798992017-06-15 23:58:54 -0700209 if (!mVDSActive) {
210 return NO_INIT;
211 }
212
Steve Kondik77754522017-06-14 17:00:33 -0700213 mCpuConsumer.clear();
214 mProducer.clear();
215 SurfaceComposerClient::destroyDisplay(mDpy);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700216
217 mVDSActive = false;
218
219 ALOGV("Virtual display destroyed");
220
Steve Kondik77754522017-06-14 17:00:33 -0700221 return NO_ERROR;
222}
223
224status_t VNCFlinger::createVNCServer() {
Steve Kondik55db0532017-06-12 11:27:18 -0700225 status_t err = NO_ERROR;
226
Steve Kondik55db0532017-06-12 11:27:18 -0700227 rfbLog = VNCFlinger::rfbLogger;
228 rfbErr = VNCFlinger::rfbLogger;
229
230 // 32-bit color
Steve Kondik5c8655c2017-06-19 00:28:47 -0700231 mVNCScreen = rfbGetScreen(0, NULL, mWidth, mHeight, 8, 3, 4);
Steve Kondik55db0532017-06-12 11:27:18 -0700232 if (mVNCScreen == NULL) {
233 ALOGE("Unable to create VNCScreen");
234 return NO_INIT;
235 }
236
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700237 mFrameNumber = 0;
238 mFrameSize = mWidth * mHeight * 4;
239 mVNCScreen->frameBuffer = (char*)new uint8_t[mFrameSize];
240 memset(mVNCScreen->frameBuffer, 0, mFrameSize);
241
Steve Kondik55db0532017-06-12 11:27:18 -0700242 mVNCScreen->desktopName = "VNCFlinger";
Steve Kondik55db0532017-06-12 11:27:18 -0700243 mVNCScreen->alwaysShared = TRUE;
244 mVNCScreen->httpDir = NULL;
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700245 mVNCScreen->newClientHook = (rfbNewClientHookPtr)VNCFlinger::onNewClient;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700246 mVNCScreen->kbdAddEvent = InputDevice::onKeyEvent;
247 mVNCScreen->ptrAddEvent = InputDevice::onPointerEvent;
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700248 mVNCScreen->displayHook = (rfbDisplayHookPtr)VNCFlinger::onFrameStart;
249 mVNCScreen->displayFinishedHook = (rfbDisplayFinishedHookPtr)VNCFlinger::onFrameDone;
Steve Kondik55db0532017-06-12 11:27:18 -0700250 mVNCScreen->serverFormat.trueColour = true;
251 mVNCScreen->serverFormat.bitsPerPixel = 32;
Steve Kondik59104ea2017-06-20 08:30:07 -0700252 mVNCScreen->serverFormat.depth = 24;
Steve Kondik55db0532017-06-12 11:27:18 -0700253 mVNCScreen->handleEventsEagerly = true;
Steve Kondik59104ea2017-06-20 08:30:07 -0700254 mVNCScreen->deferUpdateTime = 0;
Steve Kondik7225c7f2017-06-14 00:06:16 -0700255 mVNCScreen->screenData = this;
Steve Kondik5c8655c2017-06-19 00:28:47 -0700256
Steve Kondik66bedf32017-06-20 09:17:35 -0700257 std::ifstream authFile(VNC_AUTH_FILE);
258 if ((bool)authFile) {
259 mVNCScreen->authPasswdData = (void *)VNC_AUTH_FILE;
260 }
261
Steve Kondik5c8655c2017-06-19 00:28:47 -0700262 return err;
263}
264
265status_t VNCFlinger::startVNCServer() {
Steve Kondik55db0532017-06-12 11:27:18 -0700266 rfbInitServer(mVNCScreen);
267
268 /* Mark as dirty since we haven't sent any updates at all yet. */
269 rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
270
Steve Kondik5c8655c2017-06-19 00:28:47 -0700271 return NO_ERROR;
Steve Kondik55db0532017-06-12 11:27:18 -0700272}
273
Steve Kondik7225c7f2017-06-14 00:06:16 -0700274size_t VNCFlinger::addClient() {
Steve Kondik77754522017-06-14 17:00:33 -0700275 Mutex::Autolock _l(mEventMutex);
Steve Kondik7225c7f2017-06-14 00:06:16 -0700276 if (mClientCount == 0) {
Steve Kondik77754522017-06-14 17:00:33 -0700277 mClientCount++;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700278 InputDevice::getInstance().start(mWidth, mHeight);
Steve Kondik77754522017-06-14 17:00:33 -0700279 mEventCond.signal();
Steve Kondik55db0532017-06-12 11:27:18 -0700280 }
Steve Kondik7225c7f2017-06-14 00:06:16 -0700281
282 ALOGI("Client connected (%zu)", mClientCount);
283
284 return mClientCount;
Steve Kondik55db0532017-06-12 11:27:18 -0700285}
286
Steve Kondik7225c7f2017-06-14 00:06:16 -0700287size_t VNCFlinger::removeClient() {
Steve Kondik77754522017-06-14 17:00:33 -0700288 Mutex::Autolock _l(mEventMutex);
Steve Kondik7225c7f2017-06-14 00:06:16 -0700289 if (mClientCount > 0) {
290 mClientCount--;
291 if (mClientCount == 0) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700292 InputDevice::getInstance().stop();
Steve Kondik77754522017-06-14 17:00:33 -0700293 mEventCond.signal();
Steve Kondik7225c7f2017-06-14 00:06:16 -0700294 }
295 }
296
297 ALOGI("Client disconnected (%zu)", mClientCount);
298
299 return mClientCount;
300}
301
Steve Kondik77754522017-06-14 17:00:33 -0700302void VNCFlinger::processFrame() {
Steve Kondik77754522017-06-14 17:00:33 -0700303 // Take the update mutex. This ensures that we don't dequeue
304 // a new buffer and blow away the one being sent to a client.
305 // The BufferQueue is self-regulating and will drop frames
306 // automatically for us.
307 Mutex::Autolock _l(mUpdateMutex);
308
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700309 // get a frame from the virtual display
Steve Kondik77754522017-06-14 17:00:33 -0700310 CpuConsumer::LockedBuffer imgBuffer;
311 status_t res = mCpuConsumer->lockNextBuffer(&imgBuffer);
312 if (res != OK) {
313 ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
314 return;
315 }
316
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700317 mFrameNumber = imgBuffer.frameNumber;
318 ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700319 imgBuffer.width, imgBuffer.height, imgBuffer.stride);
Steve Kondik77754522017-06-14 17:00:33 -0700320
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700321 // we don't know if there was a stride change until we get
322 // a buffer from the queue. if it changed, we need to resize
323 updateFBSize(imgBuffer);
Steve Kondik77754522017-06-14 17:00:33 -0700324
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700325 // performance is extremely bad if the gpu memory is used
326 // directly without copying because it is likely uncached
327 memcpy(mVNCScreen->frameBuffer, imgBuffer.data, mFrameSize);
Steve Kondik77754522017-06-14 17:00:33 -0700328
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700329 // update clients
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700330 rfbMarkRectAsModified(mVNCScreen, 0, 0, imgBuffer.width, imgBuffer.height);
Steve Kondik77754522017-06-14 17:00:33 -0700331
332 mCpuConsumer->unlockBuffer(imgBuffer);
333}
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700334
335/*
336 * Returns "true" if the device is rotated 90 degrees.
337 */
338bool VNCFlinger::isDeviceRotated(int orientation) {
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700339 return orientation != DISPLAY_ORIENTATION_0 && orientation != DISPLAY_ORIENTATION_180;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700340}
341
342/*
343 * Sets the display projection, based on the display dimensions, video size,
344 * and device orientation.
345 */
346bool VNCFlinger::updateDisplayProjection() {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700347 DisplayInfo info;
348 status_t err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &info);
349 if (err != NO_ERROR) {
350 ALOGE("Failed to get display characteristics\n");
351 return true;
352 }
353
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700354 // Set the region of the layer stack we're interested in, which in our
355 // case is "all of it". If the app is rotated (so that the width of the
356 // app is based on the height of the display), reverse width/height.
357 bool deviceRotated = isDeviceRotated(info.orientation);
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700358 uint32_t sourceWidth, sourceHeight;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700359 if (!deviceRotated) {
360 sourceWidth = info.w;
361 sourceHeight = info.h;
362 } else {
363 ALOGV("using rotated width/height");
364 sourceHeight = info.w;
365 sourceWidth = info.h;
366 }
367
Steve Kondik59104ea2017-06-20 08:30:07 -0700368 uint32_t width = sourceWidth * mScale;
369 uint32_t height = sourceHeight * mScale;
370
371 if (mSourceWidth == sourceWidth && mSourceHeight == sourceHeight &&
372 mWidth == width && mHeight == height &&
373 mOrientation == info.orientation) {
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700374 return false;
375 }
376
Steve Kondik59104ea2017-06-20 08:30:07 -0700377 // orientation / resolution change
378 mSourceWidth = sourceWidth;
379 mSourceHeight = sourceHeight;
380 mWidth = width;
381 mHeight = height;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700382 mOrientation = info.orientation;
383
Steve Kondik59104ea2017-06-20 08:30:07 -0700384 ALOGV("Dimensions: %dx%d [out: %dx%d, scale: %f] orientation=%d",
385 mSourceWidth, mSourceHeight, mWidth, mHeight, mScale, mOrientation);
386
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700387 if (!mVDSActive) {
388 return true;
389 }
390
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700391 // it does not appear to be possible to reconfigure the virtual display
392 // on the fly without forcing surfaceflinger to tear it down
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700393 destroyVirtualDisplayLocked();
394 createVirtualDisplay();
Steve Kondik59104ea2017-06-20 08:30:07 -0700395
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700396 return false;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700397}
398
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700399bool VNCFlinger::updateFBSize(CpuConsumer::LockedBuffer& buf) {
400 uint32_t stride = (uint32_t)mVNCScreen->paddedWidthInBytes / 4;
401 uint32_t width = (uint32_t)mVNCScreen->width;
402 uint32_t height = (uint32_t)mVNCScreen->height;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700403
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700404 uint64_t newSize = buf.stride * buf.height * 4;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700405
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700406 if (stride != buf.stride || height != buf.height || width != buf.width) {
407 ALOGD("updateFBSize: old=[%dx%d %d] new=[%dx%d %d]", width, height, stride, buf.width,
408 buf.height, buf.stride);
409
410 if (mFrameSize != newSize) {
411 mFrameSize = newSize;
412 delete[] mVNCScreen->frameBuffer;
413 rfbNewFramebuffer(mVNCScreen, (char*)new uint8_t[newSize], buf.width, buf.height, 8, 3,
414 4);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700415 }
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700416 mVNCScreen->paddedWidthInBytes = buf.stride * 4;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700417 }
418 return NO_ERROR;
419}
Steve Kondik5f7b0a82017-06-16 09:04:43 -0700420
421// ------------------------------------------------------------------------ //
422
423// libvncserver logger
424void VNCFlinger::rfbLogger(const char* format, ...) {
425 va_list args;
426 char buf[256];
427
428 va_start(args, format);
429 vsprintf(buf, format, args);
430 ALOGI("%s", buf);
431 va_end(args);
432}
433
434// libvncserver callbacks
435ClientGoneHookPtr VNCFlinger::onClientGone(rfbClientPtr cl) {
436 ALOGV("onClientGone");
437 VNCFlinger* vf = (VNCFlinger*)cl->screen->screenData;
438 vf->removeClient();
439 return 0;
440}
441
442enum rfbNewClientAction VNCFlinger::onNewClient(rfbClientPtr cl) {
443 ALOGV("onNewClient");
444 cl->clientGoneHook = (ClientGoneHookPtr)VNCFlinger::onClientGone;
445 VNCFlinger* vf = (VNCFlinger*)cl->screen->screenData;
446 vf->addClient();
447 return RFB_CLIENT_ACCEPT;
448}
449
450void VNCFlinger::onFrameStart(rfbClientPtr cl) {
451 VNCFlinger* vf = (VNCFlinger*)cl->screen->screenData;
452 vf->mUpdateMutex.lock();
453
454 vf->mFrameStartWhen = systemTime(CLOCK_MONOTONIC);
455 ALOGV("frame start [%lu]", vf->mFrameNumber);
456}
457
458void VNCFlinger::onFrameDone(rfbClientPtr cl, int /* status */) {
459 VNCFlinger* vf = (VNCFlinger*)cl->screen->screenData;
460
461 float timing = (systemTime(CLOCK_MONOTONIC) - vf->mFrameStartWhen) / 1000000.0;
462 ALOGV("onFrameDone [%lu] (%.3f ms)", vf->mFrameNumber, timing);
463
464 vf->mUpdateMutex.unlock();
465}
466
467// cpuconsumer frame listener
468void VNCFlinger::FrameListener::onFrameAvailable(const BufferItem& item) {
469 Mutex::Autolock _l(mVNC->mEventMutex);
470 mVNC->mFrameAvailable = true;
471 mVNC->mEventCond.signal();
472 ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
473}