blob: 5350ef63921c429f6e84b0db77644bd9cda6f45a [file] [log] [blame]
maxwen95dceef2019-12-07 12:00:17 +01001#define LOG_TAG "VNCFlinger:AndroidDesktop"
Steve Kondik961b4cc2017-06-22 18:10:50 -07002#include <utils/Log.h>
3
4#include <fcntl.h>
5#include <sys/eventfd.h>
6
Steve Kondik961b4cc2017-06-22 18:10:50 -07007#include <gui/ISurfaceComposer.h>
8#include <gui/SurfaceComposerClient.h>
9
Steve Kondik961b4cc2017-06-22 18:10:50 -070010#include <rfb/PixelFormat.h>
11#include <rfb/Rect.h>
12#include <rfb/ScreenSet.h>
Steve Kondik961b4cc2017-06-22 18:10:50 -070013
14#include "AndroidDesktop.h"
Steve Kondik6f9ab852017-07-09 21:30:20 -070015#include "AndroidPixelBuffer.h"
Steve Kondik961b4cc2017-06-22 18:10:50 -070016#include "InputDevice.h"
Steve Kondik6f9ab852017-07-09 21:30:20 -070017#include "VirtualDisplay.h"
Steve Kondik961b4cc2017-06-22 18:10:50 -070018
19using namespace vncflinger;
20using namespace android;
21
Steve Kondik961b4cc2017-06-22 18:10:50 -070022AndroidDesktop::AndroidDesktop() {
Steve Kondik961b4cc2017-06-22 18:10:50 -070023 mInputDevice = new InputDevice();
Steve Kondik6f9ab852017-07-09 21:30:20 -070024 mDisplayRect = Rect(0, 0);
Steve Kondik961b4cc2017-06-22 18:10:50 -070025
26 mEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
27 if (mEventFd < 0) {
28 ALOGE("Failed to create event notifier");
29 return;
30 }
31}
32
33AndroidDesktop::~AndroidDesktop() {
34 mInputDevice->stop();
35 close(mEventFd);
36}
37
38void AndroidDesktop::start(rfb::VNCServer* vs) {
Steve Kondik71850752019-09-12 12:45:23 -070039 mServer = vs;
Steve Kondik961b4cc2017-06-22 18:10:50 -070040
Steve Kondik6f9ab852017-07-09 21:30:20 -070041 mPixels = new AndroidPixelBuffer();
42 mPixels->setDimensionsChangedListener(this);
Steve Kondik961b4cc2017-06-22 18:10:50 -070043
Steve Kondik6f9ab852017-07-09 21:30:20 -070044 if (updateDisplayInfo() != NO_ERROR) {
45 ALOGE("Failed to query display!");
46 return;
47 }
Steve Kondik961b4cc2017-06-22 18:10:50 -070048
49 ALOGV("Desktop is running");
50}
51
52void AndroidDesktop::stop() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070053 Mutex::Autolock _L(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070054
55 ALOGV("Shutting down");
56
57 mServer->setPixelBuffer(0);
maxwen95dceef2019-12-07 12:00:17 +010058 mPixels->reset();
Steve Kondik961b4cc2017-06-22 18:10:50 -070059
Steve Kondik6f9ab852017-07-09 21:30:20 -070060 mVirtualDisplay.clear();
61 mPixels.clear();
Steve Kondik961b4cc2017-06-22 18:10:50 -070062}
63
64void AndroidDesktop::processFrames() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070065 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070066
Steve Kondik6f9ab852017-07-09 21:30:20 -070067 updateDisplayInfo();
Steve Kondik961b4cc2017-06-22 18:10:50 -070068
69 // get a frame from the virtual display
70 CpuConsumer::LockedBuffer imgBuffer;
Steve Kondik6f9ab852017-07-09 21:30:20 -070071 status_t res = mVirtualDisplay->getConsumer()->lockNextBuffer(&imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070072 if (res != OK) {
73 ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
74 return;
75 }
76
77 mFrameNumber = imgBuffer.frameNumber;
maxwen95dceef2019-12-07 12:00:17 +010078 //ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
79 // imgBuffer.width, imgBuffer.height, imgBuffer.stride);
Steve Kondik961b4cc2017-06-22 18:10:50 -070080
81 // we don't know if there was a stride change until we get
82 // a buffer from the queue. if it changed, we need to resize
83
84 rfb::Rect bufRect(0, 0, imgBuffer.width, imgBuffer.height);
85
86 // performance is extremely bad if the gpu memory is used
87 // directly without copying because it is likely uncached
88 mPixels->imageRect(bufRect, imgBuffer.data, imgBuffer.stride);
89
Steve Kondik6f9ab852017-07-09 21:30:20 -070090 mVirtualDisplay->getConsumer()->unlockBuffer(imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070091
92 // update clients
93 mServer->add_changed(bufRect);
Steve Kondik961b4cc2017-06-22 18:10:50 -070094}
95
96// notifies the server loop that we have changes
97void AndroidDesktop::notify() {
98 static uint64_t notify = 1;
99 write(mEventFd, &notify, sizeof(notify));
100}
101
102// called when a client resizes the window
103unsigned int AndroidDesktop::setScreenLayout(int reqWidth, int reqHeight,
104 const rfb::ScreenSet& layout) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700105 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700106
107 char* dbg = new char[1024];
108 layout.print(dbg, 1024);
109
Steve Kondik6f9ab852017-07-09 21:30:20 -0700110 ALOGD("setScreenLayout: cur: %s new: %dx%d", dbg, reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700111 delete[] dbg;
112
Steve Kondik6f9ab852017-07-09 21:30:20 -0700113 if (reqWidth == mDisplayRect.getWidth() && reqHeight == mDisplayRect.getHeight()) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700114 return rfb::resultInvalid;
115 }
116
117 if (reqWidth > 0 && reqHeight > 0) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700118 mPixels->setWindowSize(reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700119
Steve Kondik6f9ab852017-07-09 21:30:20 -0700120 rfb::ScreenSet screens;
121 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
122 mServer->setScreenLayout(screens);
123 return rfb::resultSuccess;
Steve Kondik961b4cc2017-06-22 18:10:50 -0700124 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700125
Steve Kondik961b4cc2017-06-22 18:10:50 -0700126 return rfb::resultInvalid;
127}
128
Steve Kondik961b4cc2017-06-22 18:10:50 -0700129// cpuconsumer frame listener, called from binder thread
maxwen95dceef2019-12-07 12:00:17 +0100130void AndroidDesktop::onFrameAvailable(const BufferItem&) {
131 //ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700132
133 notify();
Steve Kondik961b4cc2017-06-22 18:10:50 -0700134}
135
Steve Kondikf19d1422019-09-06 13:52:12 -0700136void AndroidDesktop::keyEvent(rdr::U32 keysym, __unused_attr rdr::U32 keycode, bool down) {
137 mInputDevice->keyEvent(down, keysym);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700138}
139
140void AndroidDesktop::pointerEvent(const rfb::Point& pos, int buttonMask) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700141 if (pos.x < mDisplayRect.left || pos.x > mDisplayRect.right || pos.y < mDisplayRect.top ||
142 pos.y > mDisplayRect.bottom) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700143 // outside viewport
144 return;
145 }
maxwen95dceef2019-12-07 12:00:17 +0100146 uint32_t spaceX = abs(((float)(mDisplayRect.getWidth() - mPixels->width())) / 2);
147 uint32_t x = pos.x - spaceX;
Steve Kondik6f9ab852017-07-09 21:30:20 -0700148 uint32_t y = pos.y * ((float)(mDisplayRect.getHeight()) / (float)mPixels->height());
Steve Kondik961b4cc2017-06-22 18:10:50 -0700149
maxwen95dceef2019-12-07 12:00:17 +0100150 //ALOGV("pointer xlate x1=%d y1=%d x2=%d y2=%d", pos.x, pos.y, x, y);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700151
152 mServer->setCursorPos(rfb::Point(x, y));
153 mInputDevice->pointerEvent(buttonMask, x, y);
154}
155
Steve Kondik6f9ab852017-07-09 21:30:20 -0700156// refresh the display dimensions
157status_t AndroidDesktop::updateDisplayInfo() {
maxwen9dcd4d12019-12-07 01:23:56 +0100158 const auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
159 if (displayToken == nullptr) {
160 ALOGE("Failed to get display token\n");
161 return -1;
162 }
163
maxwen80ee9662021-10-05 21:08:06 +0200164 status_t err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &mDisplayMode);
maxwenad0a9222020-09-20 14:40:41 +0200165 if (err != NO_ERROR) {
166 ALOGE("Failed to get display configuration\n");
167 return err;
168 }
maxwen6a8820f2022-10-12 00:38:14 +0200169 //ALOGV("updateDisplayInfo: [%d:%d]", mDisplayMode.resolution.width, mDisplayMode.resolution.height);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700170
maxwenad0a9222020-09-20 14:40:41 +0200171 err = SurfaceComposerClient::getDisplayState(displayToken, &mDisplayState);
172 if (err != NO_ERROR) {
173 ALOGE("Failed to get current display status");
174 return err;
175 }
176
maxwen80ee9662021-10-05 21:08:06 +0200177 mPixels->setDisplayInfo(&mDisplayMode, &mDisplayState);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700178
179 return NO_ERROR;
180}
Steve Kondik6f9ab852017-07-09 21:30:20 -0700181
Steve Kondik71850752019-09-12 12:45:23 -0700182rfb::ScreenSet AndroidDesktop::computeScreenLayout() {
183 rfb::ScreenSet screens;
184 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
185 return screens;
186 mServer->setScreenLayout(screens);
187}
188
Steve Kondik6f9ab852017-07-09 21:30:20 -0700189void AndroidDesktop::onBufferDimensionsChanged(uint32_t width, uint32_t height) {
190 ALOGV("Dimensions changed: old=(%ux%u) new=(%ux%u)", mDisplayRect.getWidth(),
191 mDisplayRect.getHeight(), width, height);
192
193 mVirtualDisplay.clear();
maxwen80ee9662021-10-05 21:08:06 +0200194 mVirtualDisplay = new VirtualDisplay(&mDisplayMode, &mDisplayState,
maxwenad0a9222020-09-20 14:40:41 +0200195 mPixels->width(), mPixels->height(), this);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700196
197 mDisplayRect = mVirtualDisplay->getDisplayRect();
198
199 mInputDevice->reconfigure(mDisplayRect.getWidth(), mDisplayRect.getHeight());
200
Steve Kondik71850752019-09-12 12:45:23 -0700201 mServer->setPixelBuffer(mPixels.get(), computeScreenLayout());
202 mServer->setScreenLayout(computeScreenLayout());
Steve Kondik6f9ab852017-07-09 21:30:20 -0700203}
Steve Kondikf19d1422019-09-06 13:52:12 -0700204
205void AndroidDesktop::queryConnection(network::Socket* sock, __unused_attr const char* userName) {
206 mServer->approveConnection(sock, true, NULL);
207}
208
209void AndroidDesktop::terminate() {
210 kill(getpid(), SIGTERM);
211}