blob: 95d89dc610c5ba79dd12229c78f70a7dc179fd99 [file] [log] [blame]
// Copyright 2016 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 "services/device/generic_sensor/platform_sensor_provider_linux.h"
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
#include "services/device/generic_sensor/linux/sensor_data_linux.h"
#include "services/device/generic_sensor/platform_sensor_linux.h"
#include "services/device/generic_sensor/platform_sensor_reader_linux.h"
namespace device {
namespace {
constexpr base::TaskTraits kBlockingTaskRunnerTraits = {
base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
} // namespace
PlatformSensorProviderLinux::PlatformSensorProviderLinux()
: sensor_nodes_enumerated_(false),
sensor_nodes_enumeration_started_(false),
blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
kBlockingTaskRunnerTraits)),
sensor_device_manager_(nullptr,
base::OnTaskRunnerDeleter(blocking_task_runner_)) {
sensor_device_manager_.reset(
new SensorDeviceManager(weak_ptr_factory_.GetWeakPtr()));
}
PlatformSensorProviderLinux::~PlatformSensorProviderLinux() = default;
void PlatformSensorProviderLinux::CreateSensorInternal(
mojom::SensorType type,
SensorReadingSharedBuffer* reading_buffer,
CreateSensorCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sensor_nodes_enumerated_) {
if (!sensor_nodes_enumeration_started_) {
// Unretained() is safe because the deletion of |sensor_device_manager_|
// is scheduled on |blocking_task_runner_| when
// PlatformSensorProviderLinux is deleted.
sensor_nodes_enumeration_started_ = blocking_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&SensorDeviceManager::Start,
base::Unretained(sensor_device_manager_.get())));
}
return;
}
if (IsFusionSensorType(type)) {
CreateFusionSensor(type, reading_buffer, std::move(callback));
return;
}
SensorInfoLinux* sensor_device = GetSensorDevice(type);
if (!sensor_device) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(base::MakeRefCounted<PlatformSensorLinux>(
type, reading_buffer, this, sensor_device));
}
void PlatformSensorProviderLinux::FreeResources() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
bool PlatformSensorProviderLinux::IsSensorTypeAvailable(
mojom::SensorType type) const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return GetSensorDevice(type);
}
SensorInfoLinux* PlatformSensorProviderLinux::GetSensorDevice(
mojom::SensorType type) const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
const auto sensor = sensor_devices_by_type_.find(type);
if (sensor == sensor_devices_by_type_.end())
return nullptr;
return sensor->second.get();
}
void PlatformSensorProviderLinux::SetSensorDeviceManagerForTesting(
std::unique_ptr<SensorDeviceManager> sensor_device_manager) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
sensor_device_manager_.reset(sensor_device_manager.release());
}
void PlatformSensorProviderLinux::ProcessStoredRequests() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::vector<mojom::SensorType> request_types = GetPendingRequestTypes();
if (request_types.empty())
return;
for (auto const& type : request_types) {
if (IsFusionSensorType(type)) {
SensorReadingSharedBuffer* reading_buffer =
GetSensorReadingSharedBufferForType(type);
CreateFusionSensor(
type, reading_buffer,
base::BindOnce(&PlatformSensorProviderLinux::NotifySensorCreated,
base::Unretained(this), type));
continue;
}
SensorInfoLinux* device = nullptr;
auto device_entry = sensor_devices_by_type_.find(type);
if (device_entry != sensor_devices_by_type_.end())
device = device_entry->second.get();
CreateSensorAndNotify(type, device);
}
}
void PlatformSensorProviderLinux::CreateSensorAndNotify(
mojom::SensorType type,
SensorInfoLinux* sensor_device) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
scoped_refptr<PlatformSensorLinux> sensor;
SensorReadingSharedBuffer* reading_buffer =
GetSensorReadingSharedBufferForType(type);
if (sensor_device && reading_buffer) {
sensor = new PlatformSensorLinux(type, reading_buffer, this, sensor_device);
}
NotifySensorCreated(type, sensor);
}
void PlatformSensorProviderLinux::OnSensorNodesEnumerated() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!sensor_nodes_enumerated_);
sensor_nodes_enumerated_ = true;
ProcessStoredRequests();
}
void PlatformSensorProviderLinux::OnDeviceAdded(
mojom::SensorType type,
std::unique_ptr<SensorInfoLinux> sensor_device) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// At the moment, we support only one device per type.
if (base::Contains(sensor_devices_by_type_, type)) {
DVLOG(1) << "Sensor ignored. Type " << type
<< ". Node: " << sensor_device->device_node;
return;
}
sensor_devices_by_type_[type] = std::move(sensor_device);
}
void PlatformSensorProviderLinux::OnDeviceRemoved(
mojom::SensorType type,
const std::string& device_node) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto it = sensor_devices_by_type_.find(type);
if (it != sensor_devices_by_type_.end() &&
it->second->device_node == device_node) {
sensor_devices_by_type_.erase(it);
}
}
} // namespace device