Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/cvd/cuttlefish/common/libs/sensors/sensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ inline constexpr char OUTER_DELIM = ' ';
inline constexpr int kUpdateRotationVec = 0;
inline constexpr int kGetSensorsData = 1;
inline constexpr int kUpdateHal = 2;
inline constexpr int kUpdateHingeAngle = 3;

using SensorsCmd = int;

Expand Down
8 changes: 7 additions & 1 deletion base/cvd/cuttlefish/host/commands/sensors_simulator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ Result<void> ProcessWebrtcRequest(transport::SharedFdChannel& channel,
CF_EXPECT((ss >> y >> delimiter) && (delimiter == INNER_DELIM),
kReqMisFormatted);
CF_EXPECT(static_cast<bool>(ss >> z), kReqMisFormatted);
sensors_simulator.RefreshSensors(x, y, z);
sensors_simulator.SetMotion(x, y, z);
break;
}
case kUpdateHingeAngle: {
float angle;
CF_EXPECT(static_cast<bool>(ss >> angle), kReqMisFormatted);
sensors_simulator.SetHingeAngle(angle);
break;
}
case kGetSensorsData: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

#include "cuttlefish/host/commands/sensors_simulator/sensors_hal_proxy.h"

#include <mutex>
#include <string>

#include "absl/log/check.h"
#include "absl/log/log.h"

Expand All @@ -35,6 +38,13 @@ static constexpr SensorsMask kContinuousModeSensors =
(1 << kPressureId) | (1 << kUncalibGyroscopeId) |
(1 << kUncalibAccelerationId) | (1 << kLightId);

/*
On-change sensors are only reported to the guest when their value changes
(and once after the guest HAL (re)starts), instead of being streamed every
cycle like the continuous mode sensors above.
*/
static constexpr SensorsMask kOnChangeSensors = (1 << kHingeAngle0Id);

