blob: ded2ff501301292c51021c355cbfc3247839b62e [file] [log] [blame]
// Copyright 2020 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.
#include "src/camera/lib/fake_camera/fake_camera_impl.h"
#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include "src/camera/lib/fake_stream/fake_stream_impl.h"
namespace camera {
fit::result<std::unique_ptr<FakeCamera>, zx_status_t> FakeCamera::Create(
std::string identifier, std::vector<FakeConfiguration> configurations) {
auto result = FakeCameraImpl::Create(std::move(identifier), std::move(configurations));
if (result.is_error()) {
return fit::error(result.error());
}
return fit::ok(result.take_value());
}
FakeCameraImpl::FakeCameraImpl() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}
FakeCameraImpl::~FakeCameraImpl() {
async::PostTask(loop_.dispatcher(), fit::bind_member(this, &FakeCameraImpl::OnDestruction));
loop_.Quit();
loop_.JoinThreads();
}
static zx_status_t Validate(const std::vector<FakeConfiguration>& configurations) {
zx_status_t status = ZX_OK;
if (configurations.empty()) {
status = ZX_ERR_INVALID_ARGS;
FX_PLOGS(DEBUG, status) << "Configurations must not be empty.";
}
for (const auto& configuration : configurations) {
if (configuration.empty()) {
status = ZX_ERR_INVALID_ARGS;
FX_PLOGS(DEBUG, status) << "Configuration must not be empty.";
}
for (const auto& stream : configuration) {
if (!stream) {
status = ZX_ERR_INVALID_ARGS;
FX_PLOGS(DEBUG, status) << "Stream must be non-null.";
}
}
}
return status;
}
fit::result<std::unique_ptr<FakeCameraImpl>, zx_status_t> FakeCameraImpl::Create(
std::string identifier, std::vector<FakeConfiguration> configurations) {
auto camera = std::make_unique<FakeCameraImpl>();
zx_status_t status = Validate(configurations);
if (status != ZX_OK) {
FX_PLOGS(DEBUG, status) << "Configurations failed validation.";
return fit::error(status);
}
camera->identifier_ = std::move(identifier);
camera->configurations_ = std::move(configurations);
for (auto& configuration : camera->configurations_) {
fuchsia::camera3::Configuration real_configuration;
for (auto& stream : configuration) {
auto stream_impl = reinterpret_cast<FakeStreamImpl*>(stream.get());
real_configuration.streams.push_back(stream_impl->properties_);
}
camera->real_configurations_.push_back(std::move(real_configuration));
}
ZX_ASSERT(camera->loop_.StartThread("Fake Camera Loop") == ZX_OK);
return fit::ok(std::move(camera));
}
fidl::InterfaceRequestHandler<fuchsia::camera3::Device> FakeCameraImpl::GetHandler() {
return fit::bind_member(this, &FakeCameraImpl::OnNewRequest);
}
void FakeCameraImpl::SetHardwareMuteState(bool muted) { bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED); }
void FakeCameraImpl::OnNewRequest(fidl::InterfaceRequest<fuchsia::camera3::Device> request) {
if (bindings_.size() > 0) {
request.Close(ZX_ERR_ALREADY_BOUND);
return;
}
bindings_.AddBinding(this, std::move(request), loop_.dispatcher());
}
void FakeCameraImpl::OnDestruction() { bindings_.CloseAll(ZX_ERR_IO_NOT_PRESENT); }
template <class T>
void FakeCameraImpl::SetDisconnectErrorHandler(fidl::InterfacePtr<T>& p) {
p.set_error_handler([this](zx_status_t status) {
FX_PLOGS(ERROR, status) << "Dependent component disconnected.";
bindings_.CloseAll(ZX_ERR_INTERNAL);
});
}
void FakeCameraImpl::GetIdentifier(GetIdentifierCallback callback) { callback(identifier_); }
void FakeCameraImpl::GetConfigurations(GetConfigurationsCallback callback) {
callback(real_configurations_);
}
void FakeCameraImpl::WatchCurrentConfiguration(WatchCurrentConfigurationCallback callback) {
bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED);
}
void FakeCameraImpl::SetCurrentConfiguration(uint32_t index) {
bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED);
}
void FakeCameraImpl::WatchMuteState(WatchMuteStateCallback callback) {
bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED);
}
void FakeCameraImpl::SetSoftwareMuteState(bool muted, SetSoftwareMuteStateCallback callback) {
bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED);
}
void FakeCameraImpl::ConnectToStream(uint32_t index,
fidl::InterfaceRequest<fuchsia::camera3::Stream> request) {
configurations_[current_configuration_index_][index]->GetHandler()(std::move(request));
}
void FakeCameraImpl::Rebind(fidl::InterfaceRequest<Device> request) {
bindings_.CloseAll(ZX_ERR_NOT_SUPPORTED);
}
} // namespace camera