platform_sensor_provider_chromeos.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Copyright 2020 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_provider_chromeos.h"
  5. #include <algorithm>
  6. #include <iterator>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/containers/contains.h"
  10. #include "base/containers/cxx20_erase_map.h"
  11. #include "base/memory/scoped_refptr.h"
  12. #include "base/ranges/algorithm.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "base/threading/sequenced_task_runner_handle.h"
  15. #include "chromeos/components/sensors/sensor_util.h"
  16. #include "services/device/generic_sensor/platform_sensor_chromeos.h"
  17. using chromeos::sensors::mojom::SensorDeviceDisconnectReason;
  18. namespace device {
  19. namespace {
  20. constexpr base::TimeDelta kReconnectDelay = base::Milliseconds(1000);
  21. absl::optional<mojom::SensorType> ConvertSensorType(
  22. chromeos::sensors::mojom::DeviceType device_type) {
  23. switch (device_type) {
  24. case chromeos::sensors::mojom::DeviceType::ACCEL:
  25. return mojom::SensorType::ACCELEROMETER;
  26. case chromeos::sensors::mojom::DeviceType::ANGLVEL:
  27. return mojom::SensorType::GYROSCOPE;
  28. case chromeos::sensors::mojom::DeviceType::LIGHT:
  29. return mojom::SensorType::AMBIENT_LIGHT;
  30. case chromeos::sensors::mojom::DeviceType::MAGN:
  31. return mojom::SensorType::MAGNETOMETER;
  32. case chromeos::sensors::mojom::DeviceType::GRAVITY:
  33. return mojom::SensorType::GRAVITY;
  34. default:
  35. return absl::nullopt;
  36. }
  37. }
  38. bool DeviceNeedsLocationWithTypes(const std::vector<mojom::SensorType>& types) {
  39. for (auto type : types) {
  40. switch (type) {
  41. case mojom::SensorType::AMBIENT_LIGHT:
  42. case mojom::SensorType::ACCELEROMETER:
  43. case mojom::SensorType::GYROSCOPE:
  44. case mojom::SensorType::MAGNETOMETER:
  45. case mojom::SensorType::GRAVITY:
  46. return true;
  47. default:
  48. break;
  49. }
  50. }
  51. return false;
  52. }
  53. } // namespace
  54. PlatformSensorProviderChromeOS::PlatformSensorProviderChromeOS() {
  55. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  56. RegisterSensorClient();
  57. }
  58. PlatformSensorProviderChromeOS::~PlatformSensorProviderChromeOS() {
  59. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  60. }
  61. void PlatformSensorProviderChromeOS::SetUpChannel(
  62. mojo::PendingRemote<chromeos::sensors::mojom::SensorService>
  63. pending_remote) {
  64. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  65. if (sensor_service_remote_.is_bound()) {
  66. LOG(ERROR) << "Ignoring the second Remote<SensorService>";
  67. return;
  68. }
  69. sensor_service_remote_.Bind(std::move(pending_remote));
  70. sensor_service_remote_.set_disconnect_handler(
  71. base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorServiceDisconnect,
  72. weak_ptr_factory_.GetWeakPtr()));
  73. sensor_service_remote_->RegisterNewDevicesObserver(
  74. new_devices_observer_.BindNewPipeAndPassRemote());
  75. new_devices_observer_.set_disconnect_handler(base::BindOnce(
  76. &PlatformSensorProviderChromeOS::OnNewDevicesObserverDisconnect,
  77. weak_ptr_factory_.GetWeakPtr()));
  78. sensor_service_remote_->GetAllDeviceIds(
  79. base::BindOnce(&PlatformSensorProviderChromeOS::GetAllDeviceIdsCallback,
  80. weak_ptr_factory_.GetWeakPtr()));
  81. }
  82. void PlatformSensorProviderChromeOS::OnNewDeviceAdded(
  83. int32_t iio_device_id,
  84. const std::vector<chromeos::sensors::mojom::DeviceType>& types) {
  85. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  86. if (base::Contains(sensors_, iio_device_id))
  87. return;
  88. RegisterDevice(iio_device_id, types);
  89. }
  90. void PlatformSensorProviderChromeOS::CreateSensorInternal(
  91. mojom::SensorType type,
  92. SensorReadingSharedBuffer* reading_buffer,
  93. CreateSensorCallback callback) {
  94. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  95. if (!sensor_service_remote_.is_bound() || !AreAllSensorsReady()) {
  96. // Wait until |sensor_service_remote_| is connected and all sensors are
  97. // ready to proceed.
  98. // If |sensor_service_remote_| is disconnected, wait until it re-connects to
  99. // proceed, as it needs a valid SensorDevice channel.
  100. return;
  101. }
  102. // As mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES needs to know
  103. // whether mojom::SensorType::GYROSCOPE exists or not to determine the
  104. // algorithm, wait until all sensors ready before processing the fusion
  105. // sensors as well.
  106. if (IsFusionSensorType(type)) {
  107. CreateFusionSensor(type, reading_buffer, std::move(callback));
  108. return;
  109. }
  110. auto id_opt = GetDeviceId(type);
  111. if (!id_opt.has_value()) {
  112. std::move(callback).Run(nullptr);
  113. return;
  114. }
  115. int32_t id = id_opt.value();
  116. DCHECK(base::Contains(sensors_, id));
  117. auto& sensor = sensors_[id];
  118. DCHECK(sensor.scale.has_value());
  119. auto sensor_device_remote = GetSensorDeviceRemote(id);
  120. std::move(callback).Run(base::MakeRefCounted<PlatformSensorChromeOS>(
  121. id, type, reading_buffer, this,
  122. base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect,
  123. weak_ptr_factory_.GetWeakPtr(), id),
  124. sensor.scale.value(), std::move(sensor_device_remote)));
  125. }
  126. void PlatformSensorProviderChromeOS::FreeResources() {
  127. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  128. }
  129. bool PlatformSensorProviderChromeOS::IsFusionSensorType(
  130. mojom::SensorType type) const {
  131. // Let iioservice provide the Gravity sensor.
  132. switch (type) {
  133. case mojom::SensorType::LINEAR_ACCELERATION:
  134. case mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES:
  135. case mojom::SensorType::ABSOLUTE_ORIENTATION_QUATERNION:
  136. case mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES:
  137. case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION:
  138. return true;
  139. default:
  140. return false;
  141. }
  142. }
  143. bool PlatformSensorProviderChromeOS::IsSensorTypeAvailable(
  144. mojom::SensorType type) const {
  145. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  146. return GetDeviceId(type).has_value();
  147. }
  148. PlatformSensorProviderChromeOS::SensorData::SensorData() = default;
  149. PlatformSensorProviderChromeOS::SensorData::~SensorData() = default;
  150. absl::optional<PlatformSensorProviderChromeOS::SensorLocation>
  151. PlatformSensorProviderChromeOS::ParseLocation(
  152. const absl::optional<std::string>& raw_location) {
  153. if (!raw_location.has_value()) {
  154. LOG(ERROR) << "No location attribute";
  155. return absl::nullopt;
  156. }
  157. // These locations must be listed in the same order as the SensorLocation
  158. // enum.
  159. const std::vector<std::string> location_strings = {
  160. chromeos::sensors::mojom::kLocationBase,
  161. chromeos::sensors::mojom::kLocationLid,
  162. chromeos::sensors::mojom::kLocationCamera};
  163. const auto it = base::ranges::find(location_strings, raw_location.value());
  164. if (it == std::end(location_strings))
  165. return absl::nullopt;
  166. return static_cast<SensorLocation>(
  167. std::distance(std::begin(location_strings), it));
  168. }
  169. absl::optional<int32_t> PlatformSensorProviderChromeOS::GetDeviceId(
  170. mojom::SensorType type) const {
  171. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  172. const auto type_id = sensor_id_by_type_.find(type);
  173. if (type_id == sensor_id_by_type_.end())
  174. return absl::nullopt;
  175. return type_id->second;
  176. }
  177. void PlatformSensorProviderChromeOS::RegisterSensorClient() {
  178. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  179. DCHECK(!sensor_hal_client_.is_bound());
  180. if (!chromeos::sensors::BindSensorHalClient(
  181. sensor_hal_client_.BindNewPipeAndPassRemote())) {
  182. LOG(ERROR) << "Failed to bind SensorHalClient via Crosapi";
  183. return;
  184. }
  185. sensor_hal_client_.set_disconnect_handler(
  186. base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorHalClientFailure,
  187. weak_ptr_factory_.GetWeakPtr(), kReconnectDelay));
  188. }
  189. void PlatformSensorProviderChromeOS::OnSensorHalClientFailure(
  190. base::TimeDelta reconnection_delay) {
  191. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  192. LOG(ERROR) << "OnSensorHalClientFailure";
  193. ResetSensorService();
  194. sensor_hal_client_.reset();
  195. base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
  196. FROM_HERE,
  197. base::BindOnce(&PlatformSensorProviderChromeOS::RegisterSensorClient,
  198. weak_ptr_factory_.GetWeakPtr()),
  199. reconnection_delay);
  200. }
  201. void PlatformSensorProviderChromeOS::OnSensorServiceDisconnect() {
  202. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  203. LOG(ERROR) << "OnSensorServiceDisconnect";
  204. ResetSensorService();
  205. }
  206. void PlatformSensorProviderChromeOS::OnNewDevicesObserverDisconnect() {
  207. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  208. LOG(ERROR) << "OnNewDevicesObserverDisconnect";
  209. // Assumes IIO Service has crashed and waits for its relaunch.
  210. ResetSensorService();
  211. }
  212. void PlatformSensorProviderChromeOS::ResetSensorService() {
  213. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  214. for (auto& sensor : sensors_) {
  215. // Reset only the remote while keeping the attributes information to speed
  216. // up recovery, as the attributes won't need to be queried again.
  217. sensor.second.remote.reset();
  218. }
  219. // Reset the existing PlatformSensors as well.
  220. for (const auto& type_id : sensor_id_by_type_)
  221. ReplaceAndRemoveSensor(type_id.first);
  222. new_devices_observer_.reset();
  223. sensor_service_remote_.reset();
  224. }
  225. void PlatformSensorProviderChromeOS::GetAllDeviceIdsCallback(
  226. const SensorIdTypesMap& ids_types) {
  227. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  228. DCHECK(sensor_service_remote_.is_bound());
  229. sensor_ids_received_ = true;
  230. for (const auto& id_types : ids_types)
  231. RegisterDevice(id_types.first, id_types.second);
  232. ProcessSensorsIfPossible();
  233. }
  234. void PlatformSensorProviderChromeOS::RegisterDevice(
  235. int32_t id,
  236. const std::vector<chromeos::sensors::mojom::DeviceType>& types) {
  237. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  238. SensorData& sensor = sensors_[id];
  239. if (sensor.ignored)
  240. return;
  241. for (const auto& device_type : types) {
  242. auto type_opt = ConvertSensorType(device_type);
  243. if (!type_opt.has_value())
  244. continue;
  245. sensor.types.push_back(type_opt.value());
  246. }
  247. if (sensor.types.empty()) {
  248. sensor.ignored = true;
  249. return;
  250. }
  251. sensor.remote.reset();
  252. std::vector<std::string> attr_names;
  253. if (!sensor.scale.has_value())
  254. attr_names.push_back(chromeos::sensors::mojom::kScale);
  255. if (DeviceNeedsLocationWithTypes(sensor.types) &&
  256. !sensor.location.has_value()) {
  257. attr_names.push_back(chromeos::sensors::mojom::kLocation);
  258. }
  259. if (attr_names.empty())
  260. return;
  261. sensor.remote = GetSensorDeviceRemote(id);
  262. // Add a temporary disconnect handler to catch failures during sensor
  263. // enumeration. PlatformSensorChromeOS will handle disconnection during
  264. // normal operation.
  265. sensor.remote.set_disconnect_with_reason_handler(
  266. base::BindOnce(&PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect,
  267. weak_ptr_factory_.GetWeakPtr(), id));
  268. sensor.remote->GetAttributes(
  269. std::move(attr_names),
  270. base::BindOnce(&PlatformSensorProviderChromeOS::GetAttributesCallback,
  271. weak_ptr_factory_.GetWeakPtr(), id));
  272. }
  273. void PlatformSensorProviderChromeOS::GetAttributesCallback(
  274. int32_t id,
  275. const std::vector<absl::optional<std::string>>& values) {
  276. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  277. auto it = sensors_.find(id);
  278. DCHECK(it != sensors_.end());
  279. auto& sensor = it->second;
  280. DCHECK(sensor.remote.is_bound());
  281. size_t index = 0;
  282. if (!sensor.scale.has_value()) {
  283. if (index >= values.size()) {
  284. LOG(ERROR) << "values doesn't contain scale attribute.";
  285. IgnoreSensor(sensor);
  286. return;
  287. }
  288. double scale = 0.0;
  289. if (!values[index].has_value() ||
  290. !base::StringToDouble(values[index].value(), &scale)) {
  291. LOG(ERROR) << "Invalid scale: " << values[index].value_or("")
  292. << ", for accel with id: " << id;
  293. IgnoreSensor(sensor);
  294. return;
  295. }
  296. sensor.scale = scale;
  297. ++index;
  298. }
  299. if (DeviceNeedsLocationWithTypes(sensor.types) &&
  300. !sensor.location.has_value()) {
  301. if (index >= values.size()) {
  302. LOG(ERROR) << "values doesn't contain location attribute.";
  303. IgnoreSensor(sensor);
  304. return;
  305. }
  306. sensor.location = ParseLocation(values[index]);
  307. if (!sensor.location.has_value()) {
  308. LOG(ERROR) << "Failed to parse location: " << values[index].value_or("")
  309. << ", with sensor id: " << id;
  310. IgnoreSensor(sensor);
  311. return;
  312. }
  313. ++index;
  314. }
  315. ProcessSensorsIfPossible();
  316. }
  317. void PlatformSensorProviderChromeOS::IgnoreSensor(SensorData& sensor) {
  318. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  319. sensor.ignored = true;
  320. sensor.remote.reset();
  321. ProcessSensorsIfPossible();
  322. }
  323. bool PlatformSensorProviderChromeOS::AreAllSensorsReady() const {
  324. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  325. if (!sensor_ids_received_)
  326. return false;
  327. return base::ranges::all_of(sensors_, [](const auto& sensor) {
  328. return sensor.second.ignored ||
  329. (sensor.second.scale.has_value() &&
  330. (!DeviceNeedsLocationWithTypes(sensor.second.types) ||
  331. sensor.second.location.has_value()));
  332. });
  333. }
  334. void PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect(
  335. int32_t id,
  336. uint32_t custom_reason_code,
  337. const std::string& description) {
  338. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  339. auto reason =
  340. static_cast<chromeos::sensors::mojom::SensorDeviceDisconnectReason>(
  341. custom_reason_code);
  342. LOG(ERROR) << "OnSensorDeviceDisconnect: " << id << ", reason: " << reason
  343. << ", description: " << description;
  344. switch (reason) {
  345. case SensorDeviceDisconnectReason::IIOSERVICE_CRASHED:
  346. ResetSensorService();
  347. break;
  348. case SensorDeviceDisconnectReason::DEVICE_REMOVED:
  349. // Hot-pluggable sensors should be HID-stack sensors and shouldn't have
  350. // the location attribute.
  351. if (sensors_[id].location.has_value()) {
  352. LOG(WARNING) << "Device being removed has location: "
  353. << static_cast<int>(sensors_[id].location.value());
  354. }
  355. base::EraseIf(sensor_id_by_type_, [this, &id](const auto& entry) {
  356. if (entry.second == id) {
  357. ReplaceAndRemoveSensor(entry.first);
  358. return true;
  359. }
  360. return false;
  361. });
  362. sensors_.erase(id);
  363. ProcessSensorsIfPossible();
  364. break;
  365. }
  366. }
  367. void PlatformSensorProviderChromeOS::ReplaceAndRemoveSensor(
  368. mojom::SensorType type) {
  369. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  370. auto* platform_sensor = GetSensor(type).get();
  371. if (platform_sensor)
  372. platform_sensor->SensorReplaced();
  373. RemoveSensor(type, platform_sensor);
  374. }
  375. void PlatformSensorProviderChromeOS::ProcessSensorsIfPossible() {
  376. if (!AreAllSensorsReady())
  377. return;
  378. DetermineMotionSensors();
  379. DetermineLightSensor();
  380. RemoveUnusedSensorDeviceRemotes();
  381. ProcessStoredRequests();
  382. }
  383. // Follow Android's and W3C's requirements of motion sensors:
  384. // Android: https://source.android.com/devices/sensors/sensor-types
  385. // W3C: https://w3c.github.io/sensors/#local-coordinate-system
  386. // To implement fusion/composite sensors, accelerometer, gyroscope (and
  387. // magnetometer) must be in the same plane, so when it comes to choosing an
  388. // accelerometer in a convertible device, we choose the one which is in the
  389. // same place as the gyroscope. If we still have a choice, we use the one in
  390. // the lid.
  391. void PlatformSensorProviderChromeOS::DetermineMotionSensors() {
  392. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  393. struct MotionSensorInfo {
  394. size_t count;
  395. std::vector<std::pair<int32_t, mojom::SensorType>> sensor_info_pairs;
  396. };
  397. std::map<SensorLocation, MotionSensorInfo> motion_sensor_location_info;
  398. for (const auto& sensor : sensors_) {
  399. if (sensor.second.ignored || !sensor.second.location)
  400. continue;
  401. SensorLocation location = sensor.second.location.value();
  402. DCHECK_LT(location, SensorLocation::kMax);
  403. for (auto type : sensor.second.types) {
  404. switch (type) {
  405. case mojom::SensorType::ACCELEROMETER:
  406. case mojom::SensorType::GYROSCOPE:
  407. case mojom::SensorType::MAGNETOMETER: {
  408. auto& motion_sensor_info = motion_sensor_location_info[location];
  409. motion_sensor_info.count++;
  410. motion_sensor_info.sensor_info_pairs.push_back(
  411. std::make_pair(sensor.first, type));
  412. break;
  413. }
  414. case mojom::SensorType::GRAVITY: {
  415. auto& motion_sensor_info = motion_sensor_location_info[location];
  416. // Don't need to increase |motion_sensor_info.count|, as gravity
  417. // sensors shouldn't influence the decision.
  418. motion_sensor_info.sensor_info_pairs.push_back(
  419. std::make_pair(sensor.first, type));
  420. break;
  421. }
  422. default:
  423. break;
  424. }
  425. }
  426. }
  427. const auto preferred_location =
  428. motion_sensor_location_info[SensorLocation::kLid].count >=
  429. motion_sensor_location_info[SensorLocation::kBase].count
  430. ? SensorLocation::kLid
  431. : SensorLocation::kBase;
  432. const auto& sensor_info_pairs =
  433. motion_sensor_location_info[preferred_location].sensor_info_pairs;
  434. for (const auto& pair : sensor_info_pairs)
  435. UpdateSensorIdMapping(pair.second, pair.first);
  436. }
  437. // Prefer the light sensor on the lid, as it's more meaningful to web API users.
  438. void PlatformSensorProviderChromeOS::DetermineLightSensor() {
  439. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  440. absl::optional<int32_t> id = absl::nullopt;
  441. for (const auto& sensor : sensors_) {
  442. if (sensor.second.ignored ||
  443. !base::Contains(sensor.second.types, mojom::SensorType::AMBIENT_LIGHT))
  444. continue;
  445. if (!id.has_value() || sensor.second.location == SensorLocation::kLid)
  446. id = sensor.first;
  447. }
  448. if (id.has_value())
  449. UpdateSensorIdMapping(mojom::SensorType::AMBIENT_LIGHT, id.value());
  450. }
  451. void PlatformSensorProviderChromeOS::UpdateSensorIdMapping(
  452. const mojom::SensorType& type,
  453. int32_t id) {
  454. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  455. auto it = sensor_id_by_type_.find(type);
  456. if (it != sensor_id_by_type_.end() && it->second != id)
  457. ReplaceAndRemoveSensor(type);
  458. sensor_id_by_type_[type] = id;
  459. }
  460. void PlatformSensorProviderChromeOS::RemoveUnusedSensorDeviceRemotes() {
  461. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  462. std::set<int32_t> used_ids;
  463. for (const auto& type_id : sensor_id_by_type_)
  464. used_ids.emplace(type_id.second);
  465. for (auto& sensor : sensors_) {
  466. if (!base::Contains(used_ids, sensor.first))
  467. sensor.second.remote.reset();
  468. }
  469. }
  470. void PlatformSensorProviderChromeOS::ProcessStoredRequests() {
  471. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  472. std::vector<mojom::SensorType> request_types = GetPendingRequestTypes();
  473. for (const auto& type : request_types) {
  474. SensorReadingSharedBuffer* reading_buffer =
  475. GetSensorReadingSharedBufferForType(type);
  476. if (!reading_buffer)
  477. continue;
  478. if (IsFusionSensorType(type)) {
  479. CreateFusionSensor(
  480. type, reading_buffer,
  481. base::BindOnce(&PlatformSensorProviderChromeOS::NotifySensorCreated,
  482. weak_ptr_factory_.GetWeakPtr(), type));
  483. continue;
  484. }
  485. auto id_opt = GetDeviceId(type);
  486. if (!id_opt.has_value()) {
  487. NotifySensorCreated(type, nullptr);
  488. continue;
  489. }
  490. int32_t id = id_opt.value();
  491. DCHECK(base::Contains(sensors_, id));
  492. auto& sensor = sensors_[id];
  493. DCHECK(sensor.scale.has_value());
  494. auto sensor_device_remote = GetSensorDeviceRemote(id);
  495. NotifySensorCreated(
  496. type, base::MakeRefCounted<PlatformSensorChromeOS>(
  497. id, type, reading_buffer, this,
  498. base::BindOnce(
  499. &PlatformSensorProviderChromeOS::OnSensorDeviceDisconnect,
  500. weak_ptr_factory_.GetWeakPtr(), id),
  501. sensor.scale.value(), std::move(sensor_device_remote)));
  502. }
  503. }
  504. mojo::Remote<chromeos::sensors::mojom::SensorDevice>
  505. PlatformSensorProviderChromeOS::GetSensorDeviceRemote(int32_t id) {
  506. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  507. DCHECK(sensor_service_remote_.is_bound());
  508. mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote;
  509. auto& sensor = sensors_[id];
  510. if (sensor.remote.is_bound()) {
  511. // Reuse the previous remote.
  512. sensor_device_remote = std::move(sensor.remote);
  513. } else {
  514. sensor_service_remote_->GetDevice(
  515. id, sensor_device_remote.BindNewPipeAndPassReceiver());
  516. }
  517. return sensor_device_remote;
  518. }
  519. } // namespace device