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