123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/accelerometer/accelerometer_samples_observer.h"
- #include <utility>
- #include "base/bind.h"
- namespace ash {
- namespace {
- constexpr int kTimeoutToleranceInMilliseconds = 500;
- constexpr double kReadFrequencyInHz = 10.0;
- } // namespace
- AccelerometerSamplesObserver::AccelerometerSamplesObserver(
- int iio_device_id,
- mojo::Remote<chromeos::sensors::mojom::SensorDevice> sensor_device_remote,
- float scale,
- OnSampleUpdatedCallback on_sample_updated_callback)
- : iio_device_id_(iio_device_id),
- sensor_device_remote_(std::move(sensor_device_remote)),
- scale_(scale),
- on_sample_updated_callback_(std::move(on_sample_updated_callback)) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sensor_device_remote_.is_bound());
- sensor_device_remote_->GetAllChannelIds(
- base::BindOnce(&AccelerometerSamplesObserver::GetAllChannelIdsCallback,
- weak_factory_.GetWeakPtr()));
- }
- AccelerometerSamplesObserver::~AccelerometerSamplesObserver() = default;
- void AccelerometerSamplesObserver::SetEnabled(bool enabled) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (enabled_ == enabled)
- return;
- enabled_ = enabled;
- UpdateSensorDeviceFrequency();
- }
- void AccelerometerSamplesObserver::OnSampleUpdated(
- const base::flat_map<int32_t, int64_t>& sample) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (sample.size() != kNumberOfAxes) {
- LOG(ERROR) << "Invalid sample with size: " << sample.size();
- OnErrorOccurred(chromeos::sensors::mojom::ObserverErrorType::READ_FAILED);
- return;
- }
- auto it = sample.begin();
- std::vector<float> output_sample;
- for (size_t axes = 0; axes < kNumberOfAxes; ++axes) {
- if (axes != 0)
- ++it;
- if (it == sample.end() || it->first != channel_indices_[axes])
- it = sample.find(channel_indices_[axes]);
- if (it == sample.end()) {
- LOG(ERROR) << "Missing channel: " << kAccelerometerChannels[axes]
- << " in sample";
- OnErrorOccurred(chromeos::sensors::mojom::ObserverErrorType::READ_FAILED);
- return;
- }
- output_sample.push_back(it->second * scale_);
- }
- on_sample_updated_callback_.Run(iio_device_id_, output_sample);
- }
- void AccelerometerSamplesObserver::OnErrorOccurred(
- chromeos::sensors::mojom::ObserverErrorType type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- switch (type) {
- case chromeos::sensors::mojom::ObserverErrorType::ALREADY_STARTED:
- LOG(ERROR) << "Device " << iio_device_id_
- << ": Another observer has already started to read samples";
- Reset();
- break;
- case chromeos::sensors::mojom::ObserverErrorType::FREQUENCY_INVALID:
- if (!enabled_) // It's normal if this observer is not enabled
- break;
- LOG(ERROR) << "Device " << iio_device_id_
- << ": Observer started with an invalid frequency";
- UpdateSensorDeviceFrequency();
- break;
- case chromeos::sensors::mojom::ObserverErrorType::NO_ENABLED_CHANNELS:
- LOG(ERROR) << "Device " << iio_device_id_
- << ": Observer started with no channels enabled";
- if (sensor_device_remote_.is_bound()) {
- sensor_device_remote_->SetChannelsEnabled(
- std::vector<int32_t>(channel_indices_,
- channel_indices_ + kNumberOfAxes),
- /*enable=*/true,
- base::BindOnce(
- &AccelerometerSamplesObserver::SetChannelsEnabledCallback,
- weak_factory_.GetWeakPtr()));
- }
- break;
- case chromeos::sensors::mojom::ObserverErrorType::SET_FREQUENCY_IO_FAILED:
- LOG(ERROR) << "Device " << iio_device_id_
- << ": Failed to set frequency to the physical device";
- break;
- case chromeos::sensors::mojom::ObserverErrorType::GET_FD_FAILED:
- LOG(ERROR) << "Device " << iio_device_id_
- << ": Failed to get the device's fd to poll on";
- break;
- case chromeos::sensors::mojom::ObserverErrorType::READ_FAILED:
- LOG(ERROR) << "Device " << iio_device_id_ << ": Failed to read a sample";
- break;
- case chromeos::sensors::mojom::ObserverErrorType::READ_TIMEOUT:
- LOG(ERROR) << "Device " << iio_device_id_ << ": A read timed out";
- break;
- default:
- LOG(ERROR) << "Device " << iio_device_id_ << ": error "
- << static_cast<int>(type);
- break;
- }
- }
- void AccelerometerSamplesObserver::Reset() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LOG(ERROR) << "Resetting AccelerometerSamplesObserver: " << iio_device_id_;
- receiver_.reset();
- sensor_device_remote_.reset();
- }
- void AccelerometerSamplesObserver::GetAllChannelIdsCallback(
- const std::vector<std::string>& iio_channel_ids) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sensor_device_remote_.is_bound());
- iio_channel_ids_ = std::move(iio_channel_ids);
- for (size_t axis = 0; axis < kNumberOfAxes; ++axis) {
- bool found = false;
- for (size_t channel_index = 0; channel_index < iio_channel_ids_.size();
- ++channel_index) {
- if (iio_channel_ids_[channel_index].compare(
- kAccelerometerChannels[axis]) == 0) {
- found = true;
- channel_indices_[axis] = channel_index;
- break;
- }
- }
- if (!found) {
- LOG(ERROR) << "Missing channel: " << kAccelerometerChannels[axis];
- Reset();
- return;
- }
- }
- sensor_device_remote_->SetChannelsEnabled(
- std::vector<int32_t>(channel_indices_, channel_indices_ + kNumberOfAxes),
- /*enable=*/true,
- base::BindOnce(&AccelerometerSamplesObserver::SetChannelsEnabledCallback,
- weak_factory_.GetWeakPtr()));
- StartReading();
- }
- void AccelerometerSamplesObserver::StartReading() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sensor_device_remote_.is_bound());
- sensor_device_remote_->SetTimeout(kTimeoutToleranceInMilliseconds);
- sensor_device_remote_->StartReadingSamples(GetPendingRemote());
- }
- void AccelerometerSamplesObserver::UpdateSensorDeviceFrequency() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!sensor_device_remote_.is_bound())
- return;
- sensor_device_remote_->SetFrequency(
- enabled_ ? kReadFrequencyInHz : 0.0,
- base::BindOnce(&AccelerometerSamplesObserver::SetFrequencyCallback,
- weak_factory_.GetWeakPtr(), enabled_));
- }
- mojo::PendingRemote<chromeos::sensors::mojom::SensorDeviceSamplesObserver>
- AccelerometerSamplesObserver::GetPendingRemote() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto pending_remote = receiver_.BindNewPipeAndPassRemote();
- receiver_.set_disconnect_handler(
- base::BindOnce(&AccelerometerSamplesObserver::OnObserverDisconnect,
- weak_factory_.GetWeakPtr()));
- return pending_remote;
- }
- void AccelerometerSamplesObserver::OnObserverDisconnect() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- LOG(ERROR) << "OnObserverDisconnect error, assuming IIO Service crashes and "
- "waiting for its relaunch.";
- // Don't reset |sensor_device_remote_| so that AccelerometerProviderMojo can
- // get the disconnection.
- receiver_.reset();
- }
- void AccelerometerSamplesObserver::SetFrequencyCallback(
- bool enabled,
- double result_frequency) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (enabled != enabled_) {
- // As the current configuration (required frequency) is different now,
- // ignore the result of this deprecated |SensorDevice::SetFrequency|.
- return;
- }
- if ((result_frequency > 0.0 && enabled_) ||
- (result_frequency == 0.0 && !enabled_)) {
- return;
- }
- LOG(ERROR) << "Failed to set frequency: " << result_frequency
- << " with the samples observer enabled: "
- << (enabled_ ? "true" : "false");
- Reset();
- }
- void AccelerometerSamplesObserver::SetChannelsEnabledCallback(
- const std::vector<int32_t>& failed_indices) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- for (int32_t index : failed_indices)
- LOG(ERROR) << "Failed to enable " << iio_channel_ids_[index];
- if (!failed_indices.empty())
- Reset();
- }
- } // namespace ash
|