blob: 190ca8638c6a5d5907b3ece3fc3f348820e76a8f [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 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);
Steve Kondik961b4cc2017-06-22 18:10:50 -070060
Steve Kondik6f9ab852017-07-09 21:30:20 -070061 mVirtualDisplay.clear();
62 mPixels.clear();
Steve Kondik961b4cc2017-06-22 18:10:50 -070063}
64
65void AndroidDesktop::processFrames() {
Steve Kondik6f9ab852017-07-09 21:30:20 -070066 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -070067
Steve Kondik6f9ab852017-07-09 21:30:20 -070068 updateDisplayInfo();
Steve Kondik961b4cc2017-06-22 18:10:50 -070069
70 // get a frame from the virtual display
71 CpuConsumer::LockedBuffer imgBuffer;
Steve Kondik6f9ab852017-07-09 21:30:20 -070072 status_t res = mVirtualDisplay->getConsumer()->lockNextBuffer(&imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070073 if (res != OK) {
74 ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
75 return;
76 }
77
78 mFrameNumber = imgBuffer.frameNumber;
79 ALOGV("processFrame: [%lu] format: %x (%dx%d, stride=%d)", mFrameNumber, imgBuffer.format,
80 imgBuffer.width, imgBuffer.height, imgBuffer.stride);
81
82 // we don't know if there was a stride change until we get
83 // a buffer from the queue. if it changed, we need to resize
84
85 rfb::Rect bufRect(0, 0, imgBuffer.width, imgBuffer.height);
86
87 // performance is extremely bad if the gpu memory is used
88 // directly without copying because it is likely uncached
89 mPixels->imageRect(bufRect, imgBuffer.data, imgBuffer.stride);
90
Steve Kondik6f9ab852017-07-09 21:30:20 -070091 mVirtualDisplay->getConsumer()->unlockBuffer(imgBuffer);
Steve Kondik961b4cc2017-06-22 18:10:50 -070092
93 // update clients
94 mServer->add_changed(bufRect);
Steve Kondik961b4cc2017-06-22 18:10:50 -070095}
96
97// notifies the server loop that we have changes
98void AndroidDesktop::notify() {
99 static uint64_t notify = 1;
100 write(mEventFd, &notify, sizeof(notify));
101}
102
103// called when a client resizes the window
104unsigned int AndroidDesktop::setScreenLayout(int reqWidth, int reqHeight,
105 const rfb::ScreenSet& layout) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700106 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700107
108 char* dbg = new char[1024];
109 layout.print(dbg, 1024);
110
Steve Kondik6f9ab852017-07-09 21:30:20 -0700111 ALOGD("setScreenLayout: cur: %s new: %dx%d", dbg, reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700112 delete[] dbg;
113
Steve Kondik6f9ab852017-07-09 21:30:20 -0700114 if (reqWidth == mDisplayRect.getWidth() && reqHeight == mDisplayRect.getHeight()) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700115 return rfb::resultInvalid;
116 }
117
118 if (reqWidth > 0 && reqHeight > 0) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700119 mPixels->setWindowSize(reqWidth, reqHeight);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700120
Steve Kondik6f9ab852017-07-09 21:30:20 -0700121 rfb::ScreenSet screens;
122 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
123 mServer->setScreenLayout(screens);
124 return rfb::resultSuccess;
Steve Kondik961b4cc2017-06-22 18:10:50 -0700125 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700126
Steve Kondik961b4cc2017-06-22 18:10:50 -0700127 return rfb::resultInvalid;
128}
129
Steve Kondik961b4cc2017-06-22 18:10:50 -0700130// cpuconsumer frame listener, called from binder thread
Steve Kondik6f9ab852017-07-09 21:30:20 -0700131void AndroidDesktop::onFrameAvailable(const BufferItem& item) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700132 ALOGV("onFrameAvailable: [%lu] mTimestamp=%ld", item.mFrameNumber, item.mTimestamp);
Steve Kondik6f9ab852017-07-09 21:30:20 -0700133
134 notify();
Steve Kondik961b4cc2017-06-22 18:10:50 -0700135}
136
Steve Kondikf19d1422019-09-06 13:52:12 -0700137void AndroidDesktop::keyEvent(rdr::U32 keysym, __unused_attr rdr::U32 keycode, bool down) {
138 mInputDevice->keyEvent(down, keysym);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700139}
140
141void AndroidDesktop::pointerEvent(const rfb::Point& pos, int buttonMask) {
Steve Kondik6f9ab852017-07-09 21:30:20 -0700142 if (pos.x < mDisplayRect.left || pos.x > mDisplayRect.right || pos.y < mDisplayRect.top ||
143 pos.y > mDisplayRect.bottom) {
Steve Kondik961b4cc2017-06-22 18:10:50 -0700144 // outside viewport
145 return;
146 }
Steve Kondik6f9ab852017-07-09 21:30:20 -0700147 uint32_t x = pos.x * ((float)(mDisplayRect.getWidth()) / (float)mPixels->width());
148 uint32_t y = pos.y * ((float)(mDisplayRect.getHeight()) / (float)mPixels->height());
Steve Kondik961b4cc2017-06-22 18:10:50 -0700149
Steve Kondik6f9ab852017-07-09 21:30:20 -0700150 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
164 status_t err = SurfaceComposerClient::getDisplayInfo(displayToken, &mDisplayInfo);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700165 if (err != NO_ERROR) {
166 ALOGE("Failed to get display characteristics\n");
167 return err;
168 }
169
Steve Kondik6f9ab852017-07-09 21:30:20 -0700170 mPixels->setDisplayInfo(&mDisplayInfo);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700171
172 return NO_ERROR;
173}
Steve Kondik6f9ab852017-07-09 21:30:20 -0700174
Steve Kondik71850752019-09-12 12:45:23 -0700175rfb::ScreenSet AndroidDesktop::computeScreenLayout() {
176 rfb::ScreenSet screens;
177 screens.add_screen(rfb::Screen(0, 0, 0, mPixels->width(), mPixels->height(), 0));
178 return screens;
179 mServer->setScreenLayout(screens);
180}
181
Steve Kondik6f9ab852017-07-09 21:30:20 -0700182void AndroidDesktop::onBufferDimensionsChanged(uint32_t width, uint32_t height) {
183 ALOGV("Dimensions changed: old=(%ux%u) new=(%ux%u)", mDisplayRect.getWidth(),
184 mDisplayRect.getHeight(), width, height);
185
186 mVirtualDisplay.clear();
187 mVirtualDisplay = new VirtualDisplay(&mDisplayInfo, mPixels->width(), mPixels->height(), this);
188
189 mDisplayRect = mVirtualDisplay->getDisplayRect();
190
191 mInputDevice->reconfigure(mDisplayRect.getWidth(), mDisplayRect.getHeight());
192
Steve Kondik71850752019-09-12 12:45:23 -0700193 mServer->setPixelBuffer(mPixels.get(), computeScreenLayout());
194 mServer->setScreenLayout(computeScreenLayout());
Steve Kondik6f9ab852017-07-09 21:30:20 -0700195}
Steve Kondikf19d1422019-09-06 13:52:12 -0700196
197void AndroidDesktop::queryConnection(network::Socket* sock, __unused_attr const char* userName) {
198 mServer->approveConnection(sock, true, NULL);
199}
200
201void AndroidDesktop::terminate() {
202 kill(getpid(), SIGTERM);
203}