diff options
Diffstat (limited to 'src/android/camera_hal_manager.cpp')
-rw-r--r-- | src/android/camera_hal_manager.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/android/camera_hal_manager.cpp b/src/android/camera_hal_manager.cpp new file mode 100644 index 00000000..08c759df --- /dev/null +++ b/src/android/camera_hal_manager.cpp @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * camera_hal_manager.cpp - libcamera Android Camera Manager + */ + +#include "camera_hal_manager.h" + +#include <libcamera/camera.h> + +#include "log.h" + +#include "camera_device.h" +#include "camera_proxy.h" + +using namespace libcamera; + +LOG_DECLARE_CATEGORY(HAL); + +/* + * \class CameraHalManager + * + * The HAL camera manager is initializated at camera_module_t 'hal_init()' time + * and spawns its own thread where libcamera related events are dispatched to. + * It wraps the libcamera CameraManager operations and provides helpers for the + * camera_module_t operations, to retrieve the number of cameras in the system, + * their static information and to open and close camera devices. + */ + +int CameraHalManager::init() +{ + /* + * Start the camera HAL manager thread and wait until its + * initialisation completes to be fully operational before + * receiving calls from the camera stack. + */ + start(); + + MutexLocker locker(mutex_); + cv_.wait(locker); + + return 0; +} + +void CameraHalManager::run() +{ + /* + * All the libcamera components must be initialised here, in + * order to bind them to the camera HAL manager thread that + * executes the event dispatcher. + */ + cameraManager_ = libcamera::CameraManager::instance(); + + int ret = cameraManager_->start(); + if (ret) { + LOG(HAL, Error) << "Failed to start camera manager: " + << strerror(-ret); + return; + } + + /* + * For each Camera registered in the system, a CameraProxy + * gets created here to wraps a camera device. + * + * \todo Support camera hotplug. + */ + unsigned int index = 0; + for (auto &camera : cameraManager_->cameras()) { + CameraProxy *proxy = new CameraProxy(index, camera); + proxies_.emplace_back(proxy); + + ++index; + } + + /* + * libcamera has been initialized. Unlock the init() caller + * as we're now ready to handle calls from the framework. + */ + cv_.notify_one(); + + /* Now start processing events and messages. */ + exec(); +} + +CameraProxy *CameraHalManager::open(unsigned int id, + const hw_module_t *hardwareModule) +{ + if (id < 0 || id >= numCameras()) { + LOG(HAL, Error) << "Invalid camera id '" << id << "'"; + return nullptr; + } + + CameraProxy *proxy = proxies_[id].get(); + if (proxy->open(hardwareModule)) + return nullptr; + + LOG(HAL, Info) << "Open camera '" << id << "'"; + + return proxy; +} + +int CameraHalManager::close(CameraProxy *proxy) +{ + proxy->close(); + LOG(HAL, Info) << "Close camera '" << proxy->id() << "'"; + + return 0; +} + +unsigned int CameraHalManager::numCameras() const +{ + return cameraManager_->cameras().size(); +} + +int CameraHalManager::getCameraInfo(int id, struct camera_info *info) +{ + if (!info) + return -EINVAL; + + if (id >= numCameras() || id < 0) { + LOG(HAL, Error) << "Invalid camera id '" << id << "'"; + return -EINVAL; + } + + CameraProxy *proxy = proxies_[id].get(); + + /* \todo Get these info dynamically inspecting the camera module. */ + info->facing = id ? CAMERA_FACING_FRONT : CAMERA_FACING_BACK; + info->orientation = 0; + info->device_version = 0; + info->resource_cost = 0; + info->static_camera_characteristics = proxy->getStaticMetadata(); + info->conflicting_devices = nullptr; + info->conflicting_devices_length = 0; + + return 0; +} |