platform_sensor_accelerometer_mac.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/device/generic_sensor/platform_sensor_accelerometer_mac.h"
  5. #include <stdint.h>
  6. #include <cmath>
  7. #include "base/bind.h"
  8. #include "base/numerics/math_constants.h"
  9. #include "base/sequence_checker.h"
  10. #include "base/task/thread_pool.h"
  11. #include "base/threading/sequenced_task_runner_handle.h"
  12. #include "device/base/synchronization/shared_memory_seqlock_buffer.h"
  13. #include "services/device/generic_sensor/platform_sensor_provider_mac.h"
  14. #include "services/device/public/cpp/generic_sensor/sensor_traits.h"
  15. #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
  16. namespace {
  17. constexpr double kGravityThreshold = base::kMeanGravityDouble * 0.01;
  18. bool IsSignificantlyDifferentMac(const device::SensorReading& reading1,
  19. const device::SensorReading& reading2) {
  20. return (std::fabs(reading1.accel.x - reading2.accel.x) >=
  21. kGravityThreshold) ||
  22. (std::fabs(reading1.accel.y - reading2.accel.y) >=
  23. kGravityThreshold) ||
  24. (std::fabs(reading1.accel.z - reading2.accel.z) >= kGravityThreshold);
  25. }
  26. } // namespace
  27. namespace device {
  28. using mojom::SensorType;
  29. // Helper class that performs the actual I/O. It must run on a
  30. // SequencedTaskRunner that is properly configured for blocking I/O
  31. // operations.
  32. class PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper final {
  33. public:
  34. explicit BlockingTaskRunnerHelper(
  35. base::WeakPtr<PlatformSensorAccelerometerMac> platform_sensor);
  36. ~BlockingTaskRunnerHelper();
  37. BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete;
  38. BlockingTaskRunnerHelper& operator=(const BlockingTaskRunnerHelper&) = delete;
  39. void Init();
  40. void StartPolling(double frequency);
  41. void StopPolling();
  42. private:
  43. void PollForData();
  44. // Repeating timer for data polling.
  45. base::RepeatingTimer timer_;
  46. // |platform_sensor_| can only be checked for validity on
  47. // |owner_task_runner_|'s sequence.
  48. base::WeakPtr<PlatformSensorAccelerometerMac> platform_sensor_;
  49. // Task runner belonging to PlatformSensorAccelerometerMac. Calls to it
  50. // will be done via this task runner.
  51. scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
  52. // SuddenMotionSensor instance that performs blocking calls.
  53. std::unique_ptr<SuddenMotionSensor> sudden_motion_sensor_;
  54. // In builds with DCHECK enabled, checks that methods of this class are
  55. // called on the right thread.
  56. SEQUENCE_CHECKER(sequence_checker_);
  57. };
  58. PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::
  59. BlockingTaskRunnerHelper(
  60. base::WeakPtr<PlatformSensorAccelerometerMac> platform_sensor)
  61. : platform_sensor_(platform_sensor),
  62. owner_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
  63. // Detaches from the sequence on which this object was created. It will be
  64. // bound to another sequence when Init() is called.
  65. DETACH_FROM_SEQUENCE(sequence_checker_);
  66. }
  67. PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::
  68. ~BlockingTaskRunnerHelper() {
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  70. }
  71. void PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::Init() {
  72. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  73. if (sudden_motion_sensor_)
  74. return;
  75. sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
  76. }
  77. void PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::StartPolling(
  78. double frequency) {
  79. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  80. DCHECK(!timer_.IsRunning());
  81. if (!sudden_motion_sensor_)
  82. return;
  83. timer_.Start(
  84. FROM_HERE,
  85. base::Microseconds(base::Time::kMicrosecondsPerSecond / frequency), this,
  86. &PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::PollForData);
  87. }
  88. void PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::StopPolling() {
  89. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  90. timer_.Stop();
  91. }
  92. void PlatformSensorAccelerometerMac::BlockingTaskRunnerHelper::PollForData() {
  93. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  94. DCHECK(sudden_motion_sensor_);
  95. // Retrieve per-axis calibrated values.
  96. float axis_value[3];
  97. if (!sudden_motion_sensor_->ReadSensorValues(axis_value))
  98. return;
  99. SensorReading reading;
  100. reading.accel.timestamp =
  101. (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
  102. reading.accel.x = axis_value[0] * base::kMeanGravityDouble;
  103. reading.accel.y = axis_value[1] * base::kMeanGravityDouble;
  104. reading.accel.z = axis_value[2] * base::kMeanGravityDouble;
  105. owner_task_runner_->PostTask(
  106. FROM_HERE,
  107. base::BindOnce(&PlatformSensorAccelerometerMac::OnReadingAvailable,
  108. platform_sensor_, reading));
  109. }
  110. PlatformSensorAccelerometerMac::PlatformSensorAccelerometerMac(
  111. SensorReadingSharedBuffer* reading_buffer,
  112. PlatformSensorProvider* provider)
  113. : PlatformSensor(SensorType::ACCELEROMETER, reading_buffer, provider),
  114. blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
  115. {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
  116. base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
  117. blocking_task_helper_(nullptr,
  118. base::OnTaskRunnerDeleter(blocking_task_runner_)) {
  119. // We need to properly initialize |blocking_task_helper_| here because we need
  120. // |weak_factory_| to be created first.
  121. blocking_task_helper_.reset(
  122. new BlockingTaskRunnerHelper(weak_factory_.GetWeakPtr()));
  123. blocking_task_runner_->PostTask(
  124. FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Init,
  125. base::Unretained(blocking_task_helper_.get())));
  126. }
  127. PlatformSensorAccelerometerMac::~PlatformSensorAccelerometerMac() = default;
  128. mojom::ReportingMode PlatformSensorAccelerometerMac::GetReportingMode() {
  129. return mojom::ReportingMode::ON_CHANGE;
  130. }
  131. bool PlatformSensorAccelerometerMac::CheckSensorConfiguration(
  132. const PlatformSensorConfiguration& configuration) {
  133. return configuration.frequency() > 0 &&
  134. configuration.frequency() <=
  135. SensorTraits<SensorType::ACCELEROMETER>::kMaxAllowedFrequency;
  136. }
  137. PlatformSensorConfiguration
  138. PlatformSensorAccelerometerMac::GetDefaultConfiguration() {
  139. return PlatformSensorConfiguration(
  140. SensorTraits<SensorType::ACCELEROMETER>::kDefaultFrequency);
  141. }
  142. bool PlatformSensorAccelerometerMac::StartSensor(
  143. const PlatformSensorConfiguration& configuration) {
  144. if (is_reading_active_)
  145. StopSensor();
  146. is_reading_active_ = true;
  147. blocking_task_runner_->PostTask(
  148. FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::StartPolling,
  149. base::Unretained(blocking_task_helper_.get()),
  150. configuration.frequency()));
  151. return true;
  152. }
  153. void PlatformSensorAccelerometerMac::StopSensor() {
  154. is_reading_active_ = false;
  155. blocking_task_runner_->PostTask(
  156. FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::StopPolling,
  157. base::Unretained(blocking_task_helper_.get())));
  158. }
  159. void PlatformSensorAccelerometerMac::OnReadingAvailable(SensorReading reading) {
  160. if (is_reading_active_ && IsSignificantlyDifferentMac(reading_, reading)) {
  161. reading_ = reading;
  162. UpdateSharedBufferAndNotifyClients(reading);
  163. }
  164. }
  165. } // namespace device