blob: 253eefe1f2cd6295d4850bb7f28bf4ceb4b8aac5 [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
10#include <ui/DisplayInfo.h>
11
12#include <rfb/PixelFormat.h>
13#include <rfb/Rect.h>
14#include <rfb/ScreenSet.h>
Steve Kondik961b4cc2017-06-22 18:10:50 -070015
16#include "AndroidDesktop.h"
Steve Kondik6f9ab852017-07-09 21:30:20 -070017#include "AndroidPixelBuffer.h"
Steve Kondik961b4cc2017-06-22 18:10:50 -070018#include "InputDevice.h"
Steve Kondik6f9ab852017-07-09 21:30:20 -070019#include "VirtualDisplay.h"
Steve Kondik961b4cc2017-06-22 18:10:50 -070020
21using namespace vncflinger;
22using namespace android;
23
Steve Kondik961b4cc2017-06-22 18:10:50 -070024AndroidDesktop::AndroidDesktop() {
Steve Kondik961b4cc2017-06-22 18:10:50 -070025 mInputDevice = new InputDevice();
Steve Kondik6f9ab852017-07-09 21:30:20 -070026 mDisplayRect = Rect(0, 0);
Steve Kondik961b4cc2017-06-22 18:10:50 -070027
28 mEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
29 if (mEventFd < 0) {
30 ALOGE("Failed to create event notifier");
31 return;
32 }
33}
34
35AndroidDesktop::~AndroidDesktop() {
36 mInputDevice->stop();
37 close(mEventFd);
38}
39
40void AndroidDesktop::start(rfb::VNCServer* vs) {
Steve Kondik71850752019-09-12 12:45:23 -070041 mServer = vs;
Steve Kondik961b4cc2017-06-22 18:10:50 -070042
Steve Kondik6f9ab852017-07-09 21:30:20 -070043 mPixels = new AndroidPixelBuffer();
44 mPixels->setDimensionsChangedListener(this);
Steve Kondik961b4cc2017-06-22 18:10:50 -070045
Steve Kondik6f9ab852017-07-09 21:30:20 -070046 if (updateDisplayInfo() != NO_ERROR) {
47 ALOGE("Failed to query display!");
48 return;
49 }
Steve Kondik961b4cc2017-06-22 18:10:50 -070050
51 ALOGV("Desktop is running");
52}
53
54void AndroidDesktop::stop() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070055 Mutex::Autolock _L(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070056
57 ALOGV("Shutting down");
58
59 mServer->setPixelBuffer(0);
maxwen95dceef2019-12-07 12:00:17 +010060 mPixels->reset();
Steve Kondik961b4cc2017-06-22 18:10:50 -070061
Steve Kondik6f9ab852017-07-09 21:30:20 -070062 mVirtualDisplay.clear();
63 mPixels.clear();
Steve Kondik961b4cc2017-06-22 18:10:50 -070064}
65
66void AndroidDesktop::processFrames() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070067 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070068
Steve Kondik6f9ab852017-07-09 21:30:20 -070069 updateDisplayInfo();
Steve Kondik961b4cc2017-06-22 18:10:50 -070070
71 // get a frame from the virtual display
72 CpuConsumer::LockedBuffer imgBuffer;
Steve Kondik6f9ab852017-07-09 21:30:20 -070073 status_t res = mVirtualDisplay->getConsumer()->lockNextBuffer(&imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070074 if (res != OK) {
75 ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
76 return;
77 }
78
79 mFrameNumber = imgBuffer.frameNumber;
maxwen95dceef2019-12-07 12:00:17 +010080 //ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
81 // imgBuffer.width, imgBuffer.height, imgBuffer.stride);
Steve Kondik961b4cc2017-06-22 18:10:50 -070082
83 // we don't know if there was a stride change until we get
84 // a buffer from the queue. if it changed, we need to resize
85
86 rfb::Rect bufRect(0, 0, imgBuffer.width, imgBuffer.height);
87
88 // performance is extremely bad if the gpu memory is used
89 // directly without copying because it is likely uncached
90 mPixels->imageRect(bufRect, imgBuffer.data, imgBuffer.stride);
91
Steve Kondik6f9ab852017-07-09 21:30:20 -070092 mVirtualDisplay->getConsumer()->unlockBuffer(imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070093
94 // update clients
95 mServer->add_changed(bufRect);
Steve Kondik961b4cc2017-06-22 18:10:50 -070096}
97
98// notifies the server loop that we have changes
99void AndroidDesktop::notify() {
100 static uint64_t notify = 1;
101 write(mEventFd, &notify, sizeof(notify));
102}
103
104// called when a client resizes the window
105unsigned int AndroidDesktop::setScreenLayout(int reqWidth, int reqHeight,
106 const rfb::ScreenSet& layout) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700107 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700108
109 char* dbg = new char[1024];
110 layout.print(dbg, 1024);
111
Steve Kondik6f9ab852017-07-09 21:30:20 -0700112 ALOGD("setScreenLayout: cur: %s new: %dx%d", dbg, reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700113 delete[] dbg;
114
Steve Kondik6f9ab852017-07-09 21:30:20 -0700115 if (reqWidth == mDisplayRect.getWidth() && reqHeight == mDisplayRect.getHeight()) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700116 return rfb::resultInvalid;
117 }
118
119 if (reqWidth > 0 && reqHeight > 0) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700120 mPixels->setWindowSize(reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700121
Steve Kondik6f9ab852017-07-09 21:30:20 -0700122 rfb::ScreenSet screens;
123 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
124 mServer->setScreenLayout(screens);
125 return rfb::resultSuccess;
Steve Kondik961b4cc2017-06-22 18:10:50 -0700126 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700127
Steve Kondik961b4cc2017-06-22 18:10:50 -0700128 return rfb::resultInvalid;
129}
130
Steve Kondik961b4cc2017-06-22 18:10:50 -0700131// cpuconsumer frame listener, called from binder thread
maxwen95dceef2019-12-07 12:00:17 +0100132void AndroidDesktop::onFrameAvailable(const BufferItem&) {
133 //ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700134
135 notify();
Steve Kondik961b4cc2017-06-22 18:10:50 -0700136}
137
Steve Kondikf19d1422019-09-06 13:52:12 -0700138void AndroidDesktop::keyEvent(rdr::U32 keysym, __unused_attr rdr::U32 keycode, bool down) {
139 mInputDevice->keyEvent(down, keysym);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700140}
141
142void AndroidDesktop::pointerEvent(const rfb::Point& pos, int buttonMask) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700143 if (pos.x < mDisplayRect.left || pos.x > mDisplayRect.right || pos.y < mDisplayRect.top ||
144 pos.y > mDisplayRect.bottom) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700145 // outside viewport
146 return;
147 }
maxwen95dceef2019-12-07 12:00:17 +0100148 uint32_t spaceX = abs(((float)(mDisplayRect.getWidth() - mPixels->width())) / 2);
149 uint32_t x = pos.x - spaceX;
Steve Kondik6f9ab852017-07-09 21:30:20 -0700150 uint32_t y = pos.y * ((float)(mDisplayRect.getHeight()) / (float)mPixels->height());
Steve Kondik961b4cc2017-06-22 18:10:50 -0700151
maxwen95dceef2019-12-07 12:00:17 +0100152 //ALOGV("pointer xlate x1=%d y1=%d x2=%d y2=%d", pos.x, pos.y, x, y);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700153
154 mServer->setCursorPos(rfb::Point(x, y));
155 mInputDevice->pointerEvent(buttonMask, x, y);
156}
157
Steve Kondik6f9ab852017-07-09 21:30:20 -0700158// refresh the display dimensions
159status_t AndroidDesktop::updateDisplayInfo() {
maxwen9dcd4d12019-12-07 01:23:56 +0100160 const auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
161 if (displayToken == nullptr) {
162 ALOGE("Failed to get display token\n");
163 return -1;
164 }
165
166 status_t err = SurfaceComposerClient::getDisplayInfo(displayToken, &mDisplayInfo);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700167 if (err != NO_ERROR) {
168 ALOGE("Failed to get display characteristics\n");
169 return err;
170 }
maxwenad0a9222020-09-20 14:40:41 +0200171
172 err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &mDisplayConfig);
173 if (err != NO_ERROR) {
174 ALOGE("Failed to get display configuration\n");
175 return err;
176 }
177 ALOGV("updateDisplayInfo: [%d:%d]", mDisplayConfig.resolution.width, mDisplayConfig.resolution.height);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700178
maxwenad0a9222020-09-20 14:40:41 +0200179 err = SurfaceComposerClient::getDisplayState(displayToken, &mDisplayState);
180 if (err != NO_ERROR) {
181 ALOGE("Failed to get current display status");
182 return err;
183 }
184
185 mPixels->setDisplayInfo(&mDisplayConfig, &mDisplayState);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700186
187 return NO_ERROR;
188}
Steve Kondik6f9ab852017-07-09 21:30:20 -0700189
Steve Kondik71850752019-09-12 12:45:23 -0700190rfb::ScreenSet AndroidDesktop::computeScreenLayout() {
191 rfb::ScreenSet screens;
192 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
193 return screens;
194 mServer->setScreenLayout(screens);
195}
196
Steve Kondik6f9ab852017-07-09 21:30:20 -0700197void AndroidDesktop::onBufferDimensionsChanged(uint32_t width, uint32_t height) {
198 ALOGV("Dimensions changed: old=(%ux%u) new=(%ux%u)", mDisplayRect.getWidth(),
199 mDisplayRect.getHeight(), width, height);
200
201 mVirtualDisplay.clear();
maxwenad0a9222020-09-20 14:40:41 +0200202 mVirtualDisplay = new VirtualDisplay(&mDisplayConfig, &mDisplayState,
203 mPixels->width(), mPixels->height(), this);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700204
205 mDisplayRect = mVirtualDisplay->getDisplayRect();
206
207 mInputDevice->reconfigure(mDisplayRect.getWidth(), mDisplayRect.getHeight());
208
Steve Kondik71850752019-09-12 12:45:23 -0700209 mServer->setPixelBuffer(mPixels.get(), computeScreenLayout());
210 mServer->setScreenLayout(computeScreenLayout());
Steve Kondik6f9ab852017-07-09 21:30:20 -0700211}
Steve Kondikf19d1422019-09-06 13:52:12 -0700212
213void AndroidDesktop::queryConnection(network::Socket* sock, __unused_attr const char* userName) {
214 mServer->approveConnection(sock, true, NULL);
215}
216
217void AndroidDesktop::terminate() {
218 kill(getpid(), SIGTERM);
219}