Result<std::string> SensorIdToName(int id) {
switch (id) {
case kAccelerationId:
Expand Down Expand Up @@ -162,6 +172,10 @@ SensorsHalProxy::SensorsHalProxy(SharedFD control_from_guest_fd,
sensors_simulator_(sensors_simulator) {
const SensorsMask host_enabled_sensors = HostEnabledSensors(device_type);

sensors_simulator_.SetSensorsChangedCallback(
host_enabled_sensors & kOnChangeSensors,
[this](SensorsMask changed) { ReportToGuest(changed); });

req_responder_thread_ = std::thread([this, host_enabled_sensors] {
while (running_) {
auto result = ProcessHalRequest(control_channel_, hal_activated_,
Expand All @@ -174,18 +188,7 @@ SensorsHalProxy::SensorsHalProxy(SharedFD control_from_guest_fd,
});
data_reporter_thread_ = std::thread([this, host_enabled_sensors] {
while (running_) {
if (hal_activated_) {
SensorsMask host_update_sensors =
host_enabled_sensors & kContinuousModeSensors;
auto sensors_data =
sensors_simulator_.GetSensorsData(host_update_sensors);
auto result =
UpdateSensorsHal(sensors_data, data_channel_, host_update_sensors);
if (!result.ok()) {
running_ = false;
LOG(ERROR) << result.error();
}
}
ReportToGuest(host_enabled_sensors & kContinuousModeSensors);
std::this_thread::sleep_for(std::chrono::milliseconds(kIntervalMs));
}
});
Expand All @@ -201,5 +204,18 @@ SensorsHalProxy::SensorsHalProxy(SharedFD control_from_guest_fd,
});
}

void SensorsHalProxy::ReportToGuest(SensorsMask mask) {
if (!hal_activated_ || !mask) {
return;
}
std::string sensors_data = sensors_simulator_.GetSensorsData(mask);
std::lock_guard<std::mutex> lock(report_mtx_);
auto result = UpdateSensorsHal(sensors_data, data_channel_, mask);
if (!result.ok()) {
running_ = false;
LOG(ERROR) << result.error();
}
}

} // namespace sensors
} // namespace cuttlefish
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include <atomic>
#include <mutex>
#include <thread>

#include "cuttlefish/common/libs/sensors/sensors.h"
Expand All @@ -37,6 +38,8 @@ class SensorsHalProxy {
SensorsSimulator& sensors_simulator, DeviceType device_type);

private:
void ReportToGuest(SensorsMask mask);

std::thread req_responder_thread_;
std::thread data_reporter_thread_;
std::thread reboot_monitor_thread_;
Expand All @@ -46,6 +49,7 @@ class SensorsHalProxy {
SensorsSimulator& sensors_simulator_;
std::atomic<bool> hal_activated_ = false;
std::atomic<bool> running_ = true;
std::mutex report_mtx_;
};

} // namespace sensors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "cuttlefish/host/commands/sensors_simulator/sensors_simulator.h"

#include <cmath>
#include <utility>

namespace cuttlefish {
namespace sensors {
Expand Down Expand Up @@ -96,7 +97,7 @@ SensorsSimulator::SensorsSimulator(bool is_auto)
last_event_timestamp_(std::chrono::high_resolution_clock::now()),
is_auto_(is_auto) {
// Initialize sensors_data_ based on rotation vector = (0, 0, 0)
RefreshSensors(0, 0, 0);
SetMotion(0, 0, 0);
// Set constant values for the sensors that are independent of rotation vector
sensors_data_[kTemperatureId].f = kTemperature;
sensors_data_[kProximityId].f = kProximity;
Expand All @@ -106,30 +107,60 @@ SensorsSimulator::SensorsSimulator(bool is_auto)
sensors_data_[kHingeAngle0Id].f = kHingeAngle0;
}

void SensorsSimulator::RefreshSensors(double x, double y, double z) {
void SensorsSimulator::SetSensorsChangedCallback(
SensorsMask mask, SensorsChangedCallback callback) {
sensors_changed_mask_ = mask;
sensors_changed_callback_ = std::move(callback);
}

void SensorsSimulator::NotifySensorsChanged(SensorsMask changed) {
SensorsMask relevant = changed & sensors_changed_mask_;
if (sensors_changed_callback_ && relevant) {
sensors_changed_callback_(relevant);
}
}

void SensorsSimulator::SetMotion(double x, double y, double z) {
auto rotation_matrix_update = GetRotationMatrix(x, y, z);
auto acc_update = CalculateAcceleration(rotation_matrix_update, is_auto_);
auto mgn_update = CalculateMagnetometer(rotation_matrix_update);

std::lock_guard<std::mutex> lock(sensors_data_mtx_);
auto current_time = std::chrono::high_resolution_clock::now();
auto duration = current_time - last_event_timestamp_;
last_event_timestamp_ = current_time;
{
std::lock_guard<std::mutex> lock(sensors_data_mtx_);
auto current_time = std::chrono::high_resolution_clock::now();
auto duration = current_time - last_event_timestamp_;
last_event_timestamp_ = current_time;

auto gyro_update = CalculateGyroscope(duration, current_rotation_matrix_,
rotation_matrix_update);
auto gyro_update = CalculateGyroscope(duration, current_rotation_matrix_,
rotation_matrix_update);

current_rotation_matrix_ = rotation_matrix_update;
current_rotation_matrix_ = rotation_matrix_update;

sensors_data_[kRotationVecId].v << x, y, z;
sensors_data_[kAccelerationId].v = acc_update;
sensors_data_[kGyroscopeId].v = gyro_update;
sensors_data_[kMagneticId].v = mgn_update;
sensors_data_[kRotationVecId].v << x, y, z;
sensors_data_[kAccelerationId].v = acc_update;
sensors_data_[kGyroscopeId].v = gyro_update;
sensors_data_[kMagneticId].v = mgn_update;

// Copy the calibrated sensor data over for uncalibrated sensor support
sensors_data_[kUncalibAccelerationId].v = acc_update;
sensors_data_[kUncalibGyroscopeId].v = gyro_update;
sensors_data_[kUncalibMagneticId].v = mgn_update;
// Copy the calibrated sensor data over for uncalibrated sensor support
sensors_data_[kUncalibAccelerationId].v = acc_update;
sensors_data_[kUncalibGyroscopeId].v = gyro_update;
sensors_data_[kUncalibMagneticId].v = mgn_update;
}
NotifySensorsChanged((1 << kRotationVecId) | (1 << kAccelerationId) |
(1 << kGyroscopeId) | (1 << kMagneticId) |
(1 << kUncalibAccelerationId) |
(1 << kUncalibGyroscopeId) | (1 << kUncalibMagneticId));
}

void SensorsSimulator::SetHingeAngle(float angle) {
{
std::lock_guard<std::mutex> lock(sensors_data_mtx_);
if (sensors_data_[kHingeAngle0Id].f == angle) {
return;
}
sensors_data_[kHingeAngle0Id].f = angle;
}
NotifySensorsChanged(1 << kHingeAngle0Id);
}

std::string SensorsSimulator::GetSensorsData(const SensorsMask mask) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include <chrono>
#include <functional>
#include <mutex>
#include <string>

Expand All @@ -37,8 +38,15 @@ struct SensorsData {
class SensorsSimulator {
public:
SensorsSimulator(bool is_auto);
// Update sensor values based on new rotation status.
void RefreshSensors(double x, double y, double z);

using SensorsChangedCallback = std::function<void(SensorsMask)>;
// Registers a callback invoked whenever one or more sensors in |mask| are
// updated.
void SetSensorsChangedCallback(SensorsMask mask,
SensorsChangedCallback callback);

void SetMotion(double x, double y, double z);
void SetHingeAngle(float angle);

// Return a string with serialized sensors data in ascending order of
// sensor id. A bitmask is used to specify which sensors to include.
Expand All @@ -49,7 +57,11 @@ class SensorsSimulator {
std::string GetSensorsData(const SensorsMask mask);

private:
void NotifySensorsChanged(SensorsMask changed);

std::mutex sensors_data_mtx_;
SensorsMask sensors_changed_mask_ = 0;
SensorsChangedCallback sensors_changed_callback_;
SensorsData sensors_data_[kMaxSensorId + 1];
Eigen::Matrix3d current_rotation_matrix_;
std::chrono::time_point<std::chrono::high_resolution_clock>
Expand Down
13 changes: 9 additions & 4 deletions base/cvd/cuttlefish/host/frontend/webrtc/connection_observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,11 @@ class ConnectionObserverImpl : public webrtc_streaming::ConnectionObserver {
CF_EXPECT(OnSwitchEvent(SW_LID, !lid_open));
return {};
}
void OnHingeAngleChange(int /*hinge_angle*/) override {
// TODO(b/181157794) Propagate hinge angle sensor data using a custom
// Sensor HAL.
void OnHingeAngleChange(int hinge_angle) override {
auto result = sensors_handler_.SetHingeAngle(hinge_angle);
if (!result.ok()) {
LOG(ERROR) << "Failed to set hinge angle: " << result.error();
}
}
Result<void> OnPowerButton(bool button_down) override {
CF_EXPECT(OnKeyboardEvent(KEY_POWER, button_down));
Expand Down Expand Up @@ -264,7 +266,10 @@ class ConnectionObserverImpl : public webrtc_streaming::ConnectionObserver {
<< "Y rotation value must be a double";
CHECK(absl::SimpleAtod(xyz.at(2), &z))
<< "Z rotation value must be a double";
sensors_handler_.HandleMessage(x, y, z);
auto result = sensors_handler_.SetMotion(x, y, z);
if (!result.ok()) {
LOG(ERROR) << "Failed to set motion: " << result.error();
}
}

void OnLightsChannelOpen(
Expand Down
14 changes: 1 addition & 13 deletions base/cvd/cuttlefish/host/frontend/webrtc/html_client/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,18 +352,11 @@ class DeviceControlApp {
'control-panel-custom-buttons');
element.dataset.adb = true;
} else if (button.device_states) {
// This button corresponds to variable hardware device state(s).
let element = createControlPanelButton(
button.title, button.icon_name,
this.#getCustomDeviceStateButtonCb(button.device_states),
'control-panel-custom-buttons');
for (const device_state of button.device_states) {
// hinge_angle is currently injected via an adb shell command that
// triggers a guest binary.
if ('hinge_angle_value' in device_state) {
element.dataset.adb = true;
}
}
element.dataset.adb = true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this still be here? If I understand correctly, the code before amounted to something like "if the device state includes hinge_angle, make sure adb is connected."

As written this commit changes it to "always connect to adb," but I would expect "the hinge angle is not sent via adb" to imply "adb no longer matters for sensors, don't set or unset the adb connection requirement."

I may be misunderstanding what the .adb variable is for. FYI @jemoreira

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the change perspective this makes sense, I'm agree.

However, after checking the getCustomDeviceStateButtonCb implementation, it looks to me like any action on that panel triggers adbShell('cmd device_state state reset'), meaning ADB is executed regardless of whether we change the hinge angle, the lid, or anything else, so I assume the entire panel should be disabled if ADB isn't available.

Do you think I'm missing something?

} else {
// This button's command is handled by custom action server.
createControlPanelButton(
Expand Down Expand Up @@ -754,11 +747,6 @@ class DeviceControlApp {
let hingeAngle = null;
if ('hinge_angle_value' in states[index]) {
hingeAngle = states[index].hinge_angle_value;
// TODO(b/181157794): Use a custom Sensor HAL for hinge_angle
// injection instead of this guest binary.
adbShell(
'/vendor/bin/cuttlefish_sensor_injection hinge_angle ' +
states[index].hinge_angle_value);
}
// Update the Device Details view.
this.#updateDeviceStateDetails(lidSwitchOpen, hingeAngle);
Expand Down
Loading
Loading