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.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 #pragma once
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <cstdlib>
22 #include <map>
23 #include <memory>
24 #include <mutex>
25 #include <utility>
26 #include <vector>
27 
28 #include "common/libs/utils/result.h"
29 #include "host/libs/input_connector/event_buffer.h"
30 #include "host/libs/input_connector/input_connection.h"
31 #include "host/libs/input_connector/input_connector.h"
32 
33 namespace cuttlefish {
34 
35 class InputDevice {
36  public:
InputDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)37   InputDevice(std::unique_ptr<InputConnection> conn, InputEventType event_type)
38       : conn_(std::move(conn)), event_type_(event_type) {}
39   virtual ~InputDevice() = default;
40 
41  protected:
conn()42   InputConnection& conn() { return *conn_; }
event_type()43   InputEventType event_type() const { return event_type_; }
44 
45  private:
46   std::unique_ptr<InputConnection> conn_;
47   InputEventType event_type_;
48 };
49 
50 class TouchDevice : public InputDevice {
51  public:
TouchDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)52   TouchDevice(std::unique_ptr<InputConnection> conn, InputEventType event_type)
53       : InputDevice(std::move(conn), event_type) {}
54 
55   Result<void> SendTouchEvent(int x, int y, bool down);
56 
57   Result<void> SendMultiTouchEvent(const std::vector<MultitouchSlot>& slots,
58                                    bool down);
59 
60   // The InputConnector holds state of on-going touch contacts. Event sources
61   // that can't produce multi touch events should call this function when it's
62   // known they won't produce any more events (because, for example, the
63   // streaming client disconnected) to make sure no stale touch contacts
64   // remain. This addresses issues arising from clients disconnecting in the
65   // middle of a touch action.
66   void OnDisconnectedSource(void* source);
67 
68  private:
WriteEvents(const EventBuffer & buffer)69   Result<void> WriteEvents(const EventBuffer& buffer) {
70     CF_EXPECT(conn().WriteEvents(buffer.data(), buffer.size()));
71     return {};
72   }
73 
74   bool HasSlot(void* source, int32_t id);
75 
76   int32_t GetOrAcquireSlot(void* source, int32_t id);
77 
78   void ReleaseSlot(void* source, int32_t id);
79 
NumActiveSlots()80   size_t NumActiveSlots() {
81     std::lock_guard<std::mutex> lock(slots_mtx_);
82     return slots_by_source_and_id_.size();
83   }
84 
NewTrackingId()85   int NewTrackingId() { return ++tracking_id_; }
86 
87   int32_t UseNewSlot();
88 
89   std::mutex slots_mtx_;
90   std::map<std::pair<void*, int32_t>, int32_t> slots_by_source_and_id_;
91   std::vector<bool> active_slots_;
92   std::atomic<int> tracking_id_ = 0;
93 };
94 
95 class MouseDevice : public InputDevice {
96  public:
MouseDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)97   MouseDevice(std::unique_ptr<InputConnection> conn, InputEventType event_type)
98       : InputDevice(std::move(conn), event_type) {}
99 
100   Result<void> SendMoveEvent(int x, int y);
101   Result<void> SendButtonEvent(int button, bool down);
102   Result<void> SendWheelEvent(int pixels);
103 };
104 
105 class KeyboardDevice : public InputDevice {
106  public:
KeyboardDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)107   KeyboardDevice(std::unique_ptr<InputConnection> conn,
108                  InputEventType event_type)
109       : InputDevice(std::move(conn), event_type) {}
110 
111   Result<void> SendEvent(uint16_t code, bool down);
112 };
113 
114 class RotaryDevice : public InputDevice {
115  public:
RotaryDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)116   RotaryDevice(std::unique_ptr<InputConnection> conn, InputEventType event_type)
117       : InputDevice(std::move(conn), event_type) {}
118 
119   Result<void> SendEvent(int pixels);
120 };
121 
122 class SwitchesDevice : public InputDevice {
123  public:
SwitchesDevice(std::unique_ptr<InputConnection> conn,InputEventType event_type)124   SwitchesDevice(std::unique_ptr<InputConnection> conn,
125                  InputEventType event_type)
126       : InputDevice(std::move(conn), event_type) {}
127 
128   Result<void> SendEvent(uint16_t code, bool state);
129 };
130 
131 }  // namespace cuttlefish
132