Home | History | Annotate | Download | only in vsoc_input_service
      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 "vsoc_input_service.h"
     18 
     19 #include <linux/input.h>
     20 #include <linux/uinput.h>
     21 
     22 #include <thread>
     23 
     24 #include "log/log.h"
     25 
     26 #include "common/vsoc/lib/screen_region_view.h"
     27 #include "common/vsoc/lib/input_events_region_view.h"
     28 
     29 using vsoc::screen::ScreenRegionView;
     30 using vsoc::input_events::InputEvent;
     31 using vsoc::input_events::InputEventsRegionView;
     32 using vsoc_input_service::VirtualDeviceBase;
     33 using vsoc_input_service::VirtualKeyboard;
     34 using vsoc_input_service::VirtualPowerButton;
     35 using vsoc_input_service::VirtualTouchScreen;
     36 using vsoc_input_service::VSoCInputService;
     37 
     38 namespace {
     39 
     40 void EventLoop(std::shared_ptr<VirtualDeviceBase> device,
     41                std::function<int(InputEvent*, int)> next_events) {
     42   while (1) {
     43     InputEvent events[InputEventsRegionView::kMaxEventsPerPacket];
     44     int count = next_events(events, InputEventsRegionView::kMaxEventsPerPacket);
     45     if (count <= 0) {
     46       SLOGE("Error getting events from the queue: Maybe check packet size");
     47       continue;
     48     }
     49     for (int i = 0; i < count; ++i) {
     50       device->EmitEvent(events[i].type, events[i].code, events[i].value);
     51     }
     52   }
     53 }
     54 
     55 }  // namespace
     56 
     57 bool VSoCInputService::SetUpDevices() {
     58   virtual_power_button_.reset(new VirtualPowerButton());
     59   if (!virtual_power_button_->SetUp()) {
     60     return false;
     61   }
     62   virtual_keyboard_.reset(new VirtualKeyboard());
     63   if (!virtual_keyboard_->SetUp()) {
     64     return false;
     65   }
     66 
     67   auto screen_view = ScreenRegionView::GetInstance();
     68   if (!screen_view) {
     69     SLOGE("Failed to open framebuffer broadcast region");
     70     return false;
     71   }
     72 
     73   virtual_touchscreen_.reset(
     74       new VirtualTouchScreen(screen_view->x_res(), screen_view->y_res()));
     75   if (!virtual_touchscreen_->SetUp()) {
     76     return false;
     77   }
     78 
     79   return true;
     80 }
     81 
     82 bool VSoCInputService::ProcessEvents() {
     83   auto input_events_rv = InputEventsRegionView::GetInstance();
     84   // TODO(jemoreira): Post available devices to region
     85   auto worker = input_events_rv->StartWorker();
     86 
     87   // Start device threads
     88   std::thread screen_thread([this]() {
     89     EventLoop(
     90         virtual_touchscreen_, [](InputEvent* event_buffer, int max_events) {
     91           return InputEventsRegionView::GetInstance()->GetScreenEventsOrWait(
     92               event_buffer, max_events);
     93         });
     94   });
     95   std::thread keyboard_thread([this]() {
     96     EventLoop(virtual_keyboard_, [](InputEvent* event_buffer, int max_events) {
     97       return InputEventsRegionView::GetInstance()->GetKeyboardEventsOrWait(
     98           event_buffer, max_events);
     99     });
    100   });
    101   std::thread button_thread([this]() {
    102     EventLoop(virtual_power_button_,
    103               [](InputEvent* event_buffer, int max_events) {
    104                 return InputEventsRegionView::GetInstance()
    105                     ->GetPowerButtonEventsOrWait(event_buffer, max_events);
    106               });
    107   });
    108 
    109   screen_thread.join();
    110   keyboard_thread.join();
    111   button_thread.join();
    112 
    113   // Should never return
    114   return false;
    115 }
    116