1 /*
2  * Copyright (C) 2023 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.0f
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/libs/confui/host_virtual_input.h"
18 
19 #include <android-base/logging.h>
20 
21 namespace cuttlefish {
22 namespace confui {
23 
HostVirtualInput(HostServer & host_server,HostModeCtrl & host_mode_ctrl,InputConnector & android_mode_input)24 HostVirtualInput::HostVirtualInput(HostServer& host_server,
25                                    HostModeCtrl& host_mode_ctrl,
26                                    InputConnector& android_mode_input)
27     : host_server_(host_server),
28       host_mode_ctrl_(host_mode_ctrl),
29       android_mode_input_(android_mode_input) {}
30 
UserAbortEvent()31 void HostVirtualInput::UserAbortEvent() { host_server_.UserAbortEvent(); }
32 
IsConfUiActive()33 bool HostVirtualInput::IsConfUiActive() {
34   return host_mode_ctrl_.IsConfirmatioUiMode();
35 }
36 
37 class HostVirtualInputEventSink : public InputConnector::EventSink {
38  public:
HostVirtualInputEventSink(std::unique_ptr<EventSink> android_mode_input,HostVirtualInput & host_virtual_input)39   HostVirtualInputEventSink(std::unique_ptr<EventSink> android_mode_input,
40                             HostVirtualInput& host_virtual_input)
41       : android_mode_input_(std::move(android_mode_input)),
42         host_virtual_input_(host_virtual_input) {}
43 
44   // EventSink implementation
45   Result<void> SendMouseMoveEvent(int x, int y) override;
46   Result<void> SendMouseButtonEvent(int button, bool down) override;
47   Result<void> SendMouseWheelEvent(int pixels) override;
48   Result<void> SendTouchEvent(const std::string& device_label, int x, int y,
49                               bool down) override;
50   Result<void> SendMultiTouchEvent(const std::string& device_label,
51                                    const std::vector<MultitouchSlot>& slots,
52                                    bool down) override;
53   Result<void> SendKeyboardEvent(uint16_t code, bool down) override;
54   Result<void> SendRotaryEvent(int pixels) override;
55   Result<void> SendSwitchesEvent(uint16_t code, bool state) override;
56 
57  private:
58   std::unique_ptr<EventSink> android_mode_input_;
59   HostVirtualInput& host_virtual_input_;
60 };
61 
SendMouseMoveEvent(int x,int y)62 Result<void> HostVirtualInputEventSink::SendMouseMoveEvent(int x, int y) {
63   ConfUiLog(INFO) << "Sending mouse move event: " << x << "," << y;
64   return android_mode_input_->SendMouseMoveEvent(x, y);
65 }
66 
SendMouseButtonEvent(int button,bool down)67 Result<void> HostVirtualInputEventSink::SendMouseButtonEvent(int button,
68                                                              bool down) {
69   ConfUiLog(INFO) << "Sending mouse button event: " << button << "," << down;
70   return android_mode_input_->SendMouseButtonEvent(button, down);
71 }
72 
SendMouseWheelEvent(int pixels)73 Result<void> HostVirtualInputEventSink::SendMouseWheelEvent(int pixels) {
74   ConfUiLog(INFO) << "Sending mouse wheel event: " << pixels;
75   return android_mode_input_->SendMouseWheelEvent(pixels);
76 }
77 
SendTouchEvent(const std::string & device_label,int x,int y,bool down)78 Result<void> HostVirtualInputEventSink::SendTouchEvent(
79     const std::string& device_label, int x, int y, bool down) {
80   if (!host_virtual_input_.IsConfUiActive()) {
81     return android_mode_input_->SendTouchEvent(device_label, x, y, down);
82   }
83 
84   if (down) {
85     ConfUiLog(INFO) << "TouchEvent occurs in Confirmation UI Mode at [" << x
86                     << ", " << y << "]";
87     host_virtual_input_.host_server().TouchEvent(x, y, down);
88   }
89   return {};
90 }
91 
SendMultiTouchEvent(const std::string & device_label,const std::vector<MultitouchSlot> & slots,bool down)92 Result<void> HostVirtualInputEventSink::SendMultiTouchEvent(
93     const std::string& device_label, const std::vector<MultitouchSlot>& slots,
94     bool down) {
95   if (!host_virtual_input_.IsConfUiActive()) {
96     CF_EXPECT(
97         android_mode_input_->SendMultiTouchEvent(device_label, slots, down));
98     return {};
99   }
100   for (auto& slot : slots) {
101     if (down) {
102       auto this_x = slot.x;
103       auto this_y = slot.y;
104       ConfUiLog(INFO) << "TouchEvent occurs in Confirmation UI Mode at ["
105                       << this_x << ", " << this_y << "]";
106       host_virtual_input_.host_server().TouchEvent(this_x, this_y, down);
107     }
108   }
109   return {};
110 }
111 
SendKeyboardEvent(uint16_t code,bool down)112 Result<void> HostVirtualInputEventSink::SendKeyboardEvent(uint16_t code,
113                                                           bool down) {
114   if (!host_virtual_input_.IsConfUiActive()) {
115     CF_EXPECT(android_mode_input_->SendKeyboardEvent(code, down));
116     return {};
117   }
118   ConfUiLog(VERBOSE) << "keyboard event ignored in confirmation UI mode";
119   return {};
120 }
121 
SendRotaryEvent(int pixels)122 Result<void> HostVirtualInputEventSink::SendRotaryEvent(int pixels) {
123   if (!host_virtual_input_.IsConfUiActive()) {
124     CF_EXPECT(android_mode_input_->SendRotaryEvent(pixels));
125     return {};
126   }
127   ConfUiLog(VERBOSE) << "rotary event ignored in confirmation UI mode";
128   return {};
129 }
130 
SendSwitchesEvent(uint16_t code,bool state)131 Result<void> HostVirtualInputEventSink::SendSwitchesEvent(uint16_t code,
132                                                           bool state) {
133   if (!host_virtual_input_.IsConfUiActive()) {
134     CF_EXPECT(android_mode_input_->SendSwitchesEvent(code, state));
135     return {};
136   }
137   ConfUiLog(VERBOSE) << "switches event ignored in confirmation UI mode";
138   return {};
139 }
140 
CreateSink()141 std::unique_ptr<InputConnector::EventSink> HostVirtualInput::CreateSink() {
142   return std::unique_ptr<EventSink>(
143       new HostVirtualInputEventSink(android_mode_input_.CreateSink(), *this));
144 }
145 
146 }  // namespace confui
147 }  // namespace cuttlefish
148