blob: b40b1b4e2aceffd66ec62208c3110f2f4de42323 [file] [log] [blame]
Steve Kondik961b4cc2017-06-22 18:10:50 -07001#define LOG_TAG "AndroidDesktop"
2#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 Kondik961b4cc2017-06-22 18:10:50 -070041 mMainDpy = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
Steve Kondik961b4cc2017-06-22 18:10:50 -070042
Steve Kondik71850752019-09-12 12:45:23 -070043 mServer = vs;
Steve Kondik961b4cc2017-06-22 18:10:50 -070044
Steve Kondik6f9ab852017-07-09 21:30:20 -070045 mPixels = new AndroidPixelBuffer();
46 mPixels->setDimensionsChangedListener(this);
Steve Kondik961b4cc2017-06-22 18:10:50 -070047
Steve Kondik6f9ab852017-07-09 21:30:20 -070048 if (updateDisplayInfo() != NO_ERROR) {
49 ALOGE("Failed to query display!");
50 return;
51 }
Steve Kondik961b4cc2017-06-22 18:10:50 -070052
53 ALOGV("Desktop is running");
54}
55
56void AndroidDesktop::stop() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070057 Mutex::Autolock _L(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070058
59 ALOGV("Shutting down");
60
61 mServer->setPixelBuffer(0);
Steve Kondik961b4cc2017-06-22 18:10:50 -070062
Steve Kondik6f9ab852017-07-09 21:30:20 -070063 mVirtualDisplay.clear();
64 mPixels.clear();
Steve Kondik961b4cc2017-06-22 18:10:50 -070065}
66
67void AndroidDesktop::processFrames() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070068 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070069
Steve Kondik6f9ab852017-07-09 21:30:20 -070070 updateDisplayInfo();
Steve Kondik961b4cc2017-06-22 18:10:50 -070071
72 // get a frame from the virtual display
73 CpuConsumer::LockedBuffer imgBuffer;
Steve Kondik6f9ab852017-07-09 21:30:20 -070074 status_t res = mVirtualDisplay->getConsumer()->lockNextBuffer(&imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070075 if (res != OK) {
76 ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
77 return;
78 }
79
80 mFrameNumber = imgBuffer.frameNumber;
81 ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
82 imgBuffer.width, imgBuffer.height, imgBuffer.stride);
83
84 // we don't know if there was a stride change until we get
85 // a buffer from the queue. if it changed, we need to resize
86
87 rfb::Rect bufRect(0, 0, imgBuffer.width, imgBuffer.height);
88
89 // performance is extremely bad if the gpu memory is used
90 // directly without copying because it is likely uncached
91 mPixels->imageRect(bufRect, imgBuffer.data, imgBuffer.stride);
92
Steve Kondik6f9ab852017-07-09 21:30:20 -070093 mVirtualDisplay->getConsumer()->unlockBuffer(imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070094
95 // update clients
96 mServer->add_changed(bufRect);
Steve Kondik961b4cc2017-06-22 18:10:50 -070097}
98
99// notifies the server loop that we have changes
100void AndroidDesktop::notify() {
101 static uint64_t notify = 1;
102 write(mEventFd, &notify, sizeof(notify));
103}
104
105// called when a client resizes the window
106unsigned int AndroidDesktop::setScreenLayout(int reqWidth, int reqHeight,
107 const rfb::ScreenSet& layout) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700108 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700109
110 char* dbg = new char[1024];
111 layout.print(dbg, 1024);
112
Steve Kondik6f9ab852017-07-09 21:30:20 -0700113 ALOGD("setScreenLayout: cur: %s new: %dx%d", dbg, reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700114 delete[] dbg;
115
Steve Kondik6f9ab852017-07-09 21:30:20 -0700116 if (reqWidth == mDisplayRect.getWidth() && reqHeight == mDisplayRect.getHeight()) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700117 return rfb::resultInvalid;
118 }
119
120 if (reqWidth > 0 && reqHeight > 0) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700121 mPixels->setWindowSize(reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700122
Steve Kondik6f9ab852017-07-09 21:30:20 -0700123 rfb::ScreenSet screens;
124 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
125 mServer->setScreenLayout(screens);
126 return rfb::resultSuccess;
Steve Kondik961b4cc2017-06-22 18:10:50 -0700127 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700128
Steve Kondik961b4cc2017-06-22 18:10:50 -0700129 return rfb::resultInvalid;
130}
131
Steve Kondik961b4cc2017-06-22 18:10:50 -0700132// cpuconsumer frame listener, called from binder thread
Steve Kondik6f9ab852017-07-09 21:30:20 -0700133void AndroidDesktop::onFrameAvailable(const BufferItem& item) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700134 ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700135
136 notify();
Steve Kondik961b4cc2017-06-22 18:10:50 -0700137}
138
Steve Kondikf19d1422019-09-06 13:52:12 -0700139void AndroidDesktop::keyEvent(rdr::U32 keysym, __unused_attr rdr::U32 keycode, bool down) {
140 mInputDevice->keyEvent(down, keysym);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700141}
142
143void AndroidDesktop::pointerEvent(const rfb::Point& pos, int buttonMask) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700144 if (pos.x < mDisplayRect.left || pos.x > mDisplayRect.right || pos.y < mDisplayRect.top ||
145 pos.y > mDisplayRect.bottom) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700146 // outside viewport
147 return;
148 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700149 uint32_t x = pos.x * ((float)(mDisplayRect.getWidth()) / (float)mPixels->width());
150 uint32_t y = pos.y * ((float)(mDisplayRect.getHeight()) / (float)mPixels->height());
Steve Kondik961b4cc2017-06-22 18:10:50 -0700151
Steve Kondik6f9ab852017-07-09 21:30:20 -0700152 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() {
160 status_t err = SurfaceComposerClient::getDisplayInfo(mMainDpy, &mDisplayInfo);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700161 if (err != NO_ERROR) {
162 ALOGE("Failed to get display characteristics\n");
163 return err;
164 }
165
Steve Kondik6f9ab852017-07-09 21:30:20 -0700166 mPixels->setDisplayInfo(&mDisplayInfo);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700167
168 return NO_ERROR;
169}
Steve Kondik6f9ab852017-07-09 21:30:20 -0700170
Steve Kondik71850752019-09-12 12:45:23 -0700171rfb::ScreenSet AndroidDesktop::computeScreenLayout() {
172 rfb::ScreenSet screens;
173 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
174 return screens;
175 mServer->setScreenLayout(screens);
176}
177
Steve Kondik6f9ab852017-07-09 21:30:20 -0700178void AndroidDesktop::onBufferDimensionsChanged(uint32_t width, uint32_t height) {
179 ALOGV("Dimensions changed: old=(%ux%u) new=(%ux%u)", mDisplayRect.getWidth(),
180 mDisplayRect.getHeight(), width, height);
181
182 mVirtualDisplay.clear();
183 mVirtualDisplay = new VirtualDisplay(&mDisplayInfo, mPixels->width(), mPixels->height(), this);
184
185 mDisplayRect = mVirtualDisplay->getDisplayRect();
186
187 mInputDevice->reconfigure(mDisplayRect.getWidth(), mDisplayRect.getHeight());
188
Steve Kondik71850752019-09-12 12:45:23 -0700189 mServer->setPixelBuffer(mPixels.get(), computeScreenLayout());
190 mServer->setScreenLayout(computeScreenLayout());
Steve Kondik6f9ab852017-07-09 21:30:20 -0700191}
Steve Kondikf19d1422019-09-06 13:52:12 -0700192
193void AndroidDesktop::queryConnection(network::Socket* sock, __unused_attr const char* userName) {
194 mServer->approveConnection(sock, true, NULL);
195}
196
197void AndroidDesktop::terminate() {
198 kill(getpid(), SIGTERM);
199}