Commit 366f5532 authored by Jun Cai's avatar Jun Cai Committed by Commit Bot

Add support for signaling which sensor changed at PlatformSensor::Client

This CL adds a "mojom::SensorType type" parameter to the
PlatformSensor::Client::OnSensorReadingChanged() function to signal
which sensor has changed its data. By doing this, fusion sensor
algorithms may update different parts of their internal state depending
on which sensor has changed.

Bug: 750882
Change-Id: I26fad3e80c4a63337fd89d58ba6a62a6c1d5880a
Reviewed-on: https://chromium-review.googlesource.com/594720
Commit-Queue: Jun Cai <juncai@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491198}
parent f1e3fb4b
......@@ -4,6 +4,9 @@
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
#include "base/logging.h"
#include "services/device/generic_sensor/platform_sensor_fusion.h"
namespace device {
LinearAccelerationFusionAlgorithmUsingAccelerometer::
......@@ -32,26 +35,30 @@ void LinearAccelerationFusionAlgorithmUsingAccelerometer::Reset() {
gravity_z_ = 0.0;
}
void LinearAccelerationFusionAlgorithmUsingAccelerometer::GetFusedData(
const std::vector<SensorReading>& readings,
bool LinearAccelerationFusionAlgorithmUsingAccelerometer::GetFusedData(
mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) {
DCHECK(readings.size() == 1);
DCHECK(fusion_sensor_);
++reading_updates_count_;
SensorReading reading;
if (!fusion_sensor_->GetLatestReading(0, &reading))
return false;
// First reading.
if (initial_timestamp_ == 0.0) {
initial_timestamp_ = readings[0].timestamp;
return;
initial_timestamp_ = reading.timestamp;
return false;
}
double delivery_rate =
(readings[0].timestamp - initial_timestamp_) / reading_updates_count_;
(reading.timestamp - initial_timestamp_) / reading_updates_count_;
double alpha = time_constant_ / (time_constant_ + delivery_rate);
double acceleration_x = readings[0].values[0].value();
double acceleration_y = readings[0].values[1].value();
double acceleration_z = readings[0].values[2].value();
double acceleration_x = reading.values[0].value();
double acceleration_y = reading.values[1].value();
double acceleration_z = reading.values[2].value();
// Isolate gravity.
gravity_x_ = alpha * gravity_x_ + (1 - alpha) * acceleration_x;
......@@ -62,6 +69,8 @@ void LinearAccelerationFusionAlgorithmUsingAccelerometer::GetFusedData(
fused_reading->values[0].value() = acceleration_x - gravity_x_;
fused_reading->values[1].value() = acceleration_y - gravity_y_;
fused_reading->values[2].value() = acceleration_z - gravity_z_;
return true;
}
} // namespace device
......@@ -19,7 +19,7 @@ class LinearAccelerationFusionAlgorithmUsingAccelerometer final
LinearAccelerationFusionAlgorithmUsingAccelerometer();
~LinearAccelerationFusionAlgorithmUsingAccelerometer() override;
void GetFusedData(const std::vector<SensorReading>& readings,
bool GetFusedData(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
void SetFrequency(double frequency) override;
void Reset() override;
......
......@@ -6,7 +6,8 @@
#include <cmath>
#include "services/device/generic_sensor/generic_sensor_consts.h"
#include "base/logging.h"
#include "services/device/generic_sensor/platform_sensor_fusion.h"
namespace {
......@@ -40,22 +41,28 @@ OrientationQuaternionFusionAlgorithmUsingEulerAngles::
OrientationQuaternionFusionAlgorithmUsingEulerAngles::
~OrientationQuaternionFusionAlgorithmUsingEulerAngles() = default;
void OrientationQuaternionFusionAlgorithmUsingEulerAngles::GetFusedData(
const std::vector<SensorReading>& readings,
bool OrientationQuaternionFusionAlgorithmUsingEulerAngles::GetFusedData(
mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) {
// Transform the *_ORIENTATION_EULER_ANGLES values to
// *_ORIENTATION_QUATERNION.
DCHECK(readings.size() == 1);
DCHECK(fusion_sensor_);
double beta = readings[0].values[0].value();
double gamma = readings[0].values[1].value();
double alpha = readings[0].values[2].value();
SensorReading reading;
if (!fusion_sensor_->GetLatestReading(0, &reading))
return false;
double beta = reading.values[0].value();
double gamma = reading.values[1].value();
double alpha = reading.values[2].value();
double x, y, z, w;
ComputeQuaternionFromEulerAngles(alpha, beta, gamma, &x, &y, &z, &w);
fused_reading->values[0].value() = x;
fused_reading->values[1].value() = y;
fused_reading->values[2].value() = z;
fused_reading->values[3].value() = w;
return true;
}
} // namespace device
......@@ -18,7 +18,7 @@ class OrientationQuaternionFusionAlgorithmUsingEulerAngles
OrientationQuaternionFusionAlgorithmUsingEulerAngles();
~OrientationQuaternionFusionAlgorithmUsingEulerAngles() override;
void GetFusedData(const std::vector<SensorReading>& readings,
bool GetFusedData(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
private:
......
......@@ -121,7 +121,7 @@ void PlatformSensor::UpdateSensorReading(const SensorReading& reading,
void PlatformSensor::NotifySensorReadingChanged() {
for (auto& client : clients_) {
if (!client.IsSuspended())
client.OnSensorReadingChanged();
client.OnSensorReadingChanged(type_);
}
}
......
......@@ -31,7 +31,7 @@ class PlatformSensor : public base::RefCountedThreadSafe<PlatformSensor> {
// The interface that must be implemented by PlatformSensor clients.
class Client {
public:
virtual void OnSensorReadingChanged() = 0;
virtual void OnSensorReadingChanged(mojom::SensorType type) = 0;
virtual void OnSensorError() = 0;
virtual bool IsSuspended() = 0;
......
......@@ -124,7 +124,7 @@ class MockPlatformSensorClient : public PlatformSensor::Client {
}
// PlatformSensor::Client interface.
MOCK_METHOD0(OnSensorReadingChanged, void());
MOCK_METHOD1(OnSensorReadingChanged, void(mojom::SensorType type));
MOCK_METHOD0(OnSensorError, void());
MOCK_METHOD0(IsSuspended, bool());
......@@ -251,11 +251,12 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
}
// Waits before OnSensorReadingChanged is called.
void WaitOnSensorReadingChangedEvent(MockPlatformSensorClient* client) {
void WaitOnSensorReadingChangedEvent(MockPlatformSensorClient* client,
mojom::SensorType type) {
run_loop_ = base::MakeUnique<base::RunLoop>();
EXPECT_CALL(*client, OnSensorReadingChanged()).WillOnce(Invoke([this]() {
run_loop_->Quit();
}));
EXPECT_CALL(*client, OnSensorReadingChanged(type))
.WillOnce(
Invoke([this](mojom::SensorType type) { run_loop_->Quit(); }));
run_loop_->Run();
run_loop_ = nullptr;
}
......@@ -354,7 +355,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorStarted) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(5);
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
WaitOnSensorReadingChangedEvent(client.get());
WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType());
EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
}
......@@ -497,7 +498,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckAmbientLightReadings) {
PlatformSensorConfiguration configuration(
sensor->GetMaximumSupportedFrequency());
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
WaitOnSensorReadingChangedEvent(client.get());
WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType());
EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
SensorReadingSharedBuffer* buffer =
......@@ -537,7 +538,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
WaitOnSensorReadingChangedEvent(client.get());
WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType());
EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
SensorReadingSharedBuffer* buffer =
......@@ -588,7 +589,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckGyroscopeReadingConversion) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
WaitOnSensorReadingChangedEvent(client.get());
WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType());
EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
SensorReadingSharedBuffer* buffer =
......@@ -640,7 +641,7 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckMagnetometerReadingConversion) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
WaitOnSensorReadingChangedEvent(client.get());
WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType());
EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
SensorReadingSharedBuffer* buffer =
......
......@@ -402,7 +402,7 @@ class MockPlatformSensorClient : public PlatformSensor::Client {
}
// PlatformSensor::Client interface.
MOCK_METHOD0(OnSensorReadingChanged, void());
MOCK_METHOD1(OnSensorReadingChanged, void(mojom::SensorType type));
MOCK_METHOD0(OnSensorError, void());
MOCK_METHOD0(IsSuspended, bool());
......@@ -480,7 +480,7 @@ TEST_F(PlatformSensorAndProviderTestWin, SensorStarted) {
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
base::win::ScopedPropVariant pvLux;
InitPropVariantFromDouble(3.14, pvLux.Receive());
GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, pvLux.ptr()}});
......@@ -566,7 +566,7 @@ TEST_F(PlatformSensorAndProviderTestWin, CheckAccelerometerReadingConversion) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
double x_accel = 0.25;
double y_accel = -0.25;
......@@ -605,7 +605,7 @@ TEST_F(PlatformSensorAndProviderTestWin, CheckGyroscopeReadingConversion) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
double x_ang_accel = 0.0;
double y_ang_accel = -1.8;
......@@ -645,7 +645,7 @@ TEST_F(PlatformSensorAndProviderTestWin, CheckMagnetometerReadingConversion) {
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
double x_magn_field = 112.0;
double y_magn_field = -162.0;
......@@ -691,7 +691,7 @@ TEST_F(PlatformSensorAndProviderTestWin,
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
double x = 10;
double y = 20;
......@@ -734,7 +734,7 @@ TEST_F(PlatformSensorAndProviderTestWin,
auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(10);
EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
EXPECT_CALL(*client, OnSensorReadingChanged(sensor->GetType())).Times(1);
double x = -0.5;
double y = -0.5;
......
......@@ -4,6 +4,7 @@
#include "services/device/generic_sensor/platform_sensor_fusion.h"
#include "base/logging.h"
#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
#include "services/device/generic_sensor/platform_sensor_provider.h"
......@@ -63,7 +64,8 @@ bool PlatformSensorFusion::StartSensor(
FROM_HERE,
base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
configuration.frequency()),
this, &PlatformSensorFusion::OnSensorReadingChanged);
base::Bind(&PlatformSensorFusion::OnSensorReadingChanged,
base::Unretained(this), GetType()));
}
fusion_algorithm_->SetFrequency(configuration.frequency());
......@@ -90,17 +92,12 @@ bool PlatformSensorFusion::CheckSensorConfiguration(
return true;
}
void PlatformSensorFusion::OnSensorReadingChanged() {
void PlatformSensorFusion::OnSensorReadingChanged(mojom::SensorType type) {
SensorReading reading;
reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
std::vector<SensorReading> sensor_readings(source_sensors_.size());
for (size_t i = 0; i < source_sensors_.size(); ++i) {
if (!source_sensors_[i]->GetLatestReading(&sensor_readings[i]))
return;
}
fusion_algorithm_->GetFusedData(sensor_readings, &reading);
if (!fusion_algorithm_->GetFusedData(type, &reading))
return;
if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE &&
!fusion_algorithm_->IsReadingSignificantlyDifferent(reading_, reading)) {
......@@ -124,6 +121,13 @@ bool PlatformSensorFusion::IsSuspended() {
return true;
}
bool PlatformSensorFusion::GetLatestReading(size_t index,
SensorReading* result) {
DCHECK_LT(index, source_sensors_.size());
return source_sensors_[index]->GetLatestReading(result);
}
PlatformSensorFusion::~PlatformSensorFusion() {
for (const auto& sensor : source_sensors_) {
if (sensor)
......@@ -149,6 +153,8 @@ void PlatformSensorFusion::CreateSensorSucceeded() {
for (const auto& sensor : source_sensors_)
sensor->AddClient(this);
fusion_algorithm_->set_fusion_sensor(this);
callback_.Run(this);
}
......
......@@ -52,10 +52,12 @@ class PlatformSensorFusion : public PlatformSensor,
const PlatformSensorConfiguration& configuration) override;
// PlatformSensor::Client:
void OnSensorReadingChanged() override;
void OnSensorReadingChanged(mojom::SensorType type) override;
void OnSensorError() override;
bool IsSuspended() override;
bool GetLatestReading(size_t index, SensorReading* result);
protected:
~PlatformSensorFusion() override;
......
......@@ -8,10 +8,13 @@
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
namespace device {
class PlatformSensorFusion;
// Base class for platform sensor fusion algorithm.
class PlatformSensorFusionAlgorithm {
public:
......@@ -20,10 +23,14 @@ class PlatformSensorFusionAlgorithm {
void set_threshold(double threshold) { threshold_ = threshold; }
void set_fusion_sensor(PlatformSensorFusion* fusion_sensor) {
fusion_sensor_ = fusion_sensor;
}
bool IsReadingSignificantlyDifferent(const SensorReading& reading1,
const SensorReading& reading2);
virtual void GetFusedData(const std::vector<SensorReading>& readings,
virtual bool GetFusedData(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) = 0;
// Sets frequency at which data is expected to be obtained from the platform.
......@@ -35,6 +42,10 @@ class PlatformSensorFusionAlgorithm {
// might need to be reset when sensor is stopped.
virtual void Reset();
protected:
// This raw pointer is safe because |fusion_sensor_| owns this object.
PlatformSensorFusion* fusion_sensor_ = nullptr;
private:
// Default threshold for comparing SensorReading values. If a
// different threshold is better for a certain sensor type, set_threshold()
......
......@@ -6,7 +6,9 @@
#include <cmath>
#include "base/logging.h"
#include "services/device/generic_sensor/generic_sensor_consts.h"
#include "services/device/generic_sensor/platform_sensor_fusion.h"
namespace device {
......@@ -17,8 +19,8 @@ RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer::
~RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer() =
default;
void RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer::
GetFusedData(const std::vector<SensorReading>& readings,
bool RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer::
GetFusedData(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) {
// Transform the accelerometer values to W3C draft angles.
//
......@@ -40,11 +42,15 @@ void RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer::
// This is necessary in order to provide enough information to solve
// the equations.
//
DCHECK(readings.size() == 1);
DCHECK(fusion_sensor_);
double acceleration_x = readings[0].values[0].value();
double acceleration_y = readings[0].values[1].value();
double acceleration_z = readings[0].values[2].value();
SensorReading reading;
if (!fusion_sensor_->GetLatestReading(0, &reading))
return false;
double acceleration_x = reading.values[0].value();
double acceleration_y = reading.values[1].value();
double acceleration_z = reading.values[2].value();
double alpha = 0.0;
double beta = std::atan2(-acceleration_y, acceleration_z);
......@@ -54,6 +60,8 @@ void RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer::
fused_reading->values[1].value() = gamma;
fused_reading->values[2].value() = alpha;
fused_reading->values[3].value() = 0.0;
return true;
}
} // namespace device
......@@ -18,7 +18,7 @@ class RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer
RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer();
~RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer() override;
void GetFusedData(const std::vector<SensorReading>& readings,
bool GetFusedData(mojom::SensorType which_sensor_changed,
SensorReading* fused_reading) override;
private:
......
......@@ -58,7 +58,7 @@ void SensorImpl::ConfigureReadingChangeNotifications(bool enabled) {
reading_notification_enabled_ = enabled;
}
void SensorImpl::OnSensorReadingChanged() {
void SensorImpl::OnSensorReadingChanged(mojom::SensorType type) {
DCHECK(!suspended_);
if (client_ && reading_notification_enabled_)
client_->SensorReadingChanged();
......
......@@ -33,7 +33,7 @@ class SensorImpl final : public mojom::Sensor, public PlatformSensor::Client {
void ConfigureReadingChangeNotifications(bool enabled) override;
// device::Sensor::Client implementation.
void OnSensorReadingChanged() override;
void OnSensorReadingChanged(mojom::SensorType type) override;
void OnSensorError() override;
bool IsSuspended() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment