Index: device/generic_sensor/platform_sensor_fusion_relative_orientation.cc |
diff --git a/device/generic_sensor/platform_sensor_fusion_relative_orientation.cc b/device/generic_sensor/platform_sensor_fusion_relative_orientation.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ed7fbfd1a32cfc7ce41f8d2a8aef078a415cf129 |
--- /dev/null |
+++ b/device/generic_sensor/platform_sensor_fusion_relative_orientation.cc |
@@ -0,0 +1,141 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "device/generic_sensor/platform_sensor_fusion_relative_orientation.h" |
+ |
+#include <stdint.h> |
+ |
+#include <cmath> |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/memory/ptr_util.h" |
+#include "device/generic_sensor/generic_sensor_consts.h" |
+#include "device/generic_sensor/platform_sensor_provider.h" |
+#include "device/generic_sensor/relative_orientation_fusion_algorithm_using_accelerometer.h" |
+ |
+namespace { |
+ |
+constexpr double kQuaternionThreshold = 0.01; |
+ |
+bool IsSignificantlyDifferent(const device::SensorReading& reading1, |
+ const device::SensorReading& reading2) { |
+ return (std::fabs(reading1.values[0] - reading2.values[0]) >= |
+ kQuaternionThreshold) || |
+ (std::fabs(reading1.values[1] - reading2.values[1]) >= |
+ kQuaternionThreshold) || |
+ (std::fabs(reading1.values[2] - reading2.values[2]) >= |
+ kQuaternionThreshold) || |
+ (std::fabs(reading1.values[3] - reading2.values[3]) >= |
+ kQuaternionThreshold); |
+} |
+ |
+} // namespace |
+ |
+namespace device { |
+ |
+PlatformSensorFusionRelativeOrientation:: |
+ PlatformSensorFusionRelativeOrientation( |
+ mojo::ScopedSharedBufferMapping mapping, |
+ PlatformSensorProvider* provider, |
+ const PlatformSensorProviderBase::CreateSensorCallback& callback) |
+ : PlatformSensor(mojom::SensorType::RELATIVE_ORIENTATION, |
+ std::move(mapping), |
+ provider), |
+ callback_(callback) { |
+ accelerometer_ = provider->GetSensor(mojom::SensorType::ACCELEROMETER); |
+ if (accelerometer_) { |
+ CreateAccelerometerSucceeded(); |
+ } else { |
+ provider->CreateSensor(mojom::SensorType::ACCELEROMETER, |
+ base::Bind(&PlatformSensorFusionRelativeOrientation:: |
+ CreateAccelerometerCallback, |
+ base::Unretained(this))); |
+ } |
+} |
+ |
+PlatformSensorFusionRelativeOrientation:: |
+ ~PlatformSensorFusionRelativeOrientation() { |
+ if (accelerometer_) |
+ accelerometer_->RemoveClient(this); |
+} |
+ |
+mojom::ReportingMode |
+PlatformSensorFusionRelativeOrientation::GetReportingMode() { |
+ return accelerometer_->GetReportingMode(); |
+} |
+ |
+PlatformSensorConfiguration |
+PlatformSensorFusionRelativeOrientation::GetDefaultConfiguration() { |
+ return accelerometer_->GetDefaultConfiguration(); |
+} |
+ |
+bool PlatformSensorFusionRelativeOrientation::StartSensor( |
+ const PlatformSensorConfiguration& configuration) { |
+ return accelerometer_->StartSensor(configuration); |
+} |
+ |
+void PlatformSensorFusionRelativeOrientation::StopSensor() { |
+ accelerometer_->StopSensor(); |
+} |
+ |
+void PlatformSensorFusionRelativeOrientation::OnSensorReadingChanged() { |
+ SensorReading reading; |
+ reading.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
+ |
+ if (!accelerometer_->GetLatestReading(&reading)) |
+ return; |
+ |
+ fusion_algorithm_->set_acceleration(reading.values[0], reading.values[1], |
+ reading.values[2]); |
+ |
+ fusion_algorithm_->GetRelativeOrientationData( |
+ &reading.values[0].value(), &reading.values[1].value(), |
+ &reading.values[2].value(), &reading.values[3].value()); |
+ |
+ if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE && |
+ !IsSignificantlyDifferent(reading_, reading)) { |
+ return; |
+ } |
+ |
+ reading_ = reading; |
+ UpdateSensorReading(reading_, |
+ GetReportingMode() == mojom::ReportingMode::ON_CHANGE); |
+} |
+ |
+void PlatformSensorFusionRelativeOrientation::OnSensorError() { |
+ NotifySensorError(); |
+} |
+ |
+bool PlatformSensorFusionRelativeOrientation::IsNotificationSuspended() { |
+ for (auto& client : clients_) { |
+ if (!client.IsNotificationSuspended()) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool PlatformSensorFusionRelativeOrientation::CheckSensorConfiguration( |
+ const PlatformSensorConfiguration& configuration) { |
+ return accelerometer_->CheckSensorConfiguration(configuration); |
+} |
+ |
+void PlatformSensorFusionRelativeOrientation::CreateAccelerometerCallback( |
+ scoped_refptr<PlatformSensor> accelerometer) { |
+ accelerometer_ = accelerometer; |
+ if (accelerometer_) { |
+ CreateAccelerometerSucceeded(); |
+ } else { |
+ callback_.Run(nullptr); |
+ } |
+} |
+ |
+void PlatformSensorFusionRelativeOrientation::CreateAccelerometerSucceeded() { |
+ accelerometer_->AddClient(this); |
+ fusion_algorithm_ = |
+ base::MakeUnique<RelativeOrientationFusionAlgorithmUsingAccelerometer>(); |
+ callback_.Run(this); |
+} |
+ |
+} // namespace device |