blob: fe2f6caa526cad074c331a1d6d56a497f6ec4525 [file] [log] [blame]
// Copyright 2019 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 "fake_camera_controller.h"
#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/camera2/hal/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <vector>
#include "src/camera/lib/stream_utils/stream_constraints.h"
#include "src/lib/syslog/cpp/logger.h"
namespace camera {
std::vector<fuchsia::camera2::hal::Config> FakeController::InvalidConfigs() {
std::vector<fuchsia::camera2::hal::Config> configs(2);
return configs;
}
std::vector<fuchsia::camera2::hal::Config> FakeController::StandardConfigs() {
std::vector<fuchsia::camera2::hal::Config> configs(2);
StreamConstraints ml_mon_stream(fuchsia::camera2::CameraStreamType::MACHINE_LEARNING |
fuchsia::camera2::CameraStreamType::MONITORING);
ml_mon_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
configs[0].stream_configs.push_back(ml_mon_stream.ConvertToStreamConfig());
StreamConstraints mon_stream(fuchsia::camera2::CameraStreamType::MONITORING);
mon_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
mon_stream.AddImageFormat(896, 1600, fuchsia::sysmem::PixelFormatType::NV12);
configs[0].stream_configs.push_back(mon_stream.ConvertToStreamConfig());
StreamConstraints ml_vid_stream(fuchsia::camera2::CameraStreamType::MACHINE_LEARNING |
fuchsia::camera2::CameraStreamType::VIDEO_CONFERENCE);
ml_vid_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
configs[1].stream_configs.push_back(ml_vid_stream.ConvertToStreamConfig());
StreamConstraints vid_stream(fuchsia::camera2::CameraStreamType::VIDEO_CONFERENCE);
vid_stream.AddImageFormat(640, 512, fuchsia::sysmem::PixelFormatType::NV12);
vid_stream.AddImageFormat(2176, 2720, fuchsia::sysmem::PixelFormatType::NV12);
configs[1].stream_configs.push_back(vid_stream.ConvertToStreamConfig());
return configs;
}
static bool CheckMatchingChannel(const zx::channel& client_side, const zx::channel& server_side) {
zx_info_handle_basic_t info[2];
zx_status_t status = client_side.get_info(ZX_INFO_HANDLE_BASIC, &info[0],
sizeof(zx_info_handle_basic_t), nullptr, nullptr);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "Failed to get client side koid.";
return false;
}
status = server_side.get_info(ZX_INFO_HANDLE_BASIC, &info[1], sizeof(zx_info_handle_basic_t),
nullptr, nullptr);
if (status != ZX_OK || info[1].koid == 0) {
FX_LOGS(ERROR) << "Failed to get server side koid.";
return false;
}
return (info[0].related_koid == info[1].koid) && (info[1].related_koid == info[0].koid);
}
FakeController::FakeController(std::vector<fuchsia::camera2::hal::Config> configs,
async_dispatcher_t* dispatcher)
: configs_(std::move(configs)), dispatcher_(dispatcher) {}
fidl::InterfaceHandle<fuchsia::camera2::hal::Controller> FakeController::GetCameraConnection() {
ZX_ASSERT(!binding_.is_bound());
fidl::InterfaceHandle<fuchsia::camera2::hal::Controller> client;
binding_.Bind(client.NewRequest(), dispatcher_);
return client;
}
void FakeController::GetConfigs(GetConfigsCallback callback) {
// Make up some configs:
std::vector<fuchsia::camera2::hal::Config> empty_configs;
switch (configs_failure_) {
case GetConfigsFailureMode::VALID_CONFIGS:
callback(fidl::Clone(configs_), ZX_OK);
break;
case GetConfigsFailureMode::RETURNS_ERROR:
callback(fidl::Clone(configs_), ZX_ERR_INTERNAL);
break;
case GetConfigsFailureMode::EMPTY_VECTOR:
callback(std::move(empty_configs), ZX_OK);
break;
case GetConfigsFailureMode::INVALID_CONFIG:
callback(InvalidConfigs(), ZX_ERR_INTERNAL);
break;
}
}
void FakeController::CreateStream(uint32_t config_index, uint32_t stream_index,
uint32_t image_format_index,
fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection,
fidl::InterfaceRequest<fuchsia::camera2::Stream> stream) {
CameraConnection conn = {.config_index = config_index,
.stream_index = stream_index,
.image_format_index = image_format_index,
.buffer_collection = std::move(buffer_collection),
.stream = std::move(stream)};
fbl::AutoLock lock(&connections_lock_);
connections_.push_back(std::move(conn));
}
void FakeController::GetDeviceInfo(GetDeviceInfoCallback callback) {
const char* kVirtualCameraVendorName = "Google Inc.";
const char* kVirtualCameraProductName = "Fuchsia Fake Camera";
fuchsia::camera2::DeviceInfo camera_device_info;
camera_device_info.set_vendor_name(kVirtualCameraVendorName);
camera_device_info.set_product_name(kVirtualCameraProductName);
camera_device_info.set_type(fuchsia::camera2::DeviceType::VIRTUAL);
callback(std::move(camera_device_info));
}
bool FakeController::HasMatchingChannel(const zx::channel& client_side) {
fbl::AutoLock lock(&connections_lock_);
for (auto& connection : connections_) {
if (CheckMatchingChannel(connection.stream.channel(), client_side)) {
return true;
}
}
return false;
}
} // namespace camera