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