• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "host/frontend/vnc_server/virtual_inputs.h"
18 
19 #include <gflags/gflags.h>
20 #include <android-base/logging.h>
21 #include <linux/input.h>
22 #include <linux/uinput.h>
23 
24 #include <cstdint>
25 #include <mutex>
26 #include <thread>
27 #include "keysyms.h"
28 
29 #include "common/libs/confui/confui.h"
30 #include "common/libs/fs/shared_select.h"
31 #include "host/libs/config/cuttlefish_config.h"
32 #include "host/libs/config/logging.h"
33 
34 using cuttlefish::vnc::VirtualInputs;
35 
36 DEFINE_int32(touch_fd, -1,
37              "A fd for a socket where to accept touch connections");
38 
39 DEFINE_int32(keyboard_fd, -1,
40              "A fd for a socket where to accept keyboard connections");
41 
42 DEFINE_bool(write_virtio_input, false,
43             "Whether to write the virtio_input struct over the socket");
44 
45 namespace {
46 // Necessary to define here as the virtio_input.h header is not available
47 // in the host glibc.
48 struct virtio_input_event {
49   std::uint16_t type;
50   std::uint16_t code;
51   std::int32_t value;
52 };
53 
AddKeyMappings(std::map<uint32_t,uint16_t> * key_mapping)54 void AddKeyMappings(std::map<uint32_t, uint16_t>* key_mapping) {
55   (*key_mapping)[cuttlefish::xk::AltLeft] = KEY_LEFTALT;
56   (*key_mapping)[cuttlefish::xk::ControlLeft] = KEY_LEFTCTRL;
57   (*key_mapping)[cuttlefish::xk::ShiftLeft] = KEY_LEFTSHIFT;
58   (*key_mapping)[cuttlefish::xk::AltRight] = KEY_RIGHTALT;
59   (*key_mapping)[cuttlefish::xk::ControlRight] = KEY_RIGHTCTRL;
60   (*key_mapping)[cuttlefish::xk::ShiftRight] = KEY_RIGHTSHIFT;
61   (*key_mapping)[cuttlefish::xk::MetaLeft] = KEY_LEFTMETA;
62   (*key_mapping)[cuttlefish::xk::MetaRight] = KEY_RIGHTMETA;
63   (*key_mapping)[cuttlefish::xk::MultiKey] = KEY_COMPOSE;
64 
65   (*key_mapping)[cuttlefish::xk::CapsLock] = KEY_CAPSLOCK;
66   (*key_mapping)[cuttlefish::xk::NumLock] = KEY_NUMLOCK;
67   (*key_mapping)[cuttlefish::xk::ScrollLock] = KEY_SCROLLLOCK;
68 
69   (*key_mapping)[cuttlefish::xk::BackSpace] = KEY_BACKSPACE;
70   (*key_mapping)[cuttlefish::xk::Tab] = KEY_TAB;
71   (*key_mapping)[cuttlefish::xk::Return] = KEY_ENTER;
72   (*key_mapping)[cuttlefish::xk::Escape] = KEY_ESC;
73 
74   (*key_mapping)[' '] = KEY_SPACE;
75   (*key_mapping)['!'] = KEY_1;
76   (*key_mapping)['"'] = KEY_APOSTROPHE;
77   (*key_mapping)['#'] = KEY_3;
78   (*key_mapping)['$'] = KEY_4;
79   (*key_mapping)['%'] = KEY_5;
80   (*key_mapping)['^'] = KEY_6;
81   (*key_mapping)['&'] = KEY_7;
82   (*key_mapping)['\''] = KEY_APOSTROPHE;
83   (*key_mapping)['('] = KEY_9;
84   (*key_mapping)[')'] = KEY_0;
85   (*key_mapping)['*'] = KEY_8;
86   (*key_mapping)['+'] = KEY_EQUAL;
87   (*key_mapping)[','] = KEY_COMMA;
88   (*key_mapping)['-'] = KEY_MINUS;
89   (*key_mapping)['.'] = KEY_DOT;
90   (*key_mapping)['/'] = KEY_SLASH;
91   (*key_mapping)['0'] = KEY_0;
92   (*key_mapping)['1'] = KEY_1;
93   (*key_mapping)['2'] = KEY_2;
94   (*key_mapping)['3'] = KEY_3;
95   (*key_mapping)['4'] = KEY_4;
96   (*key_mapping)['5'] = KEY_5;
97   (*key_mapping)['6'] = KEY_6;
98   (*key_mapping)['7'] = KEY_7;
99   (*key_mapping)['8'] = KEY_8;
100   (*key_mapping)['9'] = KEY_9;
101   (*key_mapping)[':'] = KEY_SEMICOLON;
102   (*key_mapping)[';'] = KEY_SEMICOLON;
103   (*key_mapping)['<'] = KEY_COMMA;
104   (*key_mapping)['='] = KEY_EQUAL;
105   (*key_mapping)['>'] = KEY_DOT;
106   (*key_mapping)['?'] = KEY_SLASH;
107   (*key_mapping)['@'] = KEY_2;
108   (*key_mapping)['A'] = KEY_A;
109   (*key_mapping)['B'] = KEY_B;
110   (*key_mapping)['C'] = KEY_C;
111   (*key_mapping)['D'] = KEY_D;
112   (*key_mapping)['E'] = KEY_E;
113   (*key_mapping)['F'] = KEY_F;
114   (*key_mapping)['G'] = KEY_G;
115   (*key_mapping)['H'] = KEY_H;
116   (*key_mapping)['I'] = KEY_I;
117   (*key_mapping)['J'] = KEY_J;
118   (*key_mapping)['K'] = KEY_K;
119   (*key_mapping)['L'] = KEY_L;
120   (*key_mapping)['M'] = KEY_M;
121   (*key_mapping)['N'] = KEY_N;
122   (*key_mapping)['O'] = KEY_O;
123   (*key_mapping)['P'] = KEY_P;
124   (*key_mapping)['Q'] = KEY_Q;
125   (*key_mapping)['R'] = KEY_R;
126   (*key_mapping)['S'] = KEY_S;
127   (*key_mapping)['T'] = KEY_T;
128   (*key_mapping)['U'] = KEY_U;
129   (*key_mapping)['V'] = KEY_V;
130   (*key_mapping)['W'] = KEY_W;
131   (*key_mapping)['X'] = KEY_X;
132   (*key_mapping)['Y'] = KEY_Y;
133   (*key_mapping)['Z'] = KEY_Z;
134   (*key_mapping)['['] = KEY_LEFTBRACE;
135   (*key_mapping)['\\'] = KEY_BACKSLASH;
136   (*key_mapping)[']'] = KEY_RIGHTBRACE;
137   (*key_mapping)['-'] = KEY_MINUS;
138   (*key_mapping)['_'] = KEY_MINUS;
139   (*key_mapping)['`'] = KEY_GRAVE;
140   (*key_mapping)['a'] = KEY_A;
141   (*key_mapping)['b'] = KEY_B;
142   (*key_mapping)['c'] = KEY_C;
143   (*key_mapping)['d'] = KEY_D;
144   (*key_mapping)['e'] = KEY_E;
145   (*key_mapping)['f'] = KEY_F;
146   (*key_mapping)['g'] = KEY_G;
147   (*key_mapping)['h'] = KEY_H;
148   (*key_mapping)['i'] = KEY_I;
149   (*key_mapping)['j'] = KEY_J;
150   (*key_mapping)['k'] = KEY_K;
151   (*key_mapping)['l'] = KEY_L;
152   (*key_mapping)['m'] = KEY_M;
153   (*key_mapping)['n'] = KEY_N;
154   (*key_mapping)['o'] = KEY_O;
155   (*key_mapping)['p'] = KEY_P;
156   (*key_mapping)['q'] = KEY_Q;
157   (*key_mapping)['r'] = KEY_R;
158   (*key_mapping)['s'] = KEY_S;
159   (*key_mapping)['t'] = KEY_T;
160   (*key_mapping)['u'] = KEY_U;
161   (*key_mapping)['v'] = KEY_V;
162   (*key_mapping)['w'] = KEY_W;
163   (*key_mapping)['x'] = KEY_X;
164   (*key_mapping)['y'] = KEY_Y;
165   (*key_mapping)['z'] = KEY_Z;
166   (*key_mapping)['{'] = KEY_LEFTBRACE;
167   (*key_mapping)['\\'] = KEY_BACKSLASH;
168   (*key_mapping)['|'] = KEY_BACKSLASH;
169   (*key_mapping)['}'] = KEY_RIGHTBRACE;
170   (*key_mapping)['~'] = KEY_GRAVE;
171 
172   (*key_mapping)[cuttlefish::xk::F1] = KEY_F1;
173   (*key_mapping)[cuttlefish::xk::F2] = KEY_F2;
174   (*key_mapping)[cuttlefish::xk::F3] = KEY_F3;
175   (*key_mapping)[cuttlefish::xk::F4] = KEY_F4;
176   (*key_mapping)[cuttlefish::xk::F5] = KEY_F5;
177   (*key_mapping)[cuttlefish::xk::F6] = KEY_F6;
178   (*key_mapping)[cuttlefish::xk::F7] = KEY_F7;
179   (*key_mapping)[cuttlefish::xk::F8] = KEY_F8;
180   (*key_mapping)[cuttlefish::xk::F9] = KEY_F9;
181   (*key_mapping)[cuttlefish::xk::F10] = KEY_F10;
182   (*key_mapping)[cuttlefish::xk::F11] = KEY_F11;
183   (*key_mapping)[cuttlefish::xk::F12] = KEY_F12;
184   (*key_mapping)[cuttlefish::xk::F13] = KEY_F13;
185   (*key_mapping)[cuttlefish::xk::F14] = KEY_F14;
186   (*key_mapping)[cuttlefish::xk::F15] = KEY_F15;
187   (*key_mapping)[cuttlefish::xk::F16] = KEY_F16;
188   (*key_mapping)[cuttlefish::xk::F17] = KEY_F17;
189   (*key_mapping)[cuttlefish::xk::F18] = KEY_F18;
190   (*key_mapping)[cuttlefish::xk::F19] = KEY_F19;
191   (*key_mapping)[cuttlefish::xk::F20] = KEY_F20;
192   (*key_mapping)[cuttlefish::xk::F21] = KEY_F21;
193   (*key_mapping)[cuttlefish::xk::F22] = KEY_F22;
194   (*key_mapping)[cuttlefish::xk::F23] = KEY_F23;
195   (*key_mapping)[cuttlefish::xk::F24] = KEY_F24;
196 
197   (*key_mapping)[cuttlefish::xk::Keypad0] = KEY_KP0;
198   (*key_mapping)[cuttlefish::xk::Keypad1] = KEY_KP1;
199   (*key_mapping)[cuttlefish::xk::Keypad2] = KEY_KP2;
200   (*key_mapping)[cuttlefish::xk::Keypad3] = KEY_KP3;
201   (*key_mapping)[cuttlefish::xk::Keypad4] = KEY_KP4;
202   (*key_mapping)[cuttlefish::xk::Keypad5] = KEY_KP5;
203   (*key_mapping)[cuttlefish::xk::Keypad6] = KEY_KP6;
204   (*key_mapping)[cuttlefish::xk::Keypad7] = KEY_KP7;
205   (*key_mapping)[cuttlefish::xk::Keypad8] = KEY_KP8;
206   (*key_mapping)[cuttlefish::xk::Keypad9] = KEY_KP9;
207   (*key_mapping)[cuttlefish::xk::KeypadMultiply] = KEY_KPASTERISK;
208   (*key_mapping)[cuttlefish::xk::KeypadSubtract] = KEY_KPMINUS;
209   (*key_mapping)[cuttlefish::xk::KeypadAdd] = KEY_KPPLUS;
210   (*key_mapping)[cuttlefish::xk::KeypadDecimal] = KEY_KPDOT;
211   (*key_mapping)[cuttlefish::xk::KeypadEnter] = KEY_KPENTER;
212   (*key_mapping)[cuttlefish::xk::KeypadDivide] = KEY_KPSLASH;
213   (*key_mapping)[cuttlefish::xk::KeypadEqual] = KEY_KPEQUAL;
214   (*key_mapping)[cuttlefish::xk::PlusMinus] = KEY_KPPLUSMINUS;
215 
216   (*key_mapping)[cuttlefish::xk::SysReq] = KEY_SYSRQ;
217   (*key_mapping)[cuttlefish::xk::LineFeed] = KEY_LINEFEED;
218   (*key_mapping)[cuttlefish::xk::Home] = KEY_HOME;
219   (*key_mapping)[cuttlefish::xk::Up] = KEY_UP;
220   (*key_mapping)[cuttlefish::xk::PageUp] = KEY_PAGEUP;
221   (*key_mapping)[cuttlefish::xk::Left] = KEY_LEFT;
222   (*key_mapping)[cuttlefish::xk::Right] = KEY_RIGHT;
223   (*key_mapping)[cuttlefish::xk::End] = KEY_END;
224   (*key_mapping)[cuttlefish::xk::Down] = KEY_DOWN;
225   (*key_mapping)[cuttlefish::xk::PageDown] = KEY_PAGEDOWN;
226   (*key_mapping)[cuttlefish::xk::Insert] = KEY_INSERT;
227   (*key_mapping)[cuttlefish::xk::Delete] = KEY_DELETE;
228   (*key_mapping)[cuttlefish::xk::Pause] = KEY_PAUSE;
229   (*key_mapping)[cuttlefish::xk::KeypadSeparator] = KEY_KPCOMMA;
230   (*key_mapping)[cuttlefish::xk::Yen] = KEY_YEN;
231   (*key_mapping)[cuttlefish::xk::Cancel] = KEY_STOP;
232   (*key_mapping)[cuttlefish::xk::Redo] = KEY_AGAIN;
233   (*key_mapping)[cuttlefish::xk::Undo] = KEY_UNDO;
234   (*key_mapping)[cuttlefish::xk::Find] = KEY_FIND;
235   (*key_mapping)[cuttlefish::xk::Print] = KEY_PRINT;
236   (*key_mapping)[cuttlefish::xk::VolumeDown] = KEY_VOLUMEDOWN;
237   (*key_mapping)[cuttlefish::xk::Mute] = KEY_MUTE;
238   (*key_mapping)[cuttlefish::xk::VolumeUp] = KEY_VOLUMEUP;
239   (*key_mapping)[cuttlefish::xk::Menu] = KEY_MENU;
240   (*key_mapping)[cuttlefish::xk::VNCMenu] = KEY_MENU;
241 }
242 
InitInputEvent(struct input_event * evt,uint16_t type,uint16_t code,int32_t value)243 void InitInputEvent(struct input_event* evt, uint16_t type, uint16_t code,
244                     int32_t value) {
245   evt->type = type;
246   evt->code = code;
247   evt->value = value;
248 }
249 
250 }  // namespace
251 
252 class SocketVirtualInputs : public VirtualInputs {
253  public:
SocketVirtualInputs()254   SocketVirtualInputs()
255       : client_connector_([this]() { ClientConnectorLoop(); }) {}
256 
GenerateKeyPressEvent(int key_code,bool down)257   void GenerateKeyPressEvent(int key_code, bool down) override {
258     struct input_event events[2];
259     InitInputEvent(&events[0], EV_KEY, keymapping_[key_code], down);
260     InitInputEvent(&events[1], EV_SYN, 0, 0);
261 
262     SendEvents(keyboard_socket_, events);
263   }
264 
PressPowerButton(bool down)265   void PressPowerButton(bool down) override {
266     struct input_event events[2];
267     InitInputEvent(&events[0], EV_KEY, KEY_POWER, down);
268     InitInputEvent(&events[1], EV_SYN, 0, 0);
269 
270     SendEvents(keyboard_socket_, events);
271   }
272 
HandlePointerEvent(bool touch_down,int x,int y)273   void HandlePointerEvent(bool touch_down, int x, int y) override {
274     // TODO(b/124121375): Use multitouch when available
275     struct input_event events[4];
276     InitInputEvent(&events[0], EV_ABS, ABS_X, x);
277     InitInputEvent(&events[1], EV_ABS, ABS_Y, y);
278     InitInputEvent(&events[2], EV_KEY, BTN_TOUCH, touch_down);
279     InitInputEvent(&events[3], EV_SYN, 0, 0);
280 
281     SendEvents(touch_socket_, events);
282   }
283 
284  private:
285   template<size_t num_events>
SendEvents(cuttlefish::SharedFD socket,struct input_event (& event_buffer)[num_events])286   void SendEvents(cuttlefish::SharedFD socket, struct input_event (&event_buffer)[num_events]) {
287     std::lock_guard<std::mutex> lock(socket_mutex_);
288     if (!socket->IsOpen()) {
289       // This is unlikely as it would only happen between the start of the vnc
290       // server and the connection of the VMM to the socket.
291       // If it happens, just drop the events as the VM is not yet ready to
292       // handle it.
293       return;
294     }
295 
296     if (FLAGS_write_virtio_input) {
297       struct virtio_input_event virtio_events[num_events];
298       for (size_t i = 0; i < num_events; i++) {
299         virtio_events[i] = (struct virtio_input_event) {
300           .type = event_buffer[i].type,
301           .code = event_buffer[i].code,
302           .value = event_buffer[i].value,
303         };
304       }
305       auto ret = socket->Write(virtio_events, sizeof(virtio_events));
306       if (ret < 0) {
307         LOG(ERROR) << "Error sending input events: " << socket->StrError();
308       }
309     } else {
310       auto ret = socket->Write(event_buffer, sizeof(event_buffer));
311       if (ret < 0) {
312         LOG(ERROR) << "Error sending input events: " << socket->StrError();
313       }
314     }
315   }
316 
ClientConnectorLoop()317   void ClientConnectorLoop() {
318     auto touch_server = cuttlefish::SharedFD::Dup(FLAGS_touch_fd);
319     close(FLAGS_touch_fd);
320     FLAGS_touch_fd = -1;
321 
322     auto keyboard_server = cuttlefish::SharedFD::Dup(FLAGS_keyboard_fd);
323     close(FLAGS_keyboard_fd);
324     FLAGS_keyboard_fd = -1;
325     LOG(DEBUG) << "Input socket host accepting connections...";
326 
327     while (1) {
328       cuttlefish::SharedFDSet read_set;
329       read_set.Set(touch_server);
330       read_set.Set(keyboard_server);
331       cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
332       {
333         std::lock_guard<std::mutex> lock(socket_mutex_);
334         if (read_set.IsSet(touch_server)) {
335           touch_socket_ = cuttlefish::SharedFD::Accept(*touch_server);
336           LOG(DEBUG) << "connected to touch";
337         }
338         if (read_set.IsSet(keyboard_server)) {
339           keyboard_socket_ = cuttlefish::SharedFD::Accept(*keyboard_server);
340           LOG(DEBUG) << "connected to keyboard";
341         }
342       }
343     }
344   }
345   cuttlefish::SharedFD touch_socket_;
346   cuttlefish::SharedFD keyboard_socket_;
347   std::thread client_connector_;
348   std::mutex socket_mutex_;
349 };
350 
VirtualInputs()351 VirtualInputs::VirtualInputs() { AddKeyMappings(&keymapping_); }
352 
353 /**
354  * Depending on the host mode (e.g. android, confirmation ui(tee), etc)
355  * deliver the inputs to the right input implementation
356  * e.g. ConfUI's input or regular socket based input
357  */
358 class VirtualInputDemux : public VirtualInputs {
359  public:
VirtualInputDemux(cuttlefish::confui::HostVirtualInput & confui_input)360   VirtualInputDemux(cuttlefish::confui::HostVirtualInput& confui_input)
361       : confui_input_{confui_input} {}
362   virtual ~VirtualInputDemux() = default;
363 
364   virtual void GenerateKeyPressEvent(int code, bool down) override;
365   virtual void PressPowerButton(bool down) override;
366   virtual void HandlePointerEvent(bool touch_down, int x, int y) override;
367 
368  private:
369   SocketVirtualInputs socket_virtual_input_;
370   cuttlefish::confui::HostVirtualInput& confui_input_;
371 };
372 
GenerateKeyPressEvent(int code,bool down)373 void VirtualInputDemux::GenerateKeyPressEvent(int code, bool down) {
374   // confui input is active only in the confirmation UI
375   // also, socket virtual input should be inactive in the confirmation
376   // UI session
377   if (confui_input_.IsConfUiActive()) {
378     if (code == cuttlefish::xk::Menu) {
379       // release menu button in confirmation UI means for now cancel
380       confui_input_.PressCancelButton(down);
381     }
382     ConfUiLog(DEBUG) << "the key" << code << "ignored."
383                      << "currently confirmation UI handles"
384                      << "menu and power only.";
385     return;
386   }
387   socket_virtual_input_.GenerateKeyPressEvent(code, down);
388 }
389 
PressPowerButton(bool down)390 void VirtualInputDemux::PressPowerButton(bool down) {
391   if (confui_input_.IsConfUiActive()) {
392     confui_input_.PressConfirmButton(down);
393     return;
394   }
395   socket_virtual_input_.PressPowerButton(down);
396 }
397 
HandlePointerEvent(bool touch_down,int x,int y)398 void VirtualInputDemux::HandlePointerEvent(bool touch_down, int x, int y) {
399   if (confui_input_.IsConfUiActive()) {
400     ConfUiLog(DEBUG) << "currently confirmation UI ignores pointer events at ("
401                      << x << ", " << y << ")";
402     return;
403   }
404   socket_virtual_input_.HandlePointerEvent(touch_down, x, y);
405 }
406 
Get(cuttlefish::confui::HostVirtualInput & confui_input)407 std::shared_ptr<VirtualInputs> VirtualInputs::Get(
408     cuttlefish::confui::HostVirtualInput& confui_input) {
409   return std::make_shared<VirtualInputDemux>(confui_input);
410 }
411