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