/* 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 #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 camera devices. */ CameraHalManager::~CameraHalManager() { if (isRunning()) { exit(0); /* \todo Wait with a timeout, just in case. */ wait(); } } 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_ = new CameraManager(); 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(); /* Clean up the resources we have allocated. */ proxies_.clear(); cameraManager_->stop(); delete cameraManager_; cameraManager_ = nullptr; } CameraProxy *CameraHalManager::open(unsigned int id, const hw_module_t *hardwareModule) { if (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; } unsigned int CameraHalManager::numCameras() const { return cameraManager_->cameras().size(); } int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) { if (!info) return -EINVAL; if (id >= numCameras()) { 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; }