• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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/sensors_handler.h"
18 
19 #include <android-base/logging.h>
20 
21 #include <sstream>
22 #include <string>
23 
24 namespace cuttlefish {
25 namespace webrtc_streaming {
26 
27 namespace {
28 static constexpr sensors::SensorsMask kUiSupportedSensors =
29     (1 << sensors::kAccelerationId) | (1 << sensors::kGyroscopeId) |
30     (1 << sensors::kMagneticId) | (1 << sensors::kRotationVecId);
31 }  // namespace
32 
SensorsHandler(SharedFD sensors_fd)33 SensorsHandler::SensorsHandler(SharedFD sensors_fd)
34     : channel_(transport::SharedFdChannel(sensors_fd, sensors_fd)) {
35   auto refresh_result = RefreshSensors(0, 0, 0);
36   if (!refresh_result.ok()) {
37     LOG(ERROR) << "Failed to refresh sensors: "
38                << refresh_result.error().FormatForEnv();
39   }
40 }
41 
~SensorsHandler()42 SensorsHandler::~SensorsHandler() {}
43 
RefreshSensors(const double x,const double y,const double z)44 Result<void> SensorsHandler::RefreshSensors(const double x, const double y,
45                                             const double z) {
46   std::stringstream ss;
47   ss << x << sensors::INNER_DELIM << y << sensors::INNER_DELIM << z;
48   auto msg = ss.str();
49   auto size = msg.size();
50   auto cmd = sensors::kUpdateRotationVec;
51   auto request = CF_EXPECT(transport::CreateMessage(cmd, size),
52                            "Failed to allocate message for cmd: "
53                                << cmd << " with size: " << size << " bytes. ");
54   std::memcpy(request->payload, msg.data(), size);
55   CF_EXPECT(channel_.SendRequest(*request),
56             "Can't send request for cmd: " << cmd);
57   return {};
58 }
59 
GetSensorsData()60 Result<std::string> SensorsHandler::GetSensorsData() {
61   auto msg = std::to_string(kUiSupportedSensors);
62   auto size = msg.size();
63   auto cmd = sensors::kGetSensorsData;
64   auto request = CF_EXPECT(transport::CreateMessage(cmd, size),
65                            "Failed to allocate message for cmd: "
66                                << cmd << " with size: " << size << " bytes. ");
67   std::memcpy(request->payload, msg.data(), size);
68   CF_EXPECT(channel_.SendRequest(*request),
69             "Can't send request for cmd: " << cmd);
70   auto response =
71       CF_EXPECT(channel_.ReceiveMessage(), "Couldn't receive message.");
72   cmd = response->command;
73   auto is_response = response->is_response;
74   CF_EXPECT((cmd == sensors::kGetSensorsData) && is_response,
75             "Unexpected cmd: " << cmd << ", response: " << is_response);
76   return std::string(reinterpret_cast<const char*>(response->payload),
77                      response->payload_size);
78 }
79 
80 // Get new sensor values and send them to client.
HandleMessage(const double x,const double y,const double z)81 void SensorsHandler::HandleMessage(const double x, const double y, const double z) {
82   auto refresh_result = RefreshSensors(x, y, z);
83   if (!refresh_result.ok()) {
84     LOG(ERROR) << "Failed to refresh sensors: "
85                << refresh_result.error().FormatForEnv();
86     return;
87   }
88   UpdateSensorsUi();
89 }
90 
Subscribe(std::function<void (const uint8_t *,size_t)> send_to_client)91 int SensorsHandler::Subscribe(std::function<void(const uint8_t*, size_t)> send_to_client) {
92   int subscriber_id = ++last_client_channel_id_;
93   {
94     std::lock_guard<std::mutex> lock(subscribers_mtx_);
95     client_channels_[subscriber_id] = send_to_client;
96   }
97 
98   // Send device's initial state to the new client.
99   auto result = GetSensorsData();
100   if (!result.ok()) {
101     LOG(ERROR) << "Failed to get sensors data: "
102                << result.error().FormatForEnv();
103     return subscriber_id;
104   }
105   auto new_sensors_data = std::move(result.value());
106   const uint8_t* message =
107       reinterpret_cast<const uint8_t*>(new_sensors_data.c_str());
108   send_to_client(message, new_sensors_data.size());
109 
110   return subscriber_id;
111 }
112 
UnSubscribe(int subscriber_id)113 void SensorsHandler::UnSubscribe(int subscriber_id) {
114   std::lock_guard<std::mutex> lock(subscribers_mtx_);
115   client_channels_.erase(subscriber_id);
116 }
117 
UpdateSensorsUi()118 void SensorsHandler::UpdateSensorsUi() {
119   auto result = GetSensorsData();
120   if (!result.ok()) {
121     LOG(ERROR) << "Failed to get sensors data: "
122                << result.error().FormatForEnv();
123     return;
124   }
125   auto new_sensors_data = std::move(result.value());
126   const uint8_t* message =
127       reinterpret_cast<const uint8_t*>(new_sensors_data.c_str());
128   std::lock_guard<std::mutex> lock(subscribers_mtx_);
129   for (auto itr = client_channels_.begin(); itr != client_channels_.end();
130        itr++) {
131     itr->second(message, new_sensors_data.size());
132   }
133 }
134 
135 }  // namespace webrtc_streaming
136 }  // namespace cuttlefish
137