1 /*
2 * Copyright (C) 2020 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 #define LOG_TAG "ConnectionObserver"
18
19 #include "host/frontend/webrtc/connection_observer.h"
20
21 #include <linux/input.h>
22
23 #include <chrono>
24 #include <map>
25 #include <thread>
26 #include <vector>
27
28 #include <json/json.h>
29
30 #include <android-base/logging.h>
31 #include <android-base/parsedouble.h>
32 #include <gflags/gflags.h>
33
34 #include "common/libs/confui/confui.h"
35 #include "common/libs/fs/shared_buf.h"
36 #include "host/frontend/webrtc/adb_handler.h"
37 #include "host/frontend/webrtc/bluetooth_handler.h"
38 #include "host/frontend/webrtc/gpx_locations_handler.h"
39 #include "host/frontend/webrtc/kml_locations_handler.h"
40 #include "host/frontend/webrtc/libdevice/camera_controller.h"
41 #include "host/frontend/webrtc/libdevice/lights_observer.h"
42 #include "host/frontend/webrtc/location_handler.h"
43 #include "host/libs/config/cuttlefish_config.h"
44 #include "host/libs/input_connector/input_connector.h"
45
46 namespace cuttlefish {
47
48 /**
49 * connection observer implementation for regular android mode.
50 * i.e. when it is not in the confirmation UI mode (or TEE),
51 * the control flow will fall back to this ConnectionObserverForAndroid
52 */
53 class ConnectionObserverImpl : public webrtc_streaming::ConnectionObserver {
54 public:
ConnectionObserverImpl(std::unique_ptr<InputConnector::EventSink> input_events_sink,KernelLogEventsHandler * kernel_log_events_handler,std::map<std::string,SharedFD> commands_to_custom_action_servers,std::weak_ptr<DisplayHandler> display_handler,CameraController * camera_controller,std::shared_ptr<webrtc_streaming::SensorsHandler> sensors_handler,std::shared_ptr<webrtc_streaming::LightsObserver> lights_observer)55 ConnectionObserverImpl(
56 std::unique_ptr<InputConnector::EventSink> input_events_sink,
57 KernelLogEventsHandler *kernel_log_events_handler,
58 std::map<std::string, SharedFD> commands_to_custom_action_servers,
59 std::weak_ptr<DisplayHandler> display_handler,
60 CameraController *camera_controller,
61 std::shared_ptr<webrtc_streaming::SensorsHandler> sensors_handler,
62 std::shared_ptr<webrtc_streaming::LightsObserver> lights_observer)
63 : input_events_sink_(std::move(input_events_sink)),
64 kernel_log_events_handler_(kernel_log_events_handler),
65 commands_to_custom_action_servers_(commands_to_custom_action_servers),
66 weak_display_handler_(display_handler),
67 camera_controller_(camera_controller),
68 sensors_handler_(sensors_handler),
69 lights_observer_(lights_observer) {}
~ConnectionObserverImpl()70 virtual ~ConnectionObserverImpl() {
71 auto display_handler = weak_display_handler_.lock();
72 if (kernel_log_subscription_id_ != -1) {
73 kernel_log_events_handler_->Unsubscribe(kernel_log_subscription_id_);
74 }
75 }
76
OnConnected()77 void OnConnected() override {
78 SendLastFrameAsync(/*all displays*/ std::nullopt);
79 }
80
OnTouchEvent(const std::string & device_label,int x,int y,bool down)81 Result<void> OnTouchEvent(const std::string &device_label, int x, int y,
82 bool down) override {
83 CF_EXPECT(input_events_sink_->SendTouchEvent(device_label, x, y, down));
84 return {};
85 }
86
OnMultiTouchEvent(const std::string & device_label,Json::Value id,Json::Value slot,Json::Value x,Json::Value y,bool down,int size)87 Result<void> OnMultiTouchEvent(const std::string &device_label,
88 Json::Value id, Json::Value slot,
89 Json::Value x, Json::Value y, bool down,
90 int size) {
91 std::vector<MultitouchSlot> slots(size);
92 for (int i = 0; i < size; i++) {
93 slots[i].id = id[i].asInt();
94 slots[i].x = x[i].asInt();
95 slots[i].y = y[i].asInt();
96 }
97 CF_EXPECT(
98 input_events_sink_->SendMultiTouchEvent(device_label, slots, down));
99 return {};
100 }
101
OnKeyboardEvent(uint16_t code,bool down)102 Result<void> OnKeyboardEvent(uint16_t code, bool down) override {
103 CF_EXPECT(input_events_sink_->SendKeyboardEvent(code, down));
104 return {};
105 }
106
OnWheelEvent(int pixels)107 Result<void> OnWheelEvent(int pixels) {
108 CF_EXPECT(input_events_sink_->SendRotaryEvent(pixels));
109 return {};
110 }
111
OnSwitchEvent(uint16_t code,bool state)112 Result<void> OnSwitchEvent(uint16_t code, bool state) {
113 CF_EXPECT(input_events_sink_->SendSwitchesEvent(code, state));
114 return {};
115 }
116
OnAdbChannelOpen(std::function<bool (const uint8_t *,size_t)> adb_message_sender)117 void OnAdbChannelOpen(std::function<bool(const uint8_t *, size_t)>
118 adb_message_sender) override {
119 LOG(VERBOSE) << "Adb Channel open";
120 adb_handler_.reset(new webrtc_streaming::AdbHandler(
121 CuttlefishConfig::Get()->ForDefaultInstance().adb_ip_and_port(),
122 adb_message_sender));
123 }
OnAdbMessage(const uint8_t * msg,size_t size)124 void OnAdbMessage(const uint8_t *msg, size_t size) override {
125 adb_handler_->handleMessage(msg, size);
126 }
OnControlChannelOpen(std::function<bool (const Json::Value)> control_message_sender)127 void OnControlChannelOpen(
128 std::function<bool(const Json::Value)> control_message_sender) override {
129 LOG(VERBOSE) << "Control Channel open";
130 if (camera_controller_) {
131 camera_controller_->SetMessageSender(control_message_sender);
132 }
133 kernel_log_subscription_id_ =
134 kernel_log_events_handler_->AddSubscriber(control_message_sender);
135 }
136
OnLidStateChange(bool lid_open)137 Result<void> OnLidStateChange(bool lid_open) override {
138 // InputManagerService treats a value of 0 as open and 1 as closed, so
139 // invert the lid_switch_open value that is sent to the input device.
140 CF_EXPECT(OnSwitchEvent(SW_LID, !lid_open));
141 return {};
142 }
OnHingeAngleChange(int)143 void OnHingeAngleChange(int /*hinge_angle*/) override {
144 // TODO(b/181157794) Propagate hinge angle sensor data using a custom
145 // Sensor HAL.
146 }
OnPowerButton(bool button_down)147 Result<void> OnPowerButton(bool button_down) override {
148 CF_EXPECT(OnKeyboardEvent(KEY_POWER, button_down));
149 return {};
150 }
OnBackButton(bool button_down)151 Result<void> OnBackButton(bool button_down) override {
152 CF_EXPECT(OnKeyboardEvent(KEY_BACK, button_down));
153 return {};
154 }
OnHomeButton(bool button_down)155 Result<void> OnHomeButton(bool button_down) override {
156 CF_EXPECT(OnKeyboardEvent(KEY_HOMEPAGE, button_down));
157 return {};
158 }
OnMenuButton(bool button_down)159 Result<void> OnMenuButton(bool button_down) override {
160 CF_EXPECT(OnKeyboardEvent(KEY_MENU, button_down));
161 return {};
162 }
OnVolumeDownButton(bool button_down)163 Result<void> OnVolumeDownButton(bool button_down) override {
164 CF_EXPECT(OnKeyboardEvent(KEY_VOLUMEDOWN, button_down));
165 return {};
166 }
OnVolumeUpButton(bool button_down)167 Result<void> OnVolumeUpButton(bool button_down) override {
168 CF_EXPECT(OnKeyboardEvent(KEY_VOLUMEUP, button_down));
169 return {};
170 }
OnCustomActionButton(const std::string & command,const std::string & button_state)171 void OnCustomActionButton(const std::string &command,
172 const std::string &button_state) override {
173 if (commands_to_custom_action_servers_.find(command) !=
174 commands_to_custom_action_servers_.end()) {
175 // Simple protocol for commands forwarded to action servers:
176 // - Always 128 bytes
177 // - Format: command:button_state
178 // - Example: my_button:down
179 std::string action_server_message = command + ":" + button_state;
180 WriteAll(commands_to_custom_action_servers_[command],
181 action_server_message.c_str(), 128);
182 } else {
183 LOG(WARNING) << "Unsupported control command: " << command << " ("
184 << button_state << ")";
185 }
186 }
187
OnBluetoothChannelOpen(std::function<bool (const uint8_t *,size_t)> bluetooth_message_sender)188 void OnBluetoothChannelOpen(std::function<bool(const uint8_t *, size_t)>
189 bluetooth_message_sender) override {
190 LOG(VERBOSE) << "Bluetooth channel open";
191 auto config = CuttlefishConfig::Get();
192 CHECK(config) << "Failed to get config";
193 bluetooth_handler_.reset(new webrtc_streaming::BluetoothHandler(
194 config->rootcanal_test_port(), bluetooth_message_sender));
195 }
196
OnBluetoothMessage(const uint8_t * msg,size_t size)197 void OnBluetoothMessage(const uint8_t *msg, size_t size) override {
198 bluetooth_handler_->handleMessage(msg, size);
199 }
200
OnSensorsChannelOpen(std::function<bool (const uint8_t *,size_t)> sensors_message_sender)201 void OnSensorsChannelOpen(std::function<bool(const uint8_t *, size_t)>
202 sensors_message_sender) override {
203 sensors_subscription_id = sensors_handler_->Subscribe(sensors_message_sender);
204 LOG(VERBOSE) << "Sensors channel open";
205 }
206
OnSensorsChannelClosed()207 void OnSensorsChannelClosed() override {
208 sensors_handler_->UnSubscribe(sensors_subscription_id);
209 }
210
OnSensorsMessage(const uint8_t * msg,size_t size)211 void OnSensorsMessage(const uint8_t *msg, size_t size) override {
212 std::string msgstr(msg, msg + size);
213 std::vector<std::string> xyz = android::base::Split(msgstr, " ");
214
215 if (xyz.size() != 3) {
216 LOG(WARNING) << "Invalid rotation angles: Expected 3, received " << xyz.size();
217 return;
218 }
219
220 double x, y, z;
221 CHECK(android::base::ParseDouble(xyz.at(0), &x))
222 << "X rotation value must be a double";
223 CHECK(android::base::ParseDouble(xyz.at(1), &y))
224 << "Y rotation value must be a double";
225 CHECK(android::base::ParseDouble(xyz.at(2), &z))
226 << "Z rotation value must be a double";
227 sensors_handler_->HandleMessage(x, y, z);
228 }
229
OnLightsChannelOpen(std::function<bool (const Json::Value &)> lights_message_sender)230 void OnLightsChannelOpen(
231 std::function<bool(const Json::Value &)> lights_message_sender) override {
232 LOG(DEBUG) << "Lights channel open";
233
234 lights_subscription_id_ =
235 lights_observer_->Subscribe(lights_message_sender);
236 }
237
OnLightsChannelClosed()238 void OnLightsChannelClosed() override {
239 lights_observer_->Unsubscribe(lights_subscription_id_);
240 }
241
OnLocationChannelOpen(std::function<bool (const uint8_t *,size_t)> location_message_sender)242 void OnLocationChannelOpen(std::function<bool(const uint8_t *, size_t)>
243 location_message_sender) override {
244 LOG(VERBOSE) << "Location channel open";
245 auto config = CuttlefishConfig::Get();
246 CHECK(config) << "Failed to get config";
247 location_handler_.reset(
248 new webrtc_streaming::LocationHandler(location_message_sender));
249 }
OnLocationMessage(const uint8_t * msg,size_t size)250 void OnLocationMessage(const uint8_t *msg, size_t size) override {
251 std::string msgstr(msg, msg + size);
252
253 std::vector<std::string> inputs = android::base::Split(msgstr, ",");
254
255 if (inputs.size() != 3) {
256 LOG(WARNING) << "Invalid location length , length = " << inputs.size();
257 return;
258 }
259
260 float longitude = std::stod(inputs.at(0));
261 float latitude = std::stod(inputs.at(1));
262 float elevation = std::stod(inputs.at(2));
263 location_handler_->HandleMessage(longitude, latitude, elevation);
264 }
265
OnKmlLocationsChannelOpen(std::function<bool (const uint8_t *,size_t)> kml_locations_message_sender)266 void OnKmlLocationsChannelOpen(std::function<bool(const uint8_t *, size_t)>
267 kml_locations_message_sender) override {
268 LOG(VERBOSE) << "Kml Locations channel open";
269 auto config = CuttlefishConfig::Get();
270 CHECK(config) << "Failed to get config";
271 kml_locations_handler_.reset(new webrtc_streaming::KmlLocationsHandler(
272 kml_locations_message_sender));
273 }
OnKmlLocationsMessage(const uint8_t * msg,size_t size)274 void OnKmlLocationsMessage(const uint8_t *msg, size_t size) override {
275 kml_locations_handler_->HandleMessage(msg, size);
276 }
277
OnGpxLocationsChannelOpen(std::function<bool (const uint8_t *,size_t)> gpx_locations_message_sender)278 void OnGpxLocationsChannelOpen(std::function<bool(const uint8_t *, size_t)>
279 gpx_locations_message_sender) override {
280 LOG(VERBOSE) << "Gpx Locations channel open";
281 auto config = CuttlefishConfig::Get();
282 CHECK(config) << "Failed to get config";
283 gpx_locations_handler_.reset(new webrtc_streaming::GpxLocationsHandler(
284 gpx_locations_message_sender));
285 }
OnGpxLocationsMessage(const uint8_t * msg,size_t size)286 void OnGpxLocationsMessage(const uint8_t *msg, size_t size) override {
287 gpx_locations_handler_->HandleMessage(msg, size);
288 }
289
OnCameraControlMsg(const Json::Value & msg)290 void OnCameraControlMsg(const Json::Value &msg) override {
291 if (camera_controller_) {
292 camera_controller_->HandleMessage(msg);
293 } else {
294 LOG(VERBOSE) << "Camera control message received but no camera "
295 "controller is available";
296 }
297 }
298
OnDisplayControlMsg(const Json::Value & msg)299 void OnDisplayControlMsg(const Json::Value &msg) override {
300 static constexpr const char kRefreshDisplay[] = "refresh_display";
301 if (!msg.isMember(kRefreshDisplay)) {
302 LOG(ERROR) << "Unknown display control command.";
303 return;
304 }
305 const auto display_number_json = msg[kRefreshDisplay];
306 if (!display_number_json.isInt()) {
307 LOG(ERROR) << "Invalid display control command.";
308 return;
309 }
310 const auto display_number =
311 static_cast<uint32_t>(display_number_json.asInt());
312 LOG(VERBOSE) << "Refresh display " << display_number;
313 SendLastFrameAsync(display_number);
314 }
315
OnCameraData(const std::vector<char> & data)316 void OnCameraData(const std::vector<char> &data) override {
317 if (camera_controller_) {
318 camera_controller_->HandleMessage(data);
319 } else {
320 LOG(VERBOSE)
321 << "Camera data received but no camera controller is available";
322 }
323 }
324
325 private:
SendLastFrameAsync(std::optional<uint32_t> display_number)326 void SendLastFrameAsync(std::optional<uint32_t> display_number) {
327 auto display_handler = weak_display_handler_.lock();
328 if (display_handler) {
329 std::thread th([this, display_number]() {
330 // The encoder in libwebrtc won't drop 5 consecutive frames due to frame
331 // size, so we make sure at least 5 frames are sent every time a client
332 // connects to ensure they receive at least one.
333 constexpr int kNumFrames = 5;
334 constexpr int kMillisPerFrame = 16;
335 for (int i = 0; i < kNumFrames; ++i) {
336 auto display_handler = weak_display_handler_.lock();
337 display_handler->SendLastFrame(display_number);
338
339 if (i < kNumFrames - 1) {
340 std::this_thread::sleep_for(
341 std::chrono::milliseconds(kMillisPerFrame));
342 }
343 }
344 });
345 th.detach();
346 }
347 }
348
349 std::unique_ptr<InputConnector::EventSink> input_events_sink_;
350 KernelLogEventsHandler *kernel_log_events_handler_;
351 int kernel_log_subscription_id_ = -1;
352 std::shared_ptr<webrtc_streaming::AdbHandler> adb_handler_;
353 std::shared_ptr<webrtc_streaming::BluetoothHandler> bluetooth_handler_;
354 std::shared_ptr<webrtc_streaming::LocationHandler> location_handler_;
355 std::shared_ptr<webrtc_streaming::KmlLocationsHandler> kml_locations_handler_;
356 std::shared_ptr<webrtc_streaming::GpxLocationsHandler> gpx_locations_handler_;
357 std::map<std::string, SharedFD> commands_to_custom_action_servers_;
358 std::weak_ptr<DisplayHandler> weak_display_handler_;
359 CameraController *camera_controller_;
360 std::shared_ptr<webrtc_streaming::SensorsHandler> sensors_handler_;
361 std::shared_ptr<webrtc_streaming::LightsObserver> lights_observer_;
362 int sensors_subscription_id = -1;
363 int lights_subscription_id_ = -1;
364 };
365
CfConnectionObserverFactory(InputConnector & input_connector,KernelLogEventsHandler * kernel_log_events_handler,std::shared_ptr<webrtc_streaming::LightsObserver> lights_observer)366 CfConnectionObserverFactory::CfConnectionObserverFactory(
367 InputConnector &input_connector,
368 KernelLogEventsHandler *kernel_log_events_handler,
369 std::shared_ptr<webrtc_streaming::LightsObserver> lights_observer)
370 : input_connector_(input_connector),
371 kernel_log_events_handler_(kernel_log_events_handler),
372 lights_observer_(lights_observer) {}
373
374 std::shared_ptr<webrtc_streaming::ConnectionObserver>
CreateObserver()375 CfConnectionObserverFactory::CreateObserver() {
376 return std::shared_ptr<webrtc_streaming::ConnectionObserver>(
377 new ConnectionObserverImpl(
378 input_connector_.CreateSink(), kernel_log_events_handler_,
379 commands_to_custom_action_servers_, weak_display_handler_,
380 camera_controller_, shared_sensors_handler_, lights_observer_));
381 }
382
AddCustomActionServer(SharedFD custom_action_server_fd,const std::vector<std::string> & commands)383 void CfConnectionObserverFactory::AddCustomActionServer(
384 SharedFD custom_action_server_fd,
385 const std::vector<std::string> &commands) {
386 for (const std::string &command : commands) {
387 LOG(DEBUG) << "Action server is listening to command: " << command;
388 commands_to_custom_action_servers_[command] = custom_action_server_fd;
389 }
390 }
391
SetDisplayHandler(std::weak_ptr<DisplayHandler> display_handler)392 void CfConnectionObserverFactory::SetDisplayHandler(
393 std::weak_ptr<DisplayHandler> display_handler) {
394 weak_display_handler_ = display_handler;
395 }
396
SetCameraHandler(CameraController * controller)397 void CfConnectionObserverFactory::SetCameraHandler(
398 CameraController *controller) {
399 camera_controller_ = controller;
400 }
401 } // namespace cuttlefish
402