1 /*
2 * Copyright (C) 2022 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/webrtc/libdevice/data_channels.h"
18
19 #include <android-base/logging.h>
20
21 #include "host/frontend/webrtc/libcommon/utils.h"
22 #include "host/frontend/webrtc/libdevice/keyboard.h"
23
24 namespace cuttlefish {
25 namespace webrtc_streaming {
26
27 class DataChannelHandler : public webrtc::DataChannelObserver {
28 public:
29 virtual ~DataChannelHandler() = default;
30
31 bool Send(const uint8_t *msg, size_t size, bool binary);
32 bool Send(const Json::Value &message);
33
34 // webrtc::DataChannelObserver implementation
35 void OnStateChange() override;
36 void OnMessage(const webrtc::DataBuffer &msg) override;
37
38 protected:
39 // Provide access to the underlying data channel and the connection observer.
40 virtual rtc::scoped_refptr<webrtc::DataChannelInterface> channel() = 0;
41 virtual std::shared_ptr<ConnectionObserver> observer() = 0;
42
43 // Subclasses must override this to process messages.
44 virtual Result<void> OnMessageInner(const webrtc::DataBuffer &msg) = 0;
45 // Some subclasses may override this to defer some work until the channel is
46 // actually used.
OnFirstMessage()47 virtual void OnFirstMessage() {}
OnStateChangeInner(webrtc::DataChannelInterface::DataState)48 virtual void OnStateChangeInner(webrtc::DataChannelInterface::DataState) {}
49
GetBinarySender()50 std::function<bool(const uint8_t *, size_t len)> GetBinarySender() {
51 return [this](const uint8_t *msg, size_t size) {
52 return Send(msg, size, true /*binary*/);
53 };
54 }
GetJSONSender()55 std::function<bool(const Json::Value &)> GetJSONSender() {
56 return [this](const Json::Value &msg) { return Send(msg); };
57 }
58 private:
59 bool first_msg_received_ = false;
60 };
61
62 namespace {
63
64 static constexpr auto kInputChannelLabel = "input-channel";
65 static constexpr auto kAdbChannelLabel = "adb-channel";
66 static constexpr auto kBluetoothChannelLabel = "bluetooth-channel";
67 static constexpr auto kCameraDataChannelLabel = "camera-data-channel";
68 static constexpr auto kSensorsDataChannelLabel = "sensors-channel";
69 static constexpr auto kLightsChannelLabel = "lights-channel";
70 static constexpr auto kLocationDataChannelLabel = "location-channel";
71 static constexpr auto kKmlLocationsDataChannelLabel = "kml-locations-channel";
72 static constexpr auto kGpxLocationsDataChannelLabel = "gpx-locations-channel";
73 static constexpr auto kCameraDataEof = "EOF";
74
75 // These classes use the Template pattern to minimize code repetition between
76 // data channel handlers.
77
78 class InputChannelHandler : public DataChannelHandler {
79 public:
OnMessageInner(const webrtc::DataBuffer & msg)80 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
81 // TODO: jemoreira - consider binary protocol to avoid JSON parsing
82 // overhead
83 CF_EXPECT(!msg.binary, "Received invalid (binary) data on input channel");
84 auto size = msg.size();
85
86 Json::Value evt;
87 Json::CharReaderBuilder builder;
88 std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
89 std::string error_message;
90 auto str = msg.data.cdata<char>();
91 CF_EXPECTF(json_reader->parse(str, str + size, &evt, &error_message),
92 "Received invalid JSON object over control channel: '{}'",
93 error_message);
94
95 CF_EXPECTF(evt.isMember("type") && evt["type"].isString(),
96 "Input event doesn't have a valid 'type' field: ",
97 evt.toStyledString());
98 auto event_type = evt["type"].asString();
99
100 if (event_type == "mouseMove") {
101 CF_EXPECT(ValidateJsonObject(evt, "mouseMove",
102 {{"x", Json::ValueType::intValue},
103 {"y", Json::ValueType::intValue}}));
104 int32_t x = evt["x"].asInt();
105 int32_t y = evt["y"].asInt();
106
107 CF_EXPECT(observer()->OnMouseMoveEvent(x, y));
108 } else if (event_type == "mouseButton") {
109 CF_EXPECT(ValidateJsonObject(evt, "mouseButton",
110 {{"button", Json::ValueType::intValue},
111 {"down", Json::ValueType::intValue}}));
112 int32_t button = evt["button"].asInt();
113 int32_t down = evt["down"].asInt();
114
115 CF_EXPECT(observer()->OnMouseButtonEvent(button, down));
116 } else if (event_type == "mouseWheel") {
117 CF_EXPECT(ValidateJsonObject(evt, "mouseWheel",
118 {{"pixels", Json::ValueType::intValue}}));
119 auto pixels = evt["pixels"].asInt();
120 CF_EXPECT(observer()->OnMouseWheelEvent(pixels));
121 } else if (event_type == "multi-touch") {
122 CF_EXPECT(
123 ValidateJsonObject(evt, "multi-touch",
124 {{"id", Json::ValueType::arrayValue},
125 {"down", Json::ValueType::intValue},
126 {"x", Json::ValueType::arrayValue},
127 {"y", Json::ValueType::arrayValue},
128 {"device_label", Json::ValueType::stringValue}}));
129
130 auto label = evt["device_label"].asString();
131 auto idArr = evt["id"];
132 int32_t down = evt["down"].asInt();
133 auto xArr = evt["x"];
134 auto yArr = evt["y"];
135 auto slotArr = evt["slot"];
136 int size = evt["id"].size();
137
138 CF_EXPECT(observer()->OnMultiTouchEvent(label, idArr, slotArr, xArr, yArr,
139 down, size));
140 } else if (event_type == "keyboard") {
141 CF_EXPECT(
142 ValidateJsonObject(evt, "keyboard",
143 {{"event_type", Json::ValueType::stringValue},
144 {"keycode", Json::ValueType::stringValue}}));
145 auto down = evt["event_type"].asString() == std::string("keydown");
146 auto code = DomKeyCodeToLinux(evt["keycode"].asString());
147 CF_EXPECT(observer()->OnKeyboardEvent(code, down));
148 } else if (event_type == "wheel") {
149 CF_EXPECT(ValidateJsonObject(evt, "wheel",
150 {{"pixels", Json::ValueType::intValue}}));
151 auto pixels = evt["pixels"].asInt();
152 CF_EXPECT(observer()->OnRotaryWheelEvent(pixels));
153 } else {
154 return CF_ERRF("Unrecognized event type: '{}'", event_type);
155 }
156 return {};
157 }
158 };
159
160 class ControlChannelHandler : public DataChannelHandler {
161 public:
OnStateChangeInner(webrtc::DataChannelInterface::DataState state)162 void OnStateChangeInner(
163 webrtc::DataChannelInterface::DataState state) override {
164 if (state == webrtc::DataChannelInterface::kOpen) {
165 observer()->OnControlChannelOpen(GetJSONSender());
166 }
167 }
OnMessageInner(const webrtc::DataBuffer & msg)168 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
169 auto msg_str = msg.data.cdata<char>();
170 auto size = msg.size();
171 Json::Value evt;
172 Json::CharReaderBuilder builder;
173 std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
174 std::string error_message;
175 CF_EXPECTF(
176 json_reader->parse(msg_str, msg_str + size, &evt, &error_message),
177 "Received invalid JSON object over control channel: '{}'",
178 error_message);
179
180 CF_EXPECT(ValidateJsonObject(
181 evt, "command",
182 /*required_fields=*/{{"command", Json::ValueType::stringValue}},
183 /*optional_fields=*/
184 {
185 {"button_state", Json::ValueType::stringValue},
186 {"lid_switch_open", Json::ValueType::booleanValue},
187 {"hinge_angle_value", Json::ValueType::intValue},
188 }));
189 auto command = evt["command"].asString();
190
191 if (command == "device_state") {
192 if (evt.isMember("lid_switch_open")) {
193 CF_EXPECT(
194 observer()->OnLidStateChange(evt["lid_switch_open"].asBool()));
195 }
196 if (evt.isMember("hinge_angle_value")) {
197 observer()->OnHingeAngleChange(evt["hinge_angle_value"].asInt());
198 }
199 return {};
200 } else if (command.rfind("camera_", 0) == 0) {
201 observer()->OnCameraControlMsg(evt);
202 return {};
203 } else if (command == "display") {
204 observer()->OnDisplayControlMsg(evt);
205 return {};
206 }
207
208 auto button_state = evt["button_state"].asString();
209 LOG(VERBOSE) << "Control command: " << command << " (" << button_state
210 << ")";
211 if (command == "power") {
212 CF_EXPECT(observer()->OnPowerButton(button_state == "down"));
213 } else if (command == "back") {
214 CF_EXPECT(observer()->OnBackButton(button_state == "down"));
215 } else if (command == "home") {
216 CF_EXPECT(observer()->OnHomeButton(button_state == "down"));
217 } else if (command == "menu") {
218 CF_EXPECT(observer()->OnMenuButton(button_state == "down"));
219 } else if (command == "volumedown") {
220 CF_EXPECT(observer()->OnVolumeDownButton(button_state == "down"));
221 } else if (command == "volumeup") {
222 CF_EXPECT(observer()->OnVolumeUpButton(button_state == "down"));
223 } else {
224 observer()->OnCustomActionButton(command, button_state);
225 }
226 return {};
227 }
228 };
229
230 class AdbChannelHandler : public DataChannelHandler {
231 public:
OnMessageInner(const webrtc::DataBuffer & msg)232 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
233 observer()->OnAdbMessage(msg.data.cdata(), msg.size());
234 return {};
235 }
OnFirstMessage()236 void OnFirstMessage() override {
237 // Report the adb channel as open on the first message received instead of
238 // at channel open, this avoids unnecessarily connecting to the adb daemon
239 // for clients that don't use ADB.
240 observer()->OnAdbChannelOpen(GetBinarySender());
241 }
242 };
243
244 class BluetoothChannelHandler : public DataChannelHandler {
245 public:
OnMessageInner(const webrtc::DataBuffer & msg)246 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
247 observer()->OnBluetoothMessage(msg.data.cdata(), msg.size());
248 return {};
249 }
OnFirstMessage()250 void OnFirstMessage() override {
251 // Notify bluetooth channel opening when actually using the channel,
252 // it has the same reason with AdbChannelHandler::OnMessageInner,
253 // to avoid unnecessary connection for Rootcanal.
254 observer()->OnBluetoothChannelOpen(GetBinarySender());
255 }
256 };
257
258 class CameraChannelHandler : public DataChannelHandler {
259 public:
OnMessageInner(const webrtc::DataBuffer & msg)260 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
261 auto msg_data = msg.data.cdata<char>();
262 if (msg.size() == strlen(kCameraDataEof) &&
263 !strncmp(msg_data, kCameraDataEof, msg.size())) {
264 // Send complete buffer to observer on EOF marker
265 observer()->OnCameraData(receive_buffer_);
266 receive_buffer_.clear();
267 return {};
268 }
269 // Otherwise buffer up data
270 receive_buffer_.insert(receive_buffer_.end(), msg_data,
271 msg_data + msg.size());
272 return {};
273 }
274
275 private:
276 std::vector<char> receive_buffer_;
277 };
278
279 // TODO(b/297361564)
280 class SensorsChannelHandler : public DataChannelHandler {
281 public:
OnFirstMessage()282 void OnFirstMessage() override { observer()->OnSensorsChannelOpen(GetBinarySender()); }
OnMessageInner(const webrtc::DataBuffer & msg)283 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
284 if (!first_msg_received_) {
285 first_msg_received_ = true;
286 return {};
287 }
288 observer()->OnSensorsMessage(msg.data.cdata(), msg.size());
289 return {};
290 }
291
OnStateChangeInner(webrtc::DataChannelInterface::DataState state)292 void OnStateChangeInner(webrtc::DataChannelInterface::DataState state) override {
293 if (state == webrtc::DataChannelInterface::kClosed) {
294 observer()->OnSensorsChannelClosed();
295 }
296 }
297
298 private:
299 bool first_msg_received_ = false;
300 };
301
302 class LightsChannelHandler : public DataChannelHandler {
303 public:
304 // We do not expect any messages from the frontend.
OnMessageInner(const webrtc::DataBuffer & msg)305 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
306 return {};
307 }
308
OnStateChangeInner(webrtc::DataChannelInterface::DataState state)309 void OnStateChangeInner(
310 webrtc::DataChannelInterface::DataState state) override {
311 if (state == webrtc::DataChannelInterface::kOpen) {
312 observer()->OnLightsChannelOpen(GetJSONSender());
313 } else if (state == webrtc::DataChannelInterface::kClosed) {
314 observer()->OnLightsChannelClosed();
315 }
316 }
317 };
318
319 class LocationChannelHandler : public DataChannelHandler {
320 public:
OnMessageInner(const webrtc::DataBuffer & msg)321 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
322 observer()->OnLocationMessage(msg.data.cdata(), msg.size());
323 return {};
324 }
OnFirstMessage()325 void OnFirstMessage() override {
326 // Notify location channel opening when actually using the channel,
327 // it has the same reason with AdbChannelHandler::OnMessageInner,
328 // to avoid unnecessary connections.
329 observer()->OnLocationChannelOpen(GetBinarySender());
330 }
331 };
332
333 class KmlLocationChannelHandler : public DataChannelHandler {
334 public:
OnMessageInner(const webrtc::DataBuffer & msg)335 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
336 observer()->OnKmlLocationsMessage(msg.data.cdata(), msg.size());
337 return {};
338 }
OnFirstMessage()339 void OnFirstMessage() override {
340 // Notify location channel opening when actually using the channel,
341 // it has the same reason with AdbChannelHandler::OnMessageInner,
342 // to avoid unnecessary connections.
343 observer()->OnKmlLocationsChannelOpen(GetBinarySender());
344 }
345 };
346
347 class GpxLocationChannelHandler : public DataChannelHandler {
348 public:
OnMessageInner(const webrtc::DataBuffer & msg)349 Result<void> OnMessageInner(const webrtc::DataBuffer &msg) override {
350 observer()->OnGpxLocationsMessage(msg.data.cdata(), msg.size());
351 return {};
352 }
OnFirstMessage()353 void OnFirstMessage() override {
354 // Notify location channel opening when actually using the channel,
355 // it has the same reason with AdbChannelHandler::OnMessageInner,
356 // to avoid unnecessary connections.
357 observer()->OnGpxLocationsChannelOpen(GetBinarySender());
358 }
359 };
360
361 class UnknownChannelHandler : public DataChannelHandler {
362 public:
OnMessageInner(const webrtc::DataBuffer &)363 Result<void> OnMessageInner(const webrtc::DataBuffer &) override {
364 LOG(WARNING) << "Message received on unknown channel: "
365 << channel()->label();
366 return {};
367 }
368 };
369
370 template <typename H>
371 class DataChannelHandlerImpl : public H {
372 public:
DataChannelHandlerImpl(rtc::scoped_refptr<webrtc::DataChannelInterface> channel,std::shared_ptr<ConnectionObserver> observer)373 DataChannelHandlerImpl(
374 rtc::scoped_refptr<webrtc::DataChannelInterface> channel,
375 std::shared_ptr<ConnectionObserver> observer)
376 : channel_(channel), observer_(observer) {
377 channel->RegisterObserver(this);
378 }
~DataChannelHandlerImpl()379 ~DataChannelHandlerImpl() override { channel_->UnregisterObserver(); }
380
381 protected:
382 // DataChannelHandler implementation
channel()383 rtc::scoped_refptr<webrtc::DataChannelInterface> channel() override {
384 return channel_;
385 }
observer()386 std::shared_ptr<ConnectionObserver> observer() override { return observer_; }
387
388 private:
389 rtc::scoped_refptr<webrtc::DataChannelInterface> channel_;
390 std::shared_ptr<ConnectionObserver> observer_;
391 };
392
393 } // namespace
394
Send(const uint8_t * msg,size_t size,bool binary)395 bool DataChannelHandler::Send(const uint8_t *msg, size_t size, bool binary) {
396 webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size), binary);
397 // TODO (b/185832105): When the SCTP channel is congested data channel
398 // messages are buffered up to 16MB, when the buffer is full the channel
399 // is abruptly closed. Keep track of the buffered data to avoid losing the
400 // adb data channel.
401 return channel()->Send(buffer);
402 }
403
Send(const Json::Value & message)404 bool DataChannelHandler::Send(const Json::Value &message) {
405 Json::StreamWriterBuilder factory;
406 std::string message_string = Json::writeString(factory, message);
407 return Send(reinterpret_cast<const uint8_t *>(message_string.c_str()),
408 message_string.size(), /*binary=*/false);
409 }
410
OnStateChange()411 void DataChannelHandler::OnStateChange() {
412 LOG(VERBOSE) << channel()->label() << " channel state changed to "
413 << webrtc::DataChannelInterface::DataStateString(
414 channel()->state());
415 OnStateChangeInner(channel()->state());
416 }
417
OnMessage(const webrtc::DataBuffer & msg)418 void DataChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
419 if (!first_msg_received_) {
420 first_msg_received_ = true;
421 OnFirstMessage();
422 }
423 auto res = OnMessageInner(msg);
424 if (!res.ok()) {
425 LOG(ERROR) << res.error().FormatForEnv();
426 }
427 }
428
DataChannelHandlers(std::shared_ptr<ConnectionObserver> observer)429 DataChannelHandlers::DataChannelHandlers(
430 std::shared_ptr<ConnectionObserver> observer)
431 : observer_(observer) {}
432
~DataChannelHandlers()433 DataChannelHandlers::~DataChannelHandlers() {}
434
OnDataChannelOpen(rtc::scoped_refptr<webrtc::DataChannelInterface> channel)435 void DataChannelHandlers::OnDataChannelOpen(
436 rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
437 auto label = channel->label();
438 LOG(VERBOSE) << "Data channel connected: " << label;
439 if (label == kInputChannelLabel) {
440 input_.reset(
441 new DataChannelHandlerImpl<InputChannelHandler>(channel, observer_));
442 } else if (label == kControlChannelLabel) {
443 control_.reset(
444 new DataChannelHandlerImpl<ControlChannelHandler>(channel, observer_));
445 } else if (label == kAdbChannelLabel) {
446 adb_.reset(
447 new DataChannelHandlerImpl<AdbChannelHandler>(channel, observer_));
448 } else if (label == kBluetoothChannelLabel) {
449 bluetooth_.reset(new DataChannelHandlerImpl<BluetoothChannelHandler>(
450 channel, observer_));
451 } else if (label == kCameraDataChannelLabel) {
452 camera_.reset(
453 new DataChannelHandlerImpl<CameraChannelHandler>(channel, observer_));
454 } else if (label == kLightsChannelLabel) {
455 lights_.reset(
456 new DataChannelHandlerImpl<LightsChannelHandler>(channel, observer_));
457 } else if (label == kLocationDataChannelLabel) {
458 location_.reset(
459 new DataChannelHandlerImpl<LocationChannelHandler>(channel, observer_));
460 } else if (label == kKmlLocationsDataChannelLabel) {
461 kml_location_.reset(new DataChannelHandlerImpl<KmlLocationChannelHandler>(
462 channel, observer_));
463 } else if (label == kGpxLocationsDataChannelLabel) {
464 gpx_location_.reset(new DataChannelHandlerImpl<GpxLocationChannelHandler>(
465 channel, observer_));
466 } else if (label == kSensorsDataChannelLabel) {
467 sensors_.reset(new DataChannelHandlerImpl<SensorsChannelHandler>(
468 channel, observer_));
469 } else {
470 unknown_channels_.emplace_back(
471 new DataChannelHandlerImpl<UnknownChannelHandler>(channel, observer_));
472 }
473 }
474
475 } // namespace webrtc_streaming
476 } // namespace cuttlefish
477