platform_sensor.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback.h"
  8. #include "base/check.h"
  9. #include "base/containers/cxx20_erase.h"
  10. #include "base/observer_list.h"
  11. #include "base/threading/sequenced_task_runner_handle.h"
  12. #include "services/device/generic_sensor/platform_sensor_provider.h"
  13. #include "services/device/generic_sensor/platform_sensor_util.h"
  14. #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
  15. #include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
  16. namespace device {
  17. PlatformSensor::PlatformSensor(mojom::SensorType type,
  18. SensorReadingSharedBuffer* reading_buffer,
  19. PlatformSensorProvider* provider)
  20. : main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
  21. reading_buffer_(reading_buffer),
  22. type_(type),
  23. provider_(provider) {
  24. VLOG(1) << "Platform sensor created. Type " << type_ << ".";
  25. }
  26. PlatformSensor::~PlatformSensor() {
  27. if (provider_)
  28. provider_->RemoveSensor(GetType(), this);
  29. VLOG(1) << "Platform sensor released. Type " << type_ << ".";
  30. }
  31. mojom::SensorType PlatformSensor::GetType() const {
  32. return type_;
  33. }
  34. double PlatformSensor::GetMaximumSupportedFrequency() {
  35. return GetDefaultConfiguration().frequency();
  36. }
  37. double PlatformSensor::GetMinimumSupportedFrequency() {
  38. return 1.0 / (60 * 60);
  39. }
  40. void PlatformSensor::SensorReplaced() {
  41. ResetReadingBuffer();
  42. }
  43. bool PlatformSensor::StartListening(Client* client,
  44. const PlatformSensorConfiguration& config) {
  45. DCHECK(clients_.HasObserver(client));
  46. if (!CheckSensorConfiguration(config))
  47. return false;
  48. auto& config_list = config_map_[client];
  49. config_list.push_back(config);
  50. if (!UpdateSensorInternal(config_map_)) {
  51. config_list.pop_back();
  52. return false;
  53. }
  54. return true;
  55. }
  56. bool PlatformSensor::StopListening(Client* client,
  57. const PlatformSensorConfiguration& config) {
  58. DCHECK(clients_.HasObserver(client));
  59. auto client_entry = config_map_.find(client);
  60. if (client_entry == config_map_.end())
  61. return false;
  62. auto& config_list = client_entry->second;
  63. if (base::Erase(config_list, config) == 0)
  64. return false;
  65. return UpdateSensorInternal(config_map_);
  66. }
  67. bool PlatformSensor::StopListening(Client* client) {
  68. DCHECK(client);
  69. if (config_map_.erase(client) == 0)
  70. return false;
  71. return UpdateSensorInternal(config_map_);
  72. }
  73. void PlatformSensor::UpdateSensor() {
  74. UpdateSensorInternal(config_map_);
  75. }
  76. void PlatformSensor::AddClient(Client* client) {
  77. DCHECK(client);
  78. clients_.AddObserver(client);
  79. }
  80. void PlatformSensor::RemoveClient(Client* client) {
  81. DCHECK(client);
  82. clients_.RemoveObserver(client);
  83. StopListening(client);
  84. }
  85. bool PlatformSensor::GetLatestReading(SensorReading* result) {
  86. if (!reading_buffer_)
  87. return false;
  88. return SensorReadingSharedBufferReader::GetReading(reading_buffer_, result);
  89. }
  90. bool PlatformSensor::GetLatestRawReading(SensorReading* result) const {
  91. base::AutoLock auto_lock(lock_);
  92. if (!last_raw_reading_.has_value())
  93. return false;
  94. *result = last_raw_reading_.value();
  95. return true;
  96. }
  97. void PlatformSensor::UpdateSharedBufferAndNotifyClients(
  98. const SensorReading& reading) {
  99. if (UpdateSharedBuffer(reading, /*do_significance_check=*/true)) {
  100. main_task_runner()->PostTask(
  101. FROM_HERE, base::BindOnce(&PlatformSensor::NotifySensorReadingChanged,
  102. weak_factory_.GetWeakPtr()));
  103. }
  104. }
  105. bool PlatformSensor::UpdateSharedBuffer(const SensorReading& reading,
  106. bool do_significance_check) {
  107. if (!reading_buffer_)
  108. return false;
  109. {
  110. base::AutoLock auto_lock(lock_);
  111. // Bail out early if the new reading does not differ significantly from
  112. // our current one, when the sensor is not reporting data continuously.
  113. // Empty readings (i.e. with a zero timestamp) are always processed.
  114. if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE &&
  115. do_significance_check && last_raw_reading_.has_value() &&
  116. !IsSignificantlyDifferent(*last_raw_reading_, reading, type_)) {
  117. return false;
  118. }
  119. // Save the raw (non-rounded) reading for fusion sensors.
  120. last_raw_reading_ = reading;
  121. }
  122. ReadingBuffer* buffer = reading_buffer_;
  123. auto& seqlock = buffer->seqlock.value();
  124. // Round the reading to guard user privacy. See https://crbug.com/1018180.
  125. SensorReading rounded_reading = reading;
  126. RoundSensorReading(&rounded_reading, type_);
  127. {
  128. base::AutoLock auto_lock(lock_);
  129. // Report new values only if rounded value is different compared to
  130. // previous value.
  131. if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE &&
  132. do_significance_check && last_rounded_reading_.has_value() &&
  133. base::ranges::equal(rounded_reading.raw.values,
  134. last_rounded_reading_->raw.values)) {
  135. return false;
  136. }
  137. // Save rounded value for next comparison.
  138. last_rounded_reading_ = rounded_reading;
  139. }
  140. seqlock.WriteBegin();
  141. buffer->reading = rounded_reading;
  142. seqlock.WriteEnd();
  143. return true;
  144. }
  145. void PlatformSensor::NotifySensorReadingChanged() {
  146. for (auto& client : clients_) {
  147. if (!client.IsSuspended())
  148. client.OnSensorReadingChanged(type_);
  149. }
  150. }
  151. void PlatformSensor::NotifySensorError() {
  152. for (auto& client : clients_)
  153. client.OnSensorError();
  154. }
  155. void PlatformSensor::ResetReadingBuffer() {
  156. reading_buffer_ = nullptr;
  157. }
  158. bool PlatformSensor::UpdateSensorInternal(const ConfigMap& configurations) {
  159. const PlatformSensorConfiguration* optimal_configuration = nullptr;
  160. for (const auto& pair : configurations) {
  161. if (pair.first->IsSuspended())
  162. continue;
  163. const auto& conf_list = pair.second;
  164. for (const auto& configuration : conf_list) {
  165. if (!optimal_configuration || configuration > *optimal_configuration)
  166. optimal_configuration = &configuration;
  167. }
  168. }
  169. if (!optimal_configuration) {
  170. is_active_ = false;
  171. StopSensor();
  172. // If we reached this condition, we want to set the current reading to zero
  173. // regardless of the previous reading's value per
  174. // https://w3c.github.io/sensors/#set-sensor-settings. That is the reason
  175. // to skip significance check.
  176. UpdateSharedBuffer(SensorReading(), /*do_significance_check=*/false);
  177. return true;
  178. }
  179. is_active_ = StartSensor(*optimal_configuration);
  180. return is_active_;
  181. }
  182. bool PlatformSensor::IsActiveForTesting() const {
  183. return is_active_;
  184. }
  185. auto PlatformSensor::GetConfigMapForTesting() const -> const ConfigMap& {
  186. return config_map_;
  187. }
  188. void PlatformSensor::PostTaskToMainSequence(const base::Location& location,
  189. base::OnceClosure task) {
  190. main_task_runner()->PostTask(location, std::move(task));
  191. }
  192. bool PlatformSensor::IsSignificantlyDifferent(const SensorReading& lhs,
  193. const SensorReading& rhs,
  194. mojom::SensorType sensor_type) {
  195. switch (sensor_type) {
  196. case mojom::SensorType::AMBIENT_LIGHT:
  197. return std::fabs(lhs.als.value - rhs.als.value) >=
  198. kAlsSignificanceThreshold;
  199. case mojom::SensorType::ACCELEROMETER:
  200. case mojom::SensorType::GRAVITY:
  201. case mojom::SensorType::LINEAR_ACCELERATION:
  202. case mojom::SensorType::GYROSCOPE:
  203. case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES:
  204. case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES:
  205. case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION:
  206. case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION:
  207. case mojom::SensorType::MAGNETOMETER:
  208. case mojom::SensorType::PRESSURE:
  209. case mojom::SensorType::PROXIMITY:
  210. return !base::ranges::equal(lhs.raw.values, rhs.raw.values);
  211. }
  212. NOTREACHED();
  213. return false;
  214. }
  215. } // namespace device