| // 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 |