platform_sensor_reader_linux.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Copyright 2016 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_reader_linux.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/files/file_util.h"
  8. #include "base/sequence_checker.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/task/thread_pool.h"
  13. #include "base/timer/timer.h"
  14. #include "services/device/generic_sensor/linux/sensor_data_linux.h"
  15. #include "services/device/generic_sensor/platform_sensor_linux.h"
  16. #include "services/device/public/cpp/generic_sensor/sensor_reading.h"
  17. namespace device {
  18. class PollingSensorReader : public SensorReader {
  19. public:
  20. PollingSensorReader(const SensorInfoLinux& sensor_info,
  21. base::WeakPtr<PlatformSensorLinux> sensor);
  22. PollingSensorReader(const PollingSensorReader&) = delete;
  23. PollingSensorReader& operator=(const PollingSensorReader&) = delete;
  24. ~PollingSensorReader() override;
  25. // SensorReader overrides
  26. void StartFetchingData(
  27. const PlatformSensorConfiguration& configuration) override;
  28. void StopFetchingData() override;
  29. private:
  30. // Helper class that performs the actual I/O. It must run on a
  31. // SequencedTaskRunner that is properly configured for blocking I/O
  32. // operations.
  33. class BlockingTaskRunnerHelper final {
  34. public:
  35. BlockingTaskRunnerHelper(
  36. base::WeakPtr<PollingSensorReader> polling_sensor_reader,
  37. const SensorInfoLinux& sensor_info);
  38. BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete;
  39. BlockingTaskRunnerHelper& operator=(const BlockingTaskRunnerHelper&) =
  40. delete;
  41. ~BlockingTaskRunnerHelper();
  42. // Starts polling for data at a given |frequency|, and stops if there is an
  43. // error while reading or parsing the data.
  44. void StartPolling(double frequency);
  45. // Stops polling for data and notifying PollingSensorReader.
  46. void StopPolling();
  47. private:
  48. void StopWithError();
  49. void PollForData();
  50. // Repeating timer for data polling.
  51. base::RepeatingTimer timer_;
  52. // |polling_sensor_reader_| can only be checked for validity on
  53. // |owner_task_runner_|'s sequence.
  54. base::WeakPtr<PollingSensorReader> polling_sensor_reader_;
  55. // Task runner belonging to PollingSensorReader. Calls to
  56. // PollingSensorReader will be done via this task runner.
  57. scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
  58. // Sensor information we need in order to know where and how to read sensor
  59. // data.
  60. const SensorInfoLinux sensor_info_;
  61. SEQUENCE_CHECKER(sequence_checker_);
  62. };
  63. // Receives a reading from the platform sensor and forwards it to |sensor_|.
  64. void OnReadingAvailable(SensorReading reading);
  65. // Signals that an error occurred while trying to read from a platform sensor.
  66. void OnReadingError();
  67. // In builds with DCHECK enabled, checks that methods of this class are
  68. // called on the right thread.
  69. SEQUENCE_CHECKER(sequence_checker_);
  70. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_ =
  71. base::ThreadPool::CreateSequencedTaskRunner(
  72. {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
  73. base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
  74. std::unique_ptr<BlockingTaskRunnerHelper, base::OnTaskRunnerDeleter>
  75. blocking_task_helper_;
  76. base::WeakPtrFactory<PollingSensorReader> weak_factory_{this};
  77. };
  78. PollingSensorReader::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper(
  79. base::WeakPtr<PollingSensorReader> polling_sensor_reader,
  80. const SensorInfoLinux& sensor_info)
  81. : polling_sensor_reader_(polling_sensor_reader),
  82. owner_task_runner_(base::SequencedTaskRunnerHandle::Get()),
  83. sensor_info_(sensor_info) {
  84. // Detaches from the sequence on which this object was created. It will be
  85. // bound to its owning sequence when StartPolling() is called.
  86. DETACH_FROM_SEQUENCE(sequence_checker_);
  87. }
  88. PollingSensorReader::BlockingTaskRunnerHelper::~BlockingTaskRunnerHelper() {
  89. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  90. }
  91. void PollingSensorReader::BlockingTaskRunnerHelper::StartPolling(
  92. double frequency) {
  93. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  94. DCHECK(!timer_.IsRunning());
  95. timer_.Start(
  96. FROM_HERE,
  97. base::Microseconds(base::Time::kMicrosecondsPerSecond / frequency), this,
  98. &PollingSensorReader::BlockingTaskRunnerHelper::PollForData);
  99. }
  100. void PollingSensorReader::BlockingTaskRunnerHelper::StopPolling() {
  101. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  102. timer_.Stop();
  103. }
  104. void PollingSensorReader::BlockingTaskRunnerHelper::StopWithError() {
  105. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  106. StopPolling();
  107. owner_task_runner_->PostTask(
  108. FROM_HERE, base::BindOnce(&PollingSensorReader::OnReadingError,
  109. polling_sensor_reader_));
  110. }
  111. void PollingSensorReader::BlockingTaskRunnerHelper::PollForData() {
  112. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  113. SensorReading readings;
  114. DCHECK_LE(sensor_info_.device_reading_files.size(),
  115. std::size(readings.raw.values));
  116. int i = 0;
  117. for (const auto& path : sensor_info_.device_reading_files) {
  118. std::string new_read_value;
  119. if (!base::ReadFileToString(path, &new_read_value)) {
  120. StopWithError();
  121. return;
  122. }
  123. double new_value = 0;
  124. base::TrimWhitespaceASCII(new_read_value, base::TRIM_ALL, &new_read_value);
  125. if (!base::StringToDouble(new_read_value, &new_value)) {
  126. StopWithError();
  127. return;
  128. }
  129. readings.raw.values[i++] = new_value;
  130. }
  131. const auto& scaling_function = sensor_info_.apply_scaling_func;
  132. if (!scaling_function.is_null()) {
  133. scaling_function.Run(sensor_info_.device_scaling_value,
  134. sensor_info_.device_offset_value, readings);
  135. }
  136. owner_task_runner_->PostTask(
  137. FROM_HERE, base::BindOnce(&PollingSensorReader::OnReadingAvailable,
  138. polling_sensor_reader_, readings));
  139. }
  140. PollingSensorReader::PollingSensorReader(
  141. const SensorInfoLinux& sensor_info,
  142. base::WeakPtr<PlatformSensorLinux> sensor)
  143. : SensorReader(sensor),
  144. blocking_task_helper_(nullptr,
  145. base::OnTaskRunnerDeleter(blocking_task_runner_)) {
  146. // We need to properly initialize |blocking_task_helper_| here because we need
  147. // |weak_factory_| to be created first.
  148. blocking_task_helper_.reset(
  149. new BlockingTaskRunnerHelper(weak_factory_.GetWeakPtr(), sensor_info));
  150. }
  151. PollingSensorReader::~PollingSensorReader() {
  152. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  153. }
  154. void PollingSensorReader::StartFetchingData(
  155. const PlatformSensorConfiguration& configuration) {
  156. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  157. if (is_reading_active_)
  158. StopFetchingData();
  159. is_reading_active_ = true;
  160. blocking_task_runner_->PostTask(
  161. FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::StartPolling,
  162. base::Unretained(blocking_task_helper_.get()),
  163. configuration.frequency()));
  164. }
  165. void PollingSensorReader::StopFetchingData() {
  166. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  167. is_reading_active_ = false;
  168. blocking_task_runner_->PostTask(
  169. FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::StopPolling,
  170. base::Unretained(blocking_task_helper_.get())));
  171. }
  172. void PollingSensorReader::OnReadingAvailable(SensorReading reading) {
  173. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  174. if (!is_reading_active_)
  175. return;
  176. if (sensor_) {
  177. sensor_->PostTaskToMainSequence(
  178. FROM_HERE,
  179. base::BindOnce(&PlatformSensorLinux::UpdatePlatformSensorReading,
  180. sensor_, reading));
  181. }
  182. }
  183. void PollingSensorReader::OnReadingError() {
  184. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  185. NotifyReadError();
  186. }
  187. // static
  188. std::unique_ptr<SensorReader> SensorReader::Create(
  189. const SensorInfoLinux& sensor_info,
  190. base::WeakPtr<PlatformSensorLinux> sensor) {
  191. // TODO(maksims): implement triggered reading. At the moment,
  192. // only polling read is supported.
  193. return std::make_unique<PollingSensorReader>(sensor_info, sensor);
  194. }
  195. SensorReader::SensorReader(base::WeakPtr<PlatformSensorLinux> sensor)
  196. : sensor_(sensor), is_reading_active_(false) {}
  197. SensorReader::~SensorReader() = default;
  198. void SensorReader::NotifyReadError() {
  199. if (is_reading_active_ && sensor_) {
  200. sensor_->PostTaskToMainSequence(
  201. FROM_HERE,
  202. base::BindOnce(&PlatformSensorLinux::NotifyPlatformSensorError,
  203. sensor_));
  204. }
  205. }
  206. } // namespace device