blob: 330fc57527a76a9d79a620d4a78b864d285fc2af [file] [log] [blame]
// Copyright 2024 The Fuchsia 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 SRC_SENSORS_PLAYBACK_PLAYBACK_CONTROLLER_H_
#define SRC_SENSORS_PLAYBACK_PLAYBACK_CONTROLLER_H_
#include <fidl/fuchsia.hardware.sensors/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/fpromise/promise.h>
#include <lib/fpromise/scope.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>
#include <future>
#include <queue>
#include <unordered_map>
#include <vector>
#include "src/camera/lib/actor/actor_base.h"
#include "src/sensors/playback/playback_config_validation.h"
namespace sensors::playback {
class PlaybackController : public camera::actor::ActorBase {
using ActivateSensorError = fuchsia_hardware_sensors::ActivateSensorError;
using DeactivateSensorError = fuchsia_hardware_sensors::DeactivateSensorError;
using ConfigurePlaybackError = fuchsia_hardware_sensors::ConfigurePlaybackError;
using ConfigureSensorRateError = fuchsia_hardware_sensors::ConfigureSensorRateError;
using FixedValuesPlaybackConfig = fuchsia_hardware_sensors::FixedValuesPlaybackConfig;
using PlaybackSourceConfig = fuchsia_hardware_sensors::PlaybackSourceConfig;
using SensorEvent = fuchsia_sensors_types::SensorEvent;
using SensorId = fuchsia_sensors_types::SensorId;
using SensorInfo = fuchsia_sensors_types::SensorInfo;
using SensorRateConfig = fuchsia_sensors_types::SensorRateConfig;
public:
explicit PlaybackController(async_dispatcher_t* dispatcher);
fpromise::promise<void, ConfigurePlaybackError> ConfigurePlayback(
const PlaybackSourceConfig& config);
fpromise::promise<std::vector<SensorInfo>> GetSensorsList();
fpromise::promise<void, ActivateSensorError> ActivateSensor(SensorId sensor_id);
fpromise::promise<void, DeactivateSensorError> DeactivateSensor(SensorId sensor_id);
fpromise::promise<void, ConfigureSensorRateError> ConfigureSensorRate(
SensorId sensor_id, SensorRateConfig rate_config);
fpromise::promise<void> SetDisconnectDriverClientCallback(
std::function<fpromise::promise<void>(zx_status_t)> disconnect_callback);
fpromise::promise<void> SetEventCallback(std::function<void(const SensorEvent&)> event_callback);
void DriverClientDisconnected(fit::callback<void()> unbind_callback);
void PlaybackClientDisconnected(fit::callback<void()> unbind_callback);
private:
constexpr static int64_t kDefaultSamplingPeriodNs = 1e9; // 1 second.
constexpr static int64_t kDefaultMaxReportingLatencyNs = 0; // No buffering.
enum class PlaybackMode : std::uint8_t {
kNone,
kFixedValuesMode,
};
enum class PlaybackState : std::uint8_t { kStopped, kRunning };
struct SensorPlaybackState {
bool enabled = false;
zx::duration sampling_period = zx::duration(kDefaultSamplingPeriodNs);
zx::duration max_reporting_latency = zx::duration(kDefaultMaxReportingLatencyNs);
// Output buffer used when max reporting latency is non-zero.
std::queue<SensorEvent> event_buffer;
// For fixed value playback
std::vector<SensorEvent> fixed_sensor_events;
int next_fixed_event = 0;
std::optional<zx::time> last_scheduled_event_time;
};
// Tells any attached Driver protocol implementation to disconnect their client with the given
// epitaph.
fpromise::promise<void> DisconnectDriverClient(zx_status_t epitaph);
// Populate the sensor lists for this playback component with the sensors from the given list.
// This should only be called from a promise scheduled to run on this actor's executor.
void AdoptSensorList(const std::vector<SensorInfo>& sensor_list);
fpromise::promise<void> ClearPlaybackConfig();
fpromise::promise<void, ConfigurePlaybackError> ConfigureFixedValues(
const FixedValuesPlaybackConfig& config);
fpromise::promise<void> UpdatePlaybackState(SensorId sensor_id, bool enabled);
fpromise::promise<void> ScheduleSensorEvents(SensorId sensor_id);
// Generates the next event for a sensor given the current internal state of the fixed playback
// sequence.
// This should only be called from a promise scheduled to run on this actor's executor.
SensorEvent GenerateNextFixedEventForSensor(SensorId sensor_id, zx::time timestamp);
fpromise::promise<void> ScheduleFixedEvent(SensorId sensor_id);
fpromise::promise<void> SendOrBufferEvent(const SensorEvent& event);
fpromise::promise<void> SendBufferedEvents(SensorId sensor_id);
fpromise::promise<void> StopScheduledPlayback();
// Callback to initiate a driver client disconnect.
std::function<fpromise::promise<void>(zx_status_t)> disconnect_driver_client_callback_;
// Callback to call with sensor events.
std::function<void(const SensorEvent&)> event_callback_;
// List of "sensors" currently provided by the playback data.
std::vector<SensorInfo> sensor_list_;
// Overall playback state.
PlaybackState playback_state_ = PlaybackState::kStopped;
// Playback states for each sensor.
std::unordered_map<SensorId, SensorPlaybackState> sensor_playback_state_;
// Number of currently enabled sensors.
int enabled_sensor_count_ = 0;
// Which playback mode is currently active.
PlaybackMode playback_mode_;
// A promise scope to wrap scheduled SendEvent and scheduling promises.
std::unique_ptr<fpromise::scope> running_playback_scope_;
// This should always be the last thing in the object. Otherwise scheduled tasks within this scope
// which reference members of this object may be allowed to run after destruction of this object
// has started. Keeping this at the end ensures that the scope is destroyed first, cancelling any
// scheduled tasks before the rest of the members are destroyed.
fpromise::scope scope_;
};
} // namespace sensors::playback
#endif // SRC_SENSORS_PLAYBACK_PLAYBACK_CONTROLLER_H_