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