blob: 39300e4c3f6879f00545f592c41c9eab4b5355a5 [file] [log] [blame]
/*
* Copyright 2021 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef CAMERA_COMMON_SENSOR_HAL_CLIENT_IMPL_H_
#define CAMERA_COMMON_SENSOR_HAL_CLIENT_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <base/memory/weak_ptr.h>
#include <base/single_thread_task_runner.h>
#include <base/synchronization/lock.h>
#include <iioservice/mojo/cros_sensor_service.mojom.h>
#include <iioservice/mojo/sensor.mojom.h>
#include <mojo/public/cpp/bindings/pending_receiver.h>
#include <mojo/public/cpp/bindings/pending_remote.h>
#include <mojo/public/cpp/bindings/receiver.h>
#include <mojo/public/cpp/bindings/remote.h>
#include "common/sensor_reader.h"
#include "cros-camera/camera_mojo_channel_manager.h"
#include "cros-camera/future.h"
#include "cros-camera/sensor_hal_client.h"
namespace cros {
class CameraMojoChannelManager;
class SensorHalClientImpl final : public SensorHalClient {
public:
explicit SensorHalClientImpl(CameraMojoChannelManager* mojo_manager);
SensorHalClientImpl(const SensorHalClientImpl&) = delete;
SensorHalClientImpl& operator=(const SensorHalClientImpl&) = delete;
~SensorHalClientImpl();
// SensorHalClient implementations.
bool HasDevice(DeviceType type, Location location);
bool RegisterSamplesObserver(DeviceType type,
Location location,
double frequency,
SamplesObserver* samples_observer);
void UnregisterSamplesObserver(SamplesObserver* samples_observer);
private:
// IPCBridge wraps all the IPC-related calls. Most of its methods should/will
// be run on IPC thread.
class IPCBridge : public mojom::SensorHalClient,
public mojom::SensorServiceNewDevicesObserver {
public:
IPCBridge(CameraMojoChannelManager* mojo_manager,
CancellationRelay* cancellation_relay);
// It should only be triggered on IPC thread to ensure thread-safety.
~IPCBridge();
// Will only be called once, right after the c'tor.
void Start();
void HasDevice(mojom::DeviceType type,
Location location,
base::OnceCallback<void(bool)> callback);
void RegisterSamplesObserver(mojom::DeviceType type,
Location location,
double frequency,
SamplesObserver* samples_observer,
base::OnceCallback<void(bool)> callback);
void UnregisterSamplesObserver(SamplesObserver* samples_observer);
// SensorHalClient Mojo interface implementation.
void SetUpChannel(
mojo::PendingRemote<mojom::SensorService> pending_remote) final;
// SensorServiceNewDevicesObserver Mojo interface implementation.
void OnNewDeviceAdded(int32_t iio_device_id,
const std::vector<mojom::DeviceType>& types) final;
bool ClientIsBound() { return receiver_.is_bound(); }
bool IsReady() { return sensor_service_remote_.is_bound(); }
// Gets a weak pointer of the IPCBridge. This method can be called on
// non-IPC thread.
base::WeakPtr<IPCBridge> GetWeakPtr();
private:
struct DeviceData {
bool ignored = false;
std::vector<mojom::DeviceType> types;
base::Optional<Location> location;
base::Optional<double> scale;
// Temporarily stores the remote, waiting for its attributes information.
// It'll be passed to SensorDevice's constructor as an argument after all
// information is collected, if this device is needed.
mojo::Remote<mojom::SensorDevice> remote;
};
struct DeviceQueryInfo {
mojom::DeviceType type;
Location location;
base::OnceCallback<void(bool)> callback;
};
struct ReaderData {
int32_t iio_device_id;
mojom::DeviceType type;
double frequency;
std::unique_ptr<SensorReader> sensor_reader;
};
void OnDeviceQueryTimedOut(uint32_t info_id);
void RegisterDevice(int32_t iio_device_id,
const std::vector<mojom::DeviceType>& types);
void GetAllDeviceIdsCallback(
const base::flat_map<int32_t, std::vector<mojom::DeviceType>>&
iio_device_ids_types);
mojo::Remote<mojom::SensorDevice> GetSensorDeviceRemote(
int32_t iio_device_id);
void GetAttributesCallback(
int32_t iio_device_id,
const std::vector<std::string> attr_names,
const std::vector<base::Optional<std::string>>& values);
void IgnoreDevice(int32_t iio_device_id);
// Return true if all devices of |type| are initialized and attributes are
// ready. We can further process the queries of |type|.
bool AreAllDevicesOfTypeInitialized(mojom::DeviceType type);
void RunDeviceQueriesForType(mojom::DeviceType type);
bool HasDeviceInternal(mojom::DeviceType type, Location location);
void OnClientRegistered(int32_t result);
void OnServiceMojoChannelError();
void ResetSensorService();
void OnSensorServiceDisconnect();
void OnNewDevicesObserverDisconnect();
void OnSensorDeviceDisconnect(int32_t iio_device_id,
uint32_t custom_reason_code,
const std::string& description);
CameraMojoChannelManager* mojo_manager_;
CancellationRelay* cancellation_relay_;
// The Mojo IPC task runner.
const scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
mojo::Receiver<mojom::SensorHalClient> receiver_{this};
mojo::Remote<mojom::SensorService> sensor_service_remote_;
// The Mojo channel to get notified when new devices are added to IIO
// Service.
mojo::Receiver<mojom::SensorServiceNewDevicesObserver>
new_devices_observer_{this};
uint32_t device_query_info_counter_ = 0;
// First is the info id, second is the pending HasDevice query.
std::map<uint32_t, DeviceQueryInfo> device_queries_info_;
// Maps from DeviceType and Location to id.
std::map<mojom::DeviceType, std::map<Location, int32_t>> device_maps_;
bool devices_retrieved_ = false;
// First is iio_device_id, second is the device's attributes and Mojo
// remote.
std::map<int32_t, DeviceData> devices_;
// First is the observer's pointer, second is the specific sensor reader.
std::map<SamplesObserver*, ReaderData> readers_;
base::WeakPtrFactory<IPCBridge> weak_ptr_factory_{this};
};
CameraMojoChannelManager* mojo_manager_;
std::unique_ptr<CancellationRelay> cancellation_relay_;
// The instance which deals with the IPC-related calls. It should always run
// and be deleted on IPC thread.
std::unique_ptr<IPCBridge> ipc_bridge_;
};
} // namespace cros
#endif // CAMERA_COMMON_SENSOR_HAL_CLIENT_IMPL_H_