platform_sensor_fusion.cc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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_fusion.h"
  5. #include <algorithm>
  6. #include "base/bind.h"
  7. #include "base/check.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/scoped_refptr.h"
  10. #include "base/notreached.h"
  11. #include "base/observer_list.h"
  12. #include "base/ranges/algorithm.h"
  13. #include "base/time/time.h"
  14. #include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
  15. #include "services/device/generic_sensor/platform_sensor_provider.h"
  16. #include "services/device/generic_sensor/platform_sensor_util.h"
  17. namespace device {
  18. class PlatformSensorFusion::Factory : public base::RefCounted<Factory> {
  19. public:
  20. static void CreateSensorFusion(
  21. SensorReadingSharedBuffer* reading_buffer,
  22. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm,
  23. PlatformSensorProviderBase::CreateSensorCallback callback,
  24. PlatformSensorProvider* provider) {
  25. scoped_refptr<Factory> factory(new Factory(reading_buffer,
  26. std::move(fusion_algorithm),
  27. std::move(callback), provider));
  28. factory->FetchSources();
  29. }
  30. private:
  31. friend class base::RefCounted<Factory>;
  32. Factory(SensorReadingSharedBuffer* reading_buffer,
  33. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm,
  34. PlatformSensorProviderBase::CreateSensorCallback callback,
  35. PlatformSensorProvider* provider)
  36. : fusion_algorithm_(std::move(fusion_algorithm)),
  37. result_callback_(std::move(callback)),
  38. reading_buffer_(reading_buffer),
  39. provider_(provider) {
  40. const auto& types = fusion_algorithm_->source_types();
  41. DCHECK(!types.empty());
  42. // Make sure there are no dups.
  43. DCHECK(std::adjacent_find(types.begin(), types.end()) == types.end());
  44. DCHECK(result_callback_);
  45. DCHECK(reading_buffer_);
  46. DCHECK(provider_);
  47. }
  48. ~Factory() = default;
  49. void FetchSources() {
  50. for (mojom::SensorType type : fusion_algorithm_->source_types()) {
  51. scoped_refptr<PlatformSensor> sensor = provider_->GetSensor(type);
  52. if (sensor) {
  53. SensorCreated(std::move(sensor));
  54. } else {
  55. provider_->CreateSensor(type,
  56. base::BindOnce(&Factory::SensorCreated, this));
  57. }
  58. }
  59. }
  60. void SensorCreated(scoped_refptr<PlatformSensor> sensor) {
  61. if (!result_callback_) {
  62. // It is possible, if this callback has been already called
  63. // with nullptr (i.e. failed to fetch some of the required
  64. // source sensors). See the condition below.
  65. return;
  66. }
  67. if (!sensor) {
  68. std::move(result_callback_).Run(nullptr);
  69. return;
  70. }
  71. mojom::SensorType type = sensor->GetType();
  72. sources_map_[type] = std::move(sensor);
  73. if (sources_map_.size() == fusion_algorithm_->source_types().size()) {
  74. scoped_refptr<PlatformSensor> fusion_sensor(new PlatformSensorFusion(
  75. reading_buffer_, provider_, std::move(fusion_algorithm_),
  76. std::move(sources_map_)));
  77. std::move(result_callback_).Run(fusion_sensor);
  78. }
  79. }
  80. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm_;
  81. PlatformSensorProviderBase::CreateSensorCallback result_callback_;
  82. raw_ptr<SensorReadingSharedBuffer>
  83. reading_buffer_; // NOTE: Owned by |provider_|.
  84. raw_ptr<PlatformSensorProvider> provider_;
  85. PlatformSensorFusion::SourcesMap sources_map_;
  86. };
  87. // static
  88. void PlatformSensorFusion::Create(
  89. SensorReadingSharedBuffer* reading_buffer,
  90. PlatformSensorProvider* provider,
  91. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm,
  92. PlatformSensorProviderBase::CreateSensorCallback callback) {
  93. Factory::CreateSensorFusion(reading_buffer, std::move(fusion_algorithm),
  94. std::move(callback), provider);
  95. }
  96. PlatformSensorFusion::PlatformSensorFusion(
  97. SensorReadingSharedBuffer* reading_buffer,
  98. PlatformSensorProvider* provider,
  99. std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm,
  100. PlatformSensorFusion::SourcesMap sources)
  101. : PlatformSensor(fusion_algorithm->fused_type(), reading_buffer, provider),
  102. fusion_algorithm_(std::move(fusion_algorithm)),
  103. source_sensors_(std::move(sources)),
  104. reporting_mode_(mojom::ReportingMode::CONTINUOUS) {
  105. for (const auto& pair : source_sensors_)
  106. pair.second->AddClient(this);
  107. fusion_algorithm_->set_fusion_sensor(this);
  108. if (base::ranges::any_of(source_sensors_, [](const auto& pair) {
  109. return pair.second->GetReportingMode() ==
  110. mojom::ReportingMode::ON_CHANGE;
  111. })) {
  112. reporting_mode_ = mojom::ReportingMode::ON_CHANGE;
  113. }
  114. }
  115. PlatformSensorFusion::~PlatformSensorFusion() {
  116. for (const auto& pair : source_sensors_)
  117. pair.second->RemoveClient(this);
  118. }
  119. mojom::ReportingMode PlatformSensorFusion::GetReportingMode() {
  120. return reporting_mode_;
  121. }
  122. PlatformSensorConfiguration PlatformSensorFusion::GetDefaultConfiguration() {
  123. PlatformSensorConfiguration default_configuration;
  124. for (const auto& pair : source_sensors_) {
  125. double frequency = pair.second->GetDefaultConfiguration().frequency();
  126. if (frequency > default_configuration.frequency())
  127. default_configuration.set_frequency(frequency);
  128. }
  129. return default_configuration;
  130. }
  131. bool PlatformSensorFusion::StartSensor(
  132. const PlatformSensorConfiguration& configuration) {
  133. // Remove all the previously added source configs.
  134. StopSensor();
  135. for (const auto& pair : source_sensors_) {
  136. if (!pair.second->StartListening(
  137. this, PlatformSensorConfiguration(
  138. std::min(configuration.frequency(),
  139. pair.second->GetMaximumSupportedFrequency())))) {
  140. StopSensor();
  141. return false;
  142. }
  143. }
  144. fusion_algorithm_->SetFrequency(configuration.frequency());
  145. return true;
  146. }
  147. void PlatformSensorFusion::StopSensor() {
  148. for (const auto& pair : source_sensors_)
  149. pair.second->StopListening(this);
  150. fusion_algorithm_->Reset();
  151. }
  152. bool PlatformSensorFusion::CheckSensorConfiguration(
  153. const PlatformSensorConfiguration& configuration) {
  154. for (const auto& pair : source_sensors_) {
  155. if (!pair.second->CheckSensorConfiguration(PlatformSensorConfiguration(
  156. std::min(configuration.frequency(),
  157. pair.second->GetMaximumSupportedFrequency()))))
  158. return false;
  159. }
  160. return true;
  161. }
  162. double PlatformSensorFusion::GetMaximumSupportedFrequency() {
  163. double maximum_frequency = 0.0;
  164. for (const auto& pair : source_sensors_) {
  165. maximum_frequency = std::max(maximum_frequency,
  166. pair.second->GetMaximumSupportedFrequency());
  167. }
  168. return maximum_frequency;
  169. }
  170. void PlatformSensorFusion::OnSensorReadingChanged(mojom::SensorType type) {
  171. SensorReading reading;
  172. reading.raw.timestamp =
  173. (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
  174. if (!fusion_algorithm_->GetFusedData(type, &reading))
  175. return;
  176. UpdateSharedBufferAndNotifyClients(reading);
  177. }
  178. void PlatformSensorFusion::OnSensorError() {
  179. NotifySensorError();
  180. }
  181. bool PlatformSensorFusion::IsSuspended() {
  182. for (auto& client : clients_) {
  183. if (!client.IsSuspended())
  184. return false;
  185. }
  186. return true;
  187. }
  188. bool PlatformSensorFusion::GetSourceReading(mojom::SensorType type,
  189. SensorReading* result) {
  190. auto it = source_sensors_.find(type);
  191. if (it != source_sensors_.end())
  192. return it->second->GetLatestRawReading(result);
  193. NOTREACHED();
  194. return false;
  195. }
  196. bool PlatformSensorFusion::IsSignificantlyDifferent(
  197. const SensorReading& reading1,
  198. const SensorReading& reading2,
  199. mojom::SensorType) {
  200. for (size_t i = 0; i < SensorReadingRaw::kValuesCount; ++i) {
  201. if (std::fabs(reading1.raw.values[i] - reading2.raw.values[i]) >=
  202. fusion_algorithm_->threshold()) {
  203. return true;
  204. }
  205. }
  206. return false;
  207. }
  208. } // namespace device