summaryrefslogtreecommitdiff
path: root/utils/ipc
AgeCommit message (Collapse)Author
2021-08-19ipa: Use FileDescriptor instead of int in layers above IPC payloadPaul Elder
Regarding (de)serialization in isolated IPA calls, we have four layers: - struct - byte vector + fd vector - IPCMessage - IPC payload The proxy handles the upper three layers (with help from the IPADataSerializer), and passes an IPCMessage to the IPC mechanism (implemented as an IPCPipe), which sends an IPC payload to its worker counterpart. When a FileDescriptor is involved, previously it was only a FileDescriptor in the first layer; in the lower three it was an int. To reduce the risk of potential fd leaks in the future, keep the FileDescriptor as-is throughout the upper three layers. Only the IPC mechanism will deal with ints, if it so wishes, when it does the actual IPC. IPCPipeUnixSocket does deal with ints for sending fds, so the conversion between IPCMessage and IPCUnixSocket::Payload converts between FileDescriptor and int. Additionally, change the data portion of the serialized form of FileDescriptor to a 32-bit unsigned integer, for alightnment purposes and in preparation for conversion to an index into the fd array. Also update the deserializer of FrameBuffer::Plane accordingly. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Tested-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
2021-08-18utils: ipc: ipa_proxy_worker: Log IPCUnixSocket::send() failuresLaurent Pinchart
The IPCUnixSocket::send() function may fail, in which case it can be useful for debugging to log an error message that tells which event was affected. Do so. Reported-by: Coverity CID=35483[6-9] Reported-by: Coverity CID=35484[01] Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-08-05utils: ipc: Initialise ThreadProxyKieran Bingham
The ThreadProxy IPA template does not implement a constructor and the default compiler generated constructor does not initialise the private ipa_ pointer. Whilst this should not be expected to be used while uninitialised, it does get caught by static analysis for every IPA module constructed, so lets be clean and fix it. Reported-by: Coverity CID=350116 Reported-by: Coverity CID=350123 Reported-by: Coverity CID=350140 Reported-by: Coverity CID=350147 Fixes: 7832e19a599e ("utils: ipc: add templates for code generation for IPC mechanism") Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-07-27utils: ipc: Assign a new gid to proxy workerUmang Jain
Isolated IPAs are forked to a new process by the proxy worker, which shares the same process group. This allows the undesired effect that the proxy worker will receive signals such as SIGINT and will be closed by a Ctrl-C event before the pipeline handlers have been able to fully clean up. Prevent this signal from being delivered to the proxy worker by moving the process to a new process group, matching the pid of the isolated proxy. Bug: https://bugs.libcamera.org/show_bug.cgi?id=60 Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
2021-07-09utils: ipc: proxy: Reset ControlSerializer during IPA configureUmang Jain
ControlSerializer should be reset during IPA (re)configuration, so that it doesn't look up stale deserialized cache built from consecutive previous runs. This is already recommended in ControlSerializer docs but the implementation seems missing. The stale cache lookup seems to the core issue with Bug #58. Bug: https://bugs.libcamera.org/show_bug.cgi?id=58 Signed-off-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-06-25libcamera/base: Move extended base functionalityKieran Bingham
Move the functionality for the following components to the new base support library: - BoundMethod - EventDispatcher - EventDispatcherPoll - Log - Message - Object - Signal - Semaphore - Thread - Timer While it would be preferable to see these split to move one component per commit, these components are all interdependent upon each other, which leaves us with one big change performing the move for all of them. Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2021-06-01utils: ipc: mojo: Error if ControlInfoMap/List doesn't prefix libcameraPaul Elder
The mojo parser is fine if there are types that are used in array/map members that it does not know about. These are usually caught by the C++ compiler, because the generated code refers to unknown types. This feature is necessary for us for supporting FrameBuffer::Plane as an array/map member, since as long as the type has an IPADataSerializer and the struct defined in C++, the generated code will run fine (FrameBuffer::Plane is not defined anywhere in mojom but is used as an array member in IPABuffer). The types that are defined in controls.h (or any header included in ipa_interface.h) will all be compiled by the C++ compiler fine, since the generated files all include controls.h. The types that are there that are not ControlInfoMap or ControlList (like ControlValue) will still fail at the linker stage. For example: struct A { array<ControlValue> a; }; will compile fine, but will fail to link, since IPADataSerializer<ControlValue> doesn't exist. This behavior, although not the best, is acceptable. The issue is that if ControlInfoMap or ControlList are used as array/map members without the libcamera prefix, the compiler will not complain, as the types are valid, and the linker will also not complain, as IPADataSerializer<ControlList> and IPADataSerializer<ControlInfoMap> both exist. However, the code generator will not recognize them as types that require a ControlSerializer (since mojo doesn't recognize them, so they are different from the ones that it does recognize with the libcamera namespace)/* 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 <libcamera/property_ids.h> #include "libcamera/internal/log.h" #include "camera_device.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() : cameraManager_(nullptr), callbacks_(nullptr), numInternalCameras_(0), nextExternalCameraId_(firstExternalCameraId_) { } CameraHalManager::~CameraHalManager() { cameras_.clear(); if (cameraManager_) { cameraManager_->stop(); delete cameraManager_; cameraManager_ = nullptr; } } int CameraHalManager::init() { cameraManager_ = new CameraManager(); /* Support camera hotplug. */ cameraManager_->cameraAdded.connect(this, &CameraHalManager::cameraAdded); cameraManager_->cameraRemoved.connect(this, &CameraHalManager::cameraRemoved); int ret = cameraManager_->start(); if (ret) { LOG(HAL, Error) << "Failed to start camera manager: " << strerror(-ret); delete cameraManager_; cameraManager_ = nullptr; return ret; } return 0; } CameraDevice *CameraHalManager::open(unsigned int id, const hw_module_t *hardwareModule) { MutexLocker locker(mutex_); if (!callbacks_) { LOG(HAL, Error) << "Can't open camera before callbacks are set"; return nullptr; } CameraDevice *camera = cameraDeviceFromHalId(id); if (!camera) { LOG(HAL, Error) << "Invalid camera id '" << id << "'"; return nullptr; } if (camera->open(hardwareModule)) return nullptr; LOG(HAL, Info) << "Open camera '" << id << "'"; return camera; } void CameraHalManager::cameraAdded(std::shared_ptr<Camera> cam) { unsigned int id; bool isCameraExternal = false; bool isCameraNew = false; MutexLocker locker(mutex_); /* * Each camera is assigned a unique integer ID when it is seen for the * first time. If the camera has been seen before, the previous ID is * re-used. * * IDs starts from '0' for internal cameras and '1000' for external * cameras. */ auto iter = cameraIdsMap_.find(cam->id()); if (iter != cameraIdsMap_.end()) { id = iter->second; } else { isCameraNew = true; /* * Now check if this is an external camera and assign * its id accordingly. */ if (cameraLocation(cam.get()) == properties::CameraLocationExternal) { isCameraExternal = true; id = nextExternalCameraId_; } else { id = numInternalCameras_; } } /* Create a CameraDevice instance to wrap the libcamera Camera. */ std::shared_ptr<CameraDevice> camera = CameraDevice::create(id, std::move(cam)); int ret = camera->initialize(); if (ret) { LOG(HAL, Error) << "Failed to initialize camera: " << cam->id(); return; } if (isCameraNew) { cameraIdsMap_.emplace(cam->id(), id); if (isCameraExternal) nextExternalCameraId_++; else numInternalCameras_++
2020-11-11README, meson: Add dependency on ply and jinja2 for IPA interface generationPaul Elder
Specify in the readme and meson file that we depend on python3-ply and python3-jinja2 for generating the IPA interface. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2020-11-11utils: ipc: import mojoPaul Elder
Import mojo from the Chromium repository, so that we can use it for generating code for the IPC mechanism. The commit from which this was taken is: a079161ec8c6907b883f9cb84fc8c4e7896cb1d0 "Add PPAPI constructs for sending focus object to PdfAccessibilityTree" This tree has been pruned to remove directories that didn't have any necessary code: - mojo/* except for mojo/public - mojo core, docs, and misc files - mojo/public/* except for mojo/public/{tools,LICENSE} - language bindings for IPC, tests, and some mojo internals - mojo/public/tools/{fuzzers,chrome_ipc} - mojo/public/tools/bindings/generators - code generation for other languages No files were modified. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
="hl opt">(); }); if (iter == cameras_.end()) return; /* * CAMERA_DEVICE_STATUS_NOT_PRESENT should be set for external cameras * only. */ unsigned int id = (*iter)->id(); if (id >= firstExternalCameraId_) callbacks_->camera_device_status_change(callbacks_, id, CAMERA_DEVICE_STATUS_NOT_PRESENT); /* * \todo Check if the camera is already open and running. * Inform the framework about its absence before deleting its * reference here. */ cameras_.erase(iter); LOG(HAL, Debug) << "Camera ID: " << id << " removed successfully."; } int32_t CameraHalManager::cameraLocation(const Camera *cam) { const ControlList &properties = cam->properties(); if (!properties.contains(properties::Location)) return -1; return properties.get(properties::Location); } CameraDevice *CameraHalManager::cameraDeviceFromHalId(unsigned int id) { auto iter = std::find_if(cameras_.begin(), cameras_.end(), [id](std::shared_ptr<CameraDevice> &camera) { return camera->id() == id; }); if (iter == cameras_.end()) return nullptr; return iter->get(); } unsigned int CameraHalManager::numCameras() const { return numInternalCameras_; } int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) { if (!info) return -EINVAL; MutexLocker locker(mutex_); CameraDevice *camera = cameraDeviceFromHalId(id); if (!camera) { LOG(HAL, Error) << "Invalid camera id '" << id << "'"; return -EINVAL; } info->facing = camera->facing(); info->orientation = camera->orientation(); info->device_version = CAMERA_DEVICE_API_VERSION_3_3; info->resource_cost = 0; info->static_camera_characteristics = camera->getStaticMetadata(); info->conflicting_devices = nullptr; info->conflicting_devices_length = 0; return 0; } void CameraHalManager::setCallbacks(const camera_module_callbacks_t *callbacks) { callbacks_ = callbacks; MutexLocker locker(mutex_); /* * Some external cameras may have been identified before the callbacks_ * were set. Iterate all existing external cameras and mark them as * CAMERA_DEVICE_STATUS_PRESENT explicitly. * * Internal cameras are already assumed to be present at module load * time by the Android framework. */ for (std::shared_ptr<CameraDevice> &camera : cameras_) { unsigned int id = camera->id(); if (id >= firstExternalCameraId_) callbacks_->camera_device_status_change(callbacks_, id, CAMERA_DEVICE_STATUS_PRESENT); } }