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