From 5aad8936be1fbae6b0d7d0d66d83d9472b5708b2 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Thu, 21 Sep 2017 22:00:40 +0200 Subject: lineage/interfaces: Fork camera/{provider/2.4,device/1.0} from hardware/interfaces Identical to a8dcad048c1adb1870fca945bf85197470d5ed29 Change-Id: I4c82cba7ac8cbf8ea001a5421a81daf9886e2991 --- camera/Android.bp | 4 + camera/device/1.0/Android.bp | 34 ++ camera/device/1.0/CameraDevice.cpp | 1006 ++++++++++++++++++++++++++++++++ camera/device/1.0/CameraDevice_1_0.h | 235 ++++++++ camera/provider/2.4/Android.bp | 27 + camera/provider/2.4/CameraProvider.cpp | 507 ++++++++++++++++ camera/provider/2.4/CameraProvider.h | 124 ++++ 7 files changed, 1937 insertions(+) create mode 100644 camera/Android.bp create mode 100644 camera/device/1.0/Android.bp create mode 100644 camera/device/1.0/CameraDevice.cpp create mode 100644 camera/device/1.0/CameraDevice_1_0.h create mode 100644 camera/provider/2.4/Android.bp create mode 100644 camera/provider/2.4/CameraProvider.cpp create mode 100644 camera/provider/2.4/CameraProvider.h (limited to 'camera') diff --git a/camera/Android.bp b/camera/Android.bp new file mode 100644 index 0000000..de47f5f --- /dev/null +++ b/camera/Android.bp @@ -0,0 +1,4 @@ +subdirs = [ + "device/1.0", + "provider/2.4", +] diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp new file mode 100644 index 0000000..fa246c1 --- /dev/null +++ b/camera/device/1.0/Android.bp @@ -0,0 +1,34 @@ +cc_library_shared { + name: "camera.device@1.0-impl", + defaults: ["hidl_defaults"], + proprietary: true, + srcs: [ + "CameraDevice.cpp", + ], + shared_libs: [ + "libhidlbase", + "libhidlmemory", + "libhidltransport", + "libhwbinder", + "libutils", + "android.hardware.camera.device@1.0", + "android.hardware.camera.common@1.0", + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.common@1.0", + "android.hidl.allocator@1.0", + "android.hidl.base@1.0", + "android.hidl.memory@1.0", + "libcutils", + "liblog", + "libhardware", + "libcamera_metadata", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper" + ], + include_dirs: [ + "frameworks/native/include/media/openmax" + ], + export_include_dirs: ["."] +} diff --git a/camera/device/1.0/CameraDevice.cpp b/camera/device/1.0/CameraDevice.cpp new file mode 100644 index 0000000..c53c0d8 --- /dev/null +++ b/camera/device/1.0/CameraDevice.cpp @@ -0,0 +1,1006 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamDev@1.0-impl" +#include +#include +#include +#include +#include + +#include // For VideoNativeHandleMetadata +#include "CameraDevice_1_0.h" + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::graphics::common::V1_0::BufferUsage; +using ::android::hardware::graphics::common::V1_0::PixelFormat; + +HandleImporter CameraDevice::sHandleImporter; + +Status CameraDevice::getHidlStatus(const int& status) { + switch (status) { + case 0: return Status::OK; + case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED; + case -EBUSY : return Status::CAMERA_IN_USE; + case -EUSERS: return Status::MAX_CAMERAS_IN_USE; + case -ENODEV: return Status::INTERNAL_ERROR; + case -EINVAL: return Status::ILLEGAL_ARGUMENT; + default: + ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status); + return Status::INTERNAL_ERROR; + } +} + +status_t CameraDevice::getStatusT(const Status& s) { + switch(s) { + case Status::OK: + return OK; + case Status::ILLEGAL_ARGUMENT: + return BAD_VALUE; + case Status::CAMERA_IN_USE: + return -EBUSY; + case Status::MAX_CAMERAS_IN_USE: + return -EUSERS; + case Status::METHOD_NOT_SUPPORTED: + return UNKNOWN_TRANSACTION; + case Status::OPERATION_NOT_SUPPORTED: + return INVALID_OPERATION; + case Status::CAMERA_DISCONNECTED: + return DEAD_OBJECT; + case Status::INTERNAL_ERROR: + return INVALID_OPERATION; + } + ALOGW("Unexpected HAL status code %d", s); + return INVALID_OPERATION; +} + +Status CameraDevice::initStatus() const { + Mutex::Autolock _l(mLock); + Status status = Status::OK; + if (mInitFail) { + status = Status::INTERNAL_ERROR; + } else if (mDisconnected) { + status = Status::CAMERA_DISCONNECTED; + } + return status; +} + +CameraDevice::CameraDevice( + sp module, const std::string& cameraId, + const SortedVector>& cameraDeviceNames) : + mModule(module), + mCameraId(cameraId), + mDisconnected(false), + mCameraDeviceNames(cameraDeviceNames) { + mCameraIdInt = atoi(mCameraId.c_str()); + // Should not reach here as provider also validate ID + if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) { + ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str()); + mInitFail = true; + } + + mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt); + if (mDeviceVersion != CAMERA_DEVICE_API_VERSION_1_0 && !mModule->isOpenLegacyDefined()) { + ALOGI("%s: Camera id %s does not support HAL1.0", + __FUNCTION__, mCameraId.c_str()); + mInitFail = true; + } + + mAshmemAllocator = IAllocator::getService("ashmem"); + if (mAshmemAllocator == nullptr) { + ALOGI("%s: cannot get ashmemAllocator", __FUNCTION__); + mInitFail = true; + } +} + +CameraDevice::~CameraDevice() { + Mutex::Autolock _l(mLock); + if (mDevice != nullptr) { + ALOGW("%s: camera %s is deleted while open", __FUNCTION__, mCameraId.c_str()); + closeLocked(); + } + mHalPreviewWindow.cleanUpCirculatingBuffers(); +} + + +void CameraDevice::setConnectionStatus(bool connected) { + Mutex::Autolock _l(mLock); + mDisconnected = !connected; + if (mDevice == nullptr) { + return; + } + if (!connected) { + ALOGW("%s: camera %s is disconneted. Closing", __FUNCTION__, mCameraId.c_str()); + closeLocked(); + } + return; +} + +void CameraDevice::CameraPreviewWindow::cleanUpCirculatingBuffers() { + Mutex::Autolock _l(mLock); + for (auto pair : mCirculatingBuffers) { + sHandleImporter.freeBuffer(pair.second); + } + mCirculatingBuffers.clear(); + mBufferIdMap.clear(); +} + +int CameraDevice::sDequeueBuffer(struct preview_stream_ops* w, + buffer_handle_t** buffer, int *stride) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + if (buffer == nullptr || stride == nullptr) { + ALOGE("%s: buffer (%p) and stride (%p) must not be null!", __FUNCTION__, buffer, stride); + return BAD_VALUE; + } + + Status s; + object->mPreviewCallback->dequeueBuffer( + [&](auto status, uint64_t bufferId, const auto& buf, uint32_t strd) { + s = status; + if (s == Status::OK) { + Mutex::Autolock _l(object->mLock); + if (object->mCirculatingBuffers.count(bufferId) == 0) { + buffer_handle_t importedBuf = buf.getNativeHandle(); + sHandleImporter.importBuffer(importedBuf); + if (importedBuf == nullptr) { + ALOGE("%s: preview buffer import failed!", __FUNCTION__); + s = Status::INTERNAL_ERROR; + return; + } else { + object->mCirculatingBuffers[bufferId] = importedBuf; + object->mBufferIdMap[&(object->mCirculatingBuffers[bufferId])] = bufferId; + } + } + *buffer = &(object->mCirculatingBuffers[bufferId]); + *stride = strd; + } + }); + return getStatusT(s); +} + +int CameraDevice::sLockBuffer(struct preview_stream_ops*, buffer_handle_t*) { + return 0; +} + +int CameraDevice::sEnqueueBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + uint64_t bufferId = object->mBufferIdMap.at(buffer); + return getStatusT(object->mPreviewCallback->enqueueBuffer(bufferId)); +} + +int CameraDevice::sCancelBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + uint64_t bufferId = object->mBufferIdMap.at(buffer); + return getStatusT(object->mPreviewCallback->cancelBuffer(bufferId)); +} + +int CameraDevice::sSetBufferCount(struct preview_stream_ops* w, int count) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + object->cleanUpCirculatingBuffers(); + return getStatusT(object->mPreviewCallback->setBufferCount(count)); +} + +int CameraDevice::sSetBuffersGeometry(struct preview_stream_ops* w, + int width, int height, int format) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + object->cleanUpCirculatingBuffers(); + return getStatusT( + object->mPreviewCallback->setBuffersGeometry(width, height, (PixelFormat) format)); +} + +int CameraDevice::sSetCrop(struct preview_stream_ops *w, + int left, int top, int right, int bottom) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + return getStatusT(object->mPreviewCallback->setCrop(left, top, right, bottom)); +} + +int CameraDevice::sSetTimestamp(struct preview_stream_ops *w, int64_t timestamp) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + return getStatusT(object->mPreviewCallback->setTimestamp(timestamp)); +} + +int CameraDevice::sSetUsage(struct preview_stream_ops* w, int usage) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + object->cleanUpCirculatingBuffers(); + return getStatusT(object->mPreviewCallback->setUsage((BufferUsage)usage)); +} + +int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) { + CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + + return getStatusT(object->mPreviewCallback->setSwapInterval(interval)); +} + +int CameraDevice::sGetMinUndequeuedBufferCount( + const struct preview_stream_ops *w, + int *count) { + const CameraPreviewWindow* object = static_cast(w); + if (object->mPreviewCallback == nullptr) { + ALOGE("%s: camera HAL calling preview ops while there is no preview window!", __FUNCTION__); + return INVALID_OPERATION; + } + if (count == nullptr) { + ALOGE("%s: count is null!", __FUNCTION__); + return BAD_VALUE; + } + + Status s; + object->mPreviewCallback->getMinUndequeuedBufferCount( + [&](auto status, uint32_t cnt) { + s = status; + if (s == Status::OK) { + *count = cnt; + } + }); + return getStatusT(s); +} + +CameraDevice::CameraHeapMemory::CameraHeapMemory( + int fd, size_t buf_size, uint_t num_buffers) : + mBufSize(buf_size), + mNumBufs(num_buffers) { + mHidlHandle = native_handle_create(1,0); + mHidlHandle->data[0] = fcntl(fd, F_DUPFD_CLOEXEC, 0); + const size_t pagesize = getpagesize(); + size_t size = ((buf_size * num_buffers + pagesize-1) & ~(pagesize-1)); + mHidlHeap = hidl_memory("ashmem", mHidlHandle, size); + commonInitialization(); +} + +CameraDevice::CameraHeapMemory::CameraHeapMemory( + sp ashmemAllocator, + size_t buf_size, uint_t num_buffers) : + mBufSize(buf_size), + mNumBufs(num_buffers) { + const size_t pagesize = getpagesize(); + size_t size = ((buf_size * num_buffers + pagesize-1) & ~(pagesize-1)); + ashmemAllocator->allocate(size, + [&](bool success, const hidl_memory& mem) { + if (!success) { + ALOGE("%s: allocating ashmem of %zu bytes failed!", + __FUNCTION__, buf_size * num_buffers); + return; + } + mHidlHandle = native_handle_clone(mem.handle()); + mHidlHeap = hidl_memory("ashmem", mHidlHandle, size); + }); + + commonInitialization(); +} + +void CameraDevice::CameraHeapMemory::commonInitialization() { + mHidlHeapMemory = mapMemory(mHidlHeap); + if (mHidlHeapMemory == nullptr) { + ALOGE("%s: memory map failed!", __FUNCTION__); + native_handle_close(mHidlHandle); // close FD for the shared memory + native_handle_delete(mHidlHandle); + mHidlHeap = hidl_memory(); + mHidlHandle = nullptr; + return; + } + mHidlHeapMemData = mHidlHeapMemory->getPointer(); + handle.data = mHidlHeapMemData; + handle.size = mBufSize * mNumBufs; + handle.handle = this; + handle.release = sPutMemory; +} + +CameraDevice::CameraHeapMemory::~CameraHeapMemory() { + if (mHidlHeapMemory != nullptr) { + mHidlHeapMemData = nullptr; + mHidlHeapMemory.clear(); // The destructor will trigger munmap + } + + if (mHidlHandle) { + native_handle_close(mHidlHandle); // close FD for the shared memory + native_handle_delete(mHidlHandle); + } +} + +// shared memory methods +camera_memory_t* CameraDevice::sGetMemory(int fd, size_t buf_size, uint_t num_bufs, void *user) { + ALOGV("%s", __FUNCTION__); + CameraDevice* object = static_cast(user); + if (object->mDeviceCallback == nullptr) { + ALOGE("%s: camera HAL request memory while camera is not opened!", __FUNCTION__); + return nullptr; + } + + CameraHeapMemory* mem; + if (fd < 0) { + mem = new CameraHeapMemory(object->mAshmemAllocator, buf_size, num_bufs); + } else { + mem = new CameraHeapMemory(fd, buf_size, num_bufs); + } + mem->incStrong(mem); + hidl_handle hidlHandle = mem->mHidlHandle; + MemoryId id = object->mDeviceCallback->registerMemory(hidlHandle, buf_size, num_bufs); + mem->handle.mId = id; + if (object->mMemoryMap.count(id) != 0) { + ALOGE("%s: duplicate MemoryId %d returned by client!", __FUNCTION__, id); + } + object->mMemoryMap[id] = mem; + mem->handle.mDevice = object; + return &mem->handle; +} + +void CameraDevice::sPutMemory(camera_memory_t *data) { + if (!data) + return; + + CameraHeapMemory* mem = static_cast(data->handle); + CameraDevice* device = mem->handle.mDevice; + if (device == nullptr) { + ALOGE("%s: camera HAL return memory for a null device!", __FUNCTION__); + } + if (device->mDeviceCallback == nullptr) { + ALOGE("%s: camera HAL return memory while camera is not opened!", __FUNCTION__); + } + device->mDeviceCallback->unregisterMemory(mem->handle.mId); + device->mMemoryMap.erase(mem->handle.mId); + mem->decStrong(mem); +} + +// Callback forwarding methods +void CameraDevice::sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user) { + ALOGV("%s", __FUNCTION__); + CameraDevice* object = static_cast(user); + if (object->mDeviceCallback != nullptr) { + object->mDeviceCallback->notifyCallback((NotifyCallbackMsg) msg_type, ext1, ext2); + } +} + +void CameraDevice::sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index, + camera_frame_metadata_t *metadata, void *user) { + ALOGV("%s", __FUNCTION__); + CameraDevice* object = static_cast(user); + sp mem(static_cast(data->handle)); + if (index >= mem->mNumBufs) { + ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__, + index, mem->mNumBufs); + return; + } + if (object->mDeviceCallback != nullptr) { + CameraFrameMetadata hidlMetadata; + if (metadata) { + hidlMetadata.faces.resize(metadata->number_of_faces); + for (size_t i = 0; i < hidlMetadata.faces.size(); i++) { + hidlMetadata.faces[i].score = metadata->faces[i].score; + hidlMetadata.faces[i].id = metadata->faces[i].id; + for (int k = 0; k < 4; k++) { + hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k]; + } + for (int k = 0; k < 2; k++) { + hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k]; + } + for (int k = 0; k < 2; k++) { + hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k]; + } + for (int k = 0; k < 2; k++) { + hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k]; + } + } + } + CameraHeapMemory* mem = static_cast(data->handle); + object->mDeviceCallback->dataCallback( + (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata); + } +} + +void CameraDevice::handleCallbackTimestamp( + nsecs_t timestamp, int32_t msg_type, + MemoryId memId , unsigned index, native_handle_t* handle) { + uint32_t batchSize = 0; + { + Mutex::Autolock _l(mBatchLock); + batchSize = mBatchSize; + } + + if (batchSize == 0) { // non-batch mode + mDeviceCallback->handleCallbackTimestamp( + (DataCallbackMsg) msg_type, handle, memId, index, timestamp); + } else { // batch mode + Mutex::Autolock _l(mBatchLock); + size_t inflightSize = mInflightBatch.size(); + if (inflightSize == 0) { + mBatchMsgType = msg_type; + } else if (mBatchMsgType != msg_type) { + ALOGE("%s: msg_type change (from %d to %d) is not supported!", + __FUNCTION__, mBatchMsgType, msg_type); + return; + } + mInflightBatch.push_back({handle, memId, index, timestamp}); + + // Send batched frames to camera framework + if (mInflightBatch.size() >= batchSize) { + mDeviceCallback->handleCallbackTimestampBatch( + (DataCallbackMsg) mBatchMsgType, mInflightBatch); + mInflightBatch.clear(); + } + } +} + +void CameraDevice::sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type, + const camera_memory_t *data, unsigned index, void *user) { + ALOGV("%s", __FUNCTION__); + CameraDevice* object = static_cast(user); + // Start refcounting the heap object from here on. When the clients + // drop all references, it will be destroyed (as well as the enclosed + // MemoryHeapBase. + sp mem(static_cast(data->handle)); + if (index >= mem->mNumBufs) { + ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__, + index, mem->mNumBufs); + return; + } + + native_handle_t* handle = nullptr; + if (object->mMetadataMode) { + if (mem->mBufSize == sizeof(VideoNativeHandleMetadata)) { + VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) + ((uint8_t*) mem->mHidlHeapMemData + index * mem->mBufSize); + if (md->eType == kMetadataBufferTypeNativeHandleSource) { + handle = md->pHandle; + } + } + } + + if (object->mDeviceCallback != nullptr) { + if (handle == nullptr) { + object->mDeviceCallback->dataCallbackTimestamp( + (DataCallbackMsg) msg_type, mem->handle.mId, index, timestamp); + } else { + object->handleCallbackTimestamp(timestamp, msg_type, mem->handle.mId, index, handle); + } + } +} + +void CameraDevice::initHalPreviewWindow() +{ + mHalPreviewWindow.cancel_buffer = sCancelBuffer; + mHalPreviewWindow.lock_buffer = sLockBuffer; + mHalPreviewWindow.dequeue_buffer = sDequeueBuffer; + mHalPreviewWindow.enqueue_buffer = sEnqueueBuffer; + mHalPreviewWindow.set_buffer_count = sSetBufferCount; + mHalPreviewWindow.set_buffers_geometry = sSetBuffersGeometry; + mHalPreviewWindow.set_crop = sSetCrop; + mHalPreviewWindow.set_timestamp = sSetTimestamp; + mHalPreviewWindow.set_usage = sSetUsage; + mHalPreviewWindow.set_swap_interval = sSetSwapInterval; + + mHalPreviewWindow.get_min_undequeued_buffer_count = + sGetMinUndequeuedBufferCount; +} + +// Methods from ::android::hardware::camera::device::V1_0::ICameraDevice follow. +Return CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { + Status status = initStatus(); + CameraResourceCost resCost; + if (status == Status::OK) { + int cost = 100; + std::vector conflicting_devices; + struct camera_info info; + + // If using post-2.4 module version, query the cost + conflicting devices from the HAL + if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) { + int ret = mModule->getCameraInfo(mCameraIdInt, &info); + if (ret == OK) { + cost = info.resource_cost; + for (size_t i = 0; i < info.conflicting_devices_length; i++) { + std::string cameraId(info.conflicting_devices[i]); + for (const auto& pair : mCameraDeviceNames) { + if (cameraId == pair.first) { + conflicting_devices.push_back(pair.second); + } + } + } + } else { + status = Status::INTERNAL_ERROR; + } + } + + if (status == Status::OK) { + resCost.resourceCost = cost; + resCost.conflictingDevices.resize(conflicting_devices.size()); + for (size_t i = 0; i < conflicting_devices.size(); i++) { + resCost.conflictingDevices[i] = conflicting_devices[i]; + ALOGV("CamDevice %s is conflicting with camDevice %s", + mCameraId.c_str(), resCost.conflictingDevices[i].c_str()); + } + } + } + _hidl_cb(status, resCost); + return Void(); +} + +Return CameraDevice::getCameraInfo(getCameraInfo_cb _hidl_cb) { + Status status = initStatus(); + CameraInfo cameraInfo; + if (status == Status::OK) { + struct camera_info info; + int ret = mModule->getCameraInfo(mCameraIdInt, &info); + if (ret == OK) { + cameraInfo.facing = (CameraFacing) info.facing; + // Device 1.0 does not support external camera facing. + // The closest approximation would be front camera. + if (cameraInfo.facing == CameraFacing::EXTERNAL) { + cameraInfo.facing = CameraFacing::FRONT; + } + cameraInfo.orientation = info.orientation; + } else { + ALOGE("%s: get camera info failed!", __FUNCTION__); + status = Status::INTERNAL_ERROR; + } + } + _hidl_cb(status, cameraInfo); + return Void(); +} + +Return CameraDevice::setTorchMode(TorchMode mode) { + if (!mModule->isSetTorchModeSupported()) { + return Status::METHOD_NOT_SUPPORTED; + } + + Status status = initStatus(); + if (status == Status::OK) { + bool enable = (mode == TorchMode::ON) ? true : false; + status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable)); + } + return status; +} + +Return CameraDevice::dumpState(const hidl_handle& handle) { + Mutex::Autolock _l(mLock); + if (handle.getNativeHandle() == nullptr) { + ALOGE("%s: handle must not be null", __FUNCTION__); + return Status::ILLEGAL_ARGUMENT; + } + if (handle->numFds != 1 || handle->numInts != 0) { + ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints", + __FUNCTION__, handle->numFds, handle->numInts); + return Status::ILLEGAL_ARGUMENT; + } + int fd = handle->data[0]; + + if (mDevice != nullptr) { + if (mDevice->ops->dump) { // It's fine if the HAL doesn't implement dump() + return getHidlStatus(mDevice->ops->dump(mDevice, fd)); + } + } + return Status::OK; +} + +Return CameraDevice::open(const sp& callback) { + ALOGI("Opening camera %s", mCameraId.c_str()); + Mutex::Autolock _l(mLock); + + camera_info info; + status_t res = mModule->getCameraInfo(mCameraIdInt, &info); + if (res != OK) { + ALOGE("Could not get camera info: %s: %d", mCameraId.c_str(), res); + return getHidlStatus(res); + } + + int rc = OK; + if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 && + info.device_version > CAMERA_DEVICE_API_VERSION_1_0) { + // Open higher version camera device as HAL1.0 device. + rc = mModule->openLegacy(mCameraId.c_str(), + CAMERA_DEVICE_API_VERSION_1_0, + (hw_device_t **)&mDevice); + } else { + rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice); + } + if (rc != OK) { + mDevice = nullptr; + ALOGE("Could not open camera %s: %d", mCameraId.c_str(), rc); + return getHidlStatus(rc); + } + + initHalPreviewWindow(); + mDeviceCallback = callback; + + if (mDevice->ops->set_callbacks) { + mDevice->ops->set_callbacks(mDevice, + sNotifyCb, sDataCb, sDataCbTimestamp, sGetMemory, this); + } + + return getHidlStatus(rc); +} + +Return CameraDevice::setPreviewWindow(const sp& window) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + + mHalPreviewWindow.mPreviewCallback = window; + if (mDevice->ops->set_preview_window) { + return getHidlStatus(mDevice->ops->set_preview_window(mDevice, + (window == nullptr) ? nullptr : &mHalPreviewWindow)); + } + return Status::INTERNAL_ERROR; // HAL should provide set_preview_window +} + +Return CameraDevice::enableMsgType(uint32_t msgType) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Void(); + } + if (mDevice->ops->enable_msg_type) { + mDevice->ops->enable_msg_type(mDevice, msgType); + } + return Void(); +} + +Return CameraDevice::disableMsgType(uint32_t msgType) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Void(); + } + if (mDevice->ops->disable_msg_type) { + mDevice->ops->disable_msg_type(mDevice, msgType); + } + return Void(); +} + +Return CameraDevice::msgTypeEnabled(uint32_t msgType) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return false; + } + if (mDevice->ops->msg_type_enabled) { + return mDevice->ops->msg_type_enabled(mDevice, msgType); + } + return false; +} + +Return CameraDevice::startPreview() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->start_preview) { + return getHidlStatus(mDevice->ops->start_preview(mDevice)); + } + return Status::INTERNAL_ERROR; // HAL should provide start_preview +} + +Return CameraDevice::stopPreview() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Void(); + } + if (mDevice->ops->stop_preview) { + mDevice->ops->stop_preview(mDevice); + } + return Void(); +} + +Return CameraDevice::previewEnabled() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return false; + } + if (mDevice->ops->preview_enabled) { + return mDevice->ops->preview_enabled(mDevice); + } + return false; +} + +Return CameraDevice::storeMetaDataInBuffers(bool enable) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->store_meta_data_in_buffers) { + status_t s = mDevice->ops->store_meta_data_in_buffers(mDevice, enable); + if (s == OK && enable) { + mMetadataMode = true; + } + return getHidlStatus(s); + } + return enable ? Status::ILLEGAL_ARGUMENT : Status::OK; +} + +Return CameraDevice::startRecording() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->start_recording) { + return getHidlStatus(mDevice->ops->start_recording(mDevice)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::stopRecording() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Void(); + } + if (mDevice->ops->stop_recording) { + mDevice->ops->stop_recording(mDevice); + } + return Void(); +} + +Return CameraDevice::recordingEnabled() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return false; + } + if (mDevice->ops->recording_enabled) { + return mDevice->ops->recording_enabled(mDevice); + } + return false; +} + +void CameraDevice::releaseRecordingFrameLocked( + uint32_t memId, uint32_t bufferIndex, const native_handle_t* handle) { + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return; + } + if (mDevice->ops->release_recording_frame) { + CameraHeapMemory* camMemory = mMemoryMap.at(memId); + if (bufferIndex >= camMemory->mNumBufs) { + ALOGE("%s: bufferIndex %d exceeds number of buffers %d", + __FUNCTION__, bufferIndex, camMemory->mNumBufs); + return; + } + void *data = ((uint8_t *) camMemory->mHidlHeapMemData) + bufferIndex * camMemory->mBufSize; + if (handle) { + VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) data; + if (md->eType == kMetadataBufferTypeNativeHandleSource) { + // Input handle will be closed by HIDL transport later, so clone it + // HAL implementation is responsible to close/delete the clone + native_handle_t* clone = native_handle_clone(handle); + if (!clone) { + ALOGE("%s: failed to clone buffer %p", __FUNCTION__, handle); + return; + } + md->pHandle = clone; + } else { + ALOGE("%s:Malform VideoNativeHandleMetadata at memId %d, bufferId %d", + __FUNCTION__, memId, bufferIndex); + return; + } + } + mDevice->ops->release_recording_frame(mDevice, data); + } +} + +Return CameraDevice::releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + releaseRecordingFrameLocked(memId, bufferIndex, nullptr); + return Void(); +} + +Return CameraDevice::releaseRecordingFrameHandle( + uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + releaseRecordingFrameLocked( + memId, bufferIndex, frame.getNativeHandle()); + return Void(); +} + +Return CameraDevice::releaseRecordingFrameHandleBatch( + const hidl_vec& msgs) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + for (auto& msg : msgs) { + releaseRecordingFrameLocked( + msg.data, msg.bufferIndex, msg.frameData.getNativeHandle()); + } + return Void(); +} + +Return CameraDevice::autoFocus() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->auto_focus) { + return getHidlStatus(mDevice->ops->auto_focus(mDevice)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::cancelAutoFocus() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->cancel_auto_focus) { + return getHidlStatus(mDevice->ops->cancel_auto_focus(mDevice)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::takePicture() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->take_picture) { + return getHidlStatus(mDevice->ops->take_picture(mDevice)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::cancelPicture() { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->cancel_picture) { + return getHidlStatus(mDevice->ops->cancel_picture(mDevice)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::setParameters(const hidl_string& params) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->set_parameters) { + return getHidlStatus(mDevice->ops->set_parameters(mDevice, params.c_str())); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::getParameters(getParameters_cb _hidl_cb) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + hidl_string outStr; + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + _hidl_cb(outStr); + return Void(); + } + if (mDevice->ops->get_parameters) { + char *temp = mDevice->ops->get_parameters(mDevice); + outStr = temp; + if (mDevice->ops->put_parameters) { + mDevice->ops->put_parameters(mDevice, temp); + } else { + free(temp); + } + } + _hidl_cb(outStr); + return Void(); +} + +Return CameraDevice::sendCommand(CommandType cmd, int32_t arg1, int32_t arg2) { + ALOGV("%s(%s)", __FUNCTION__, mCameraId.c_str()); + Mutex::Autolock _l(mLock); + if (!mDevice) { + ALOGE("%s called while camera is not opened", __FUNCTION__); + return Status::OPERATION_NOT_SUPPORTED; + } + if (mDevice->ops->send_command) { + return getHidlStatus(mDevice->ops->send_command(mDevice, (int32_t) cmd, arg1, arg2)); + } + return Status::ILLEGAL_ARGUMENT; +} + +Return CameraDevice::close() { + Mutex::Autolock _l(mLock); + closeLocked(); + return Void(); +} + +void CameraDevice::closeLocked() { + ALOGI("Closing camera %s", mCameraId.c_str()); + if(mDevice) { + int rc = mDevice->common.close(&mDevice->common); + if (rc != OK) { + ALOGE("Could not close camera %s: %d", mCameraId.c_str(), rc); + } + mDevice = nullptr; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/device/1.0/CameraDevice_1_0.h b/camera/device/1.0/CameraDevice_1_0.h new file mode 100644 index 0000000..c078596 --- /dev/null +++ b/camera/device/1.0/CameraDevice_1_0.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H +#define ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H + +#include +#include "utils/Mutex.h" +#include "utils/SortedVector.h" +#include "CameraModule.h" +#include "HandleImporter.h" + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::camera::common::V1_0::CameraResourceCost; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::TorchMode; +using ::android::hardware::camera::common::V1_0::helper::CameraModule; +using ::android::hardware::camera::common::V1_0::helper::HandleImporter; +using ::android::hardware::camera::device::V1_0::CameraInfo; +using ::android::hardware::camera::device::V1_0::CommandType; +using ::android::hardware::camera::device::V1_0::ICameraDevice; +using ::android::hardware::camera::device::V1_0::ICameraDeviceCallback; +using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback; +using ::android::hardware::camera::device::V1_0::MemoryId; +using ::android::hidl::allocator::V1_0::IAllocator; +using ::android::hidl::base::V1_0::IBase; +using ::android::hidl::memory::V1_0::IMemory; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +struct CameraDevice : public ICameraDevice { + + // Called by provider HAL. Provider HAL must ensure the uniqueness of + // CameraDevice object per cameraId, or there could be multiple CameraDevice + // trying to access the same physical camera. + // Also, provider will have to keep track of all CameraDevice objects in + // order to notify CameraDevice when the underlying camera is detached + CameraDevice(sp module, + const std::string& cameraId, + const SortedVector>& cameraDeviceNames); + ~CameraDevice(); + + // Caller must use this method to check if CameraDevice ctor failed + bool isInitFailed() { return mInitFail; } + // Used by provider HAL to signal external camera disconnected + void setConnectionStatus(bool connected); + + // Methods from ::android::hardware::camera::device::V1_0::ICameraDevice follow. + Return getResourceCost(getResourceCost_cb _hidl_cb) override; + Return getCameraInfo(getCameraInfo_cb _hidl_cb) override; + Return setTorchMode(TorchMode mode) override; + Return dumpState(const hidl_handle& fd) override; + Return open(const sp& callback) override; + Return setPreviewWindow(const sp& window) override; + Return enableMsgType(uint32_t msgType) override; + Return disableMsgType(uint32_t msgType) override; + Return msgTypeEnabled(uint32_t msgType) override; + Return startPreview() override; + Return stopPreview() override; + Return previewEnabled() override; + Return storeMetaDataInBuffers(bool enable) override; + Return startRecording() override; + Return stopRecording() override; + Return recordingEnabled() override; + Return releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override; + Return releaseRecordingFrameHandle( + uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override; + Return releaseRecordingFrameHandleBatch( + const hidl_vec&) override; + Return autoFocus() override; + Return cancelAutoFocus() override; + Return takePicture() override; + Return cancelPicture() override; + Return setParameters(const hidl_string& params) override; + Return getParameters(getParameters_cb _hidl_cb) override; + Return sendCommand(CommandType cmd, int32_t arg1, int32_t arg2) override; + Return close() override; + +private: + struct CameraMemory : public camera_memory_t { + MemoryId mId; + CameraDevice* mDevice; + }; + + class CameraHeapMemory : public RefBase { + public: + CameraHeapMemory(int fd, size_t buf_size, uint_t num_buffers = 1); + explicit CameraHeapMemory( + sp ashmemAllocator, size_t buf_size, uint_t num_buffers = 1); + void commonInitialization(); + virtual ~CameraHeapMemory(); + + size_t mBufSize; + uint_t mNumBufs; + + // Shared memory related members + hidl_memory mHidlHeap; + native_handle_t* mHidlHandle; // contains one shared memory FD + void* mHidlHeapMemData; + sp mHidlHeapMemory; // munmap happens in ~IMemory() + + CameraMemory handle; + }; + sp mAshmemAllocator; + + const sp mModule; + const std::string mCameraId; + // const after ctor + int mCameraIdInt; + int mDeviceVersion; + + camera_device_t* mDevice = nullptr; + + void initHalPreviewWindow(); + struct CameraPreviewWindow : public preview_stream_ops { + // Called when we expect buffer will be re-allocated + void cleanUpCirculatingBuffers(); + + Mutex mLock; + sp mPreviewCallback = nullptr; + std::unordered_map mCirculatingBuffers; + std::unordered_map mBufferIdMap; + } mHalPreviewWindow; + + // gating access to mDevice, mInitFail, mDisconnected + mutable Mutex mLock; + + bool mInitFail = false; + // Set by provider (when external camera is connected/disconnected) + bool mDisconnected; + + static HandleImporter sHandleImporter; + + const SortedVector>& mCameraDeviceNames; + + sp mDeviceCallback = nullptr; + + std::unordered_map mMemoryMap; + + bool mMetadataMode = false; + + mutable Mutex mBatchLock; + // Start of protection scope for mBatchLock + uint32_t mBatchSize = 0; // 0 for non-batch mode, set to other value to start batching + int32_t mBatchMsgType; // Maybe only allow DataCallbackMsg::VIDEO_FRAME? + std::vector mInflightBatch; + // End of protection scope for mBatchLock + + void handleCallbackTimestamp( + nsecs_t timestamp, int32_t msg_type, + MemoryId memId , unsigned index, native_handle_t* handle); + void releaseRecordingFrameLocked(uint32_t memId, uint32_t bufferIndex, const native_handle_t*); + + // shared memory methods + static camera_memory_t* sGetMemory(int fd, size_t buf_size, uint_t num_bufs, void *user); + static void sPutMemory(camera_memory_t *data); + + // Device callback forwarding methods + static void sNotifyCb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user); + static void sDataCb(int32_t msg_type, const camera_memory_t *data, unsigned int index, + camera_frame_metadata_t *metadata, void *user); + static void sDataCbTimestamp(nsecs_t timestamp, int32_t msg_type, + const camera_memory_t *data, unsigned index, void *user); + + // Preview window callback forwarding methods + static int sDequeueBuffer(struct preview_stream_ops* w, + buffer_handle_t** buffer, int *stride); + + static int sLockBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer); + + static int sEnqueueBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer); + + static int sCancelBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer); + + static int sSetBufferCount(struct preview_stream_ops* w, int count); + + static int sSetBuffersGeometry(struct preview_stream_ops* w, + int width, int height, int format); + + static int sSetCrop(struct preview_stream_ops *w, int left, int top, int right, int bottom); + + static int sSetTimestamp(struct preview_stream_ops *w, int64_t timestamp); + + static int sSetUsage(struct preview_stream_ops* w, int usage); + + static int sSetSwapInterval(struct preview_stream_ops *w, int interval); + + static int sGetMinUndequeuedBufferCount(const struct preview_stream_ops *w, int *count); + + // convert conventional HAL status to HIDL Status + static Status getHidlStatus(const int&); + static status_t getStatusT(const Status& s); + + Status initStatus() const; + void closeLocked(); +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V1_0_CAMERADEVICE_H diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp new file mode 100644 index 0000000..26b1e94 --- /dev/null +++ b/camera/provider/2.4/Android.bp @@ -0,0 +1,27 @@ +cc_library_shared { + name: "android.hardware.camera.provider@2.4-impl", + defaults: ["hidl_defaults"], + proprietary: true, + relative_install_path: "hw", + srcs: ["CameraProvider.cpp"], + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libutils", + "libcutils", + "android.hardware.camera.device@1.0", + "camera.device@1.0-impl", + "camera.device@3.2-impl", + "android.hardware.camera.provider@2.4", + "android.hardware.camera.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hidl.allocator@1.0", + "android.hidl.memory@1.0", + "liblog", + "libhardware", + "libcamera_metadata" + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper" + ] +} diff --git a/camera/provider/2.4/CameraProvider.cpp b/camera/provider/2.4/CameraProvider.cpp new file mode 100644 index 0000000..19f7bdd --- /dev/null +++ b/camera/provider/2.4/CameraProvider.cpp @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CamProvider@2.4-impl" +#include + +#include "CameraProvider.h" +#include "CameraDevice_1_0.h" +#include "CameraDevice_3_2.h" +#include +#include + + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_4 { +namespace implementation { + +namespace { +const char *kLegacyProviderName = "legacy/0"; +// "device@/legacy/" +const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)"); +const char *kHAL3_2 = "3.2"; +const char *kHAL1_0 = "1.0"; +const int kMaxCameraDeviceNameLen = 128; +const int kMaxCameraIdLen = 16; + +bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion, + std::string* cameraId) { + std::string deviceNameStd(deviceName.c_str()); + std::smatch sm; + if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) { + if (deviceVersion != nullptr) { + *deviceVersion = sm[1]; + } + if (cameraId != nullptr) { + *cameraId = sm[2]; + } + return true; + } + return false; +} + +} // anonymous namespace + +using ::android::hardware::camera::common::V1_0::CameraMetadataType; +using ::android::hardware::camera::common::V1_0::Status; + +/** + * static callback forwarding methods from HAL to instance + */ +void CameraProvider::sCameraDeviceStatusChange( + const struct camera_module_callbacks* callbacks, + int camera_id, + int new_status) { + CameraProvider* cp = const_cast( + static_cast(callbacks)); + + if (cp == nullptr) { + ALOGE("%s: callback ops is null", __FUNCTION__); + return; + } + + Mutex::Autolock _l(cp->mCbLock); + char cameraId[kMaxCameraIdLen]; + snprintf(cameraId, sizeof(cameraId), "%d", camera_id); + std::string cameraIdStr(cameraId); + cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status; + if (cp->mCallbacks != nullptr) { + CameraDeviceStatus status = (CameraDeviceStatus) new_status; + for (auto const& deviceNamePair : cp->mCameraDeviceNames) { + if (cameraIdStr.compare(deviceNamePair.first) == 0) { + cp->mCallbacks->cameraDeviceStatusChange( + deviceNamePair.second, status); + } + } + } +} + +void CameraProvider::sTorchModeStatusChange( + const struct camera_module_callbacks* callbacks, + const char* camera_id, + int new_status) { + CameraProvider* cp = const_cast( + static_cast(callbacks)); + + if (cp == nullptr) { + ALOGE("%s: callback ops is null", __FUNCTION__); + return; + } + + Mutex::Autolock _l(cp->mCbLock); + if (cp->mCallbacks != nullptr) { + std::string cameraIdStr(camera_id); + TorchModeStatus status = (TorchModeStatus) new_status; + for (auto const& deviceNamePair : cp->mCameraDeviceNames) { + if (cameraIdStr.compare(deviceNamePair.first) == 0) { + cp->mCallbacks->torchModeStatusChange( + deviceNamePair.second, status); + } + } + } +} + +Status CameraProvider::getHidlStatus(int status) { + switch (status) { + case 0: return Status::OK; + case -ENODEV: return Status::INTERNAL_ERROR; + case -EINVAL: return Status::ILLEGAL_ARGUMENT; + default: + ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status); + return Status::INTERNAL_ERROR; + } +} + +std::string CameraProvider::getLegacyCameraId(const hidl_string& deviceName) { + std::string cameraId; + matchDeviceName(deviceName, nullptr, &cameraId); + return cameraId; +} + +int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) { + std::string deviceVersion; + bool match = matchDeviceName(deviceName, &deviceVersion, nullptr); + if (!match) { + return -1; + } + if (deviceVersion == kHAL3_2) { + // maybe switched to 3.4 or define the hidl version enum later + return CAMERA_DEVICE_API_VERSION_3_2; + } else if (deviceVersion == kHAL1_0) { + return CAMERA_DEVICE_API_VERSION_1_0; + } + return 0; +} + +std::string CameraProvider::getHidlDeviceName( + std::string cameraId, int deviceVersion) { + // Maybe consider create a version check method and SortedVec to speed up? + if (deviceVersion != CAMERA_DEVICE_API_VERSION_1_0 && + deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 && + deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 && + deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 ) { + return hidl_string(""); + } + const char* versionStr = (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) ? kHAL1_0 : kHAL3_2; + char deviceName[kMaxCameraDeviceNameLen]; + snprintf(deviceName, sizeof(deviceName), "device@%s/legacy/%s", + versionStr, cameraId.c_str()); + return deviceName; +} + +CameraProvider::CameraProvider() : + camera_module_callbacks_t({sCameraDeviceStatusChange, + sTorchModeStatusChange}) { + mInitFailed = initialize(); +} + +CameraProvider::~CameraProvider() {} + +bool CameraProvider::initialize() { + camera_module_t *rawModule; + int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, + (const hw_module_t **)&rawModule); + if (err < 0) { + ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err)); + return true; + } + + mModule = new CameraModule(rawModule); + err = mModule->init(); + if (err != OK) { + ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err)); + mModule.clear(); + return true; + } + ALOGI("Loaded \"%s\" camera module", mModule->getModuleName()); + + // Setup vendor tags here so HAL can setup vendor keys in camera characteristics + VendorTagDescriptor::clearGlobalVendorTagDescriptor(); + if (!setUpVendorTags()) { + ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__); + } + + // Setup callback now because we are going to try openLegacy next + err = mModule->setCallbacks(this); + if (err != OK) { + ALOGE("Could not set camera module callback: %d (%s)", err, strerror(-err)); + mModule.clear(); + return true; + } + + mNumberOfLegacyCameras = mModule->getNumberOfCameras(); + for (int i = 0; i < mNumberOfLegacyCameras; i++) { + struct camera_info info; + auto rc = mModule->getCameraInfo(i, &info); + if (rc != NO_ERROR) { + ALOGE("%s: Camera info query failed!", __func__); + mModule.clear(); + return true; + } + + if (checkCameraVersion(i, info) != OK) { + ALOGE("%s: Camera version check failed!", __func__); + mModule.clear(); + return true; + } + + char cameraId[kMaxCameraIdLen]; + snprintf(cameraId, sizeof(cameraId), "%d", i); + std::string cameraIdStr(cameraId); + mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT; + mCameraIds.add(cameraIdStr); + + // initialize mCameraDeviceNames and mOpenLegacySupported + mOpenLegacySupported[cameraIdStr] = false; + int deviceVersion = mModule->getDeviceVersion(i); + mCameraDeviceNames.add( + std::make_pair(cameraIdStr, + getHidlDeviceName(cameraIdStr, deviceVersion))); + if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 && + mModule->isOpenLegacyDefined()) { + // try open_legacy to see if it actually works + struct hw_device_t* halDev = nullptr; + int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev); + if (ret == 0) { + mOpenLegacySupported[cameraIdStr] = true; + halDev->close(halDev); + mCameraDeviceNames.add( + std::make_pair(cameraIdStr, + getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0))); + } else if (ret == -EBUSY || ret == -EUSERS) { + // Looks like this provider instance is not initialized during + // system startup and there are other camera users already. + // Not a good sign but not fatal. + ALOGW("%s: open_legacy try failed!", __FUNCTION__); + } + } + } + + return false; // mInitFailed +} + +/** + * Check that the device HAL version is still in supported. + */ +int CameraProvider::checkCameraVersion(int id, camera_info info) { + if (mModule == nullptr) { + return NO_INIT; + } + + // device_version undefined in CAMERA_MODULE_API_VERSION_1_0, + // All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible + if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) { + // Verify the device version is in the supported range + switch (info.device_version) { + case CAMERA_DEVICE_API_VERSION_1_0: + case CAMERA_DEVICE_API_VERSION_3_2: + case CAMERA_DEVICE_API_VERSION_3_3: + case CAMERA_DEVICE_API_VERSION_3_4: + // in support + break; + case CAMERA_DEVICE_API_VERSION_2_0: + case CAMERA_DEVICE_API_VERSION_2_1: + case CAMERA_DEVICE_API_VERSION_3_0: + case CAMERA_DEVICE_API_VERSION_3_1: + // no longer supported + default: + ALOGE("%s: Device %d has HAL version %x, which is not supported", + __FUNCTION__, id, info.device_version); + return NO_INIT; + } + } + + return OK; +} + +bool CameraProvider::setUpVendorTags() { + ATRACE_CALL(); + vendor_tag_ops_t vOps = vendor_tag_ops_t(); + + // Check if vendor operations have been implemented + if (!mModule->isVendorTagDefined()) { + ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__); + return true; + } + + mModule->getVendorTagOps(&vOps); + + // Ensure all vendor operations are present + if (vOps.get_tag_count == nullptr || vOps.get_all_tags == nullptr || + vOps.get_section_name == nullptr || vOps.get_tag_name == nullptr || + vOps.get_tag_type == nullptr) { + ALOGE("%s: Vendor tag operations not fully defined. Ignoring definitions." + , __FUNCTION__); + return false; + } + + // Read all vendor tag definitions into a descriptor + sp desc; + status_t res; + if ((res = VendorTagDescriptor::createDescriptorFromOps(&vOps, /*out*/desc)) + != OK) { + ALOGE("%s: Could not generate descriptor from vendor tag operations," + "received error %s (%d). Camera clients will not be able to use" + "vendor tags", __FUNCTION__, strerror(res), res); + return false; + } + + // Set the global descriptor to use with camera metadata + VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc); + const SortedVector* sectionNames = desc->getAllSectionNames(); + size_t numSections = sectionNames->size(); + std::vector> tagsBySection(numSections); + int tagCount = desc->getTagCount(); + std::vector tags(tagCount); + desc->getTagArray(tags.data()); + for (int i = 0; i < tagCount; i++) { + VendorTag vt; + vt.tagId = tags[i]; + vt.tagName = desc->getTagName(tags[i]); + vt.tagType = (CameraMetadataType) desc->getTagType(tags[i]); + ssize_t sectionIdx = desc->getSectionIndex(tags[i]); + tagsBySection[sectionIdx].push_back(vt); + } + mVendorTagSections.resize(numSections); + for (size_t s = 0; s < numSections; s++) { + mVendorTagSections[s].sectionName = (*sectionNames)[s].string(); + mVendorTagSections[s].tags = tagsBySection[s]; + } + return true; +} + +// Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. +Return CameraProvider::setCallback(const sp& callback) { + Mutex::Autolock _l(mCbLock); + mCallbacks = callback; + return Status::OK; +} + +Return CameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) { + _hidl_cb(Status::OK, mVendorTagSections); + return Void(); +} + +Return CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { + std::vector deviceNameList; + for (auto const& deviceNamePair : mCameraDeviceNames) { + if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) { + deviceNameList.push_back(deviceNamePair.second); + } + } + hidl_vec hidlDeviceNameList(deviceNameList); + _hidl_cb(Status::OK, hidlDeviceNameList); + return Void(); +} + +Return CameraProvider::isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) { + bool support = mModule->isSetTorchModeSupported(); + _hidl_cb (Status::OK, support); + return Void(); +} + +Return CameraProvider::getCameraDeviceInterface_V1_x( + const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb) { + std::string cameraId, deviceVersion; + bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId); + if (!match) { + _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr); + return Void(); + } + + std::string deviceName(cameraDeviceName.c_str()); + ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName)); + if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch + Status status = Status::OK; + ssize_t idx = mCameraIds.indexOf(cameraId); + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str()); + status = Status::ILLEGAL_ARGUMENT; + } else { // invalid version + ALOGE("%s: camera device %s does not support version %s!", + __FUNCTION__, cameraId.c_str(), deviceVersion.c_str()); + status = Status::OPERATION_NOT_SUPPORTED; + } + _hidl_cb(status, nullptr); + return Void(); + } + + if (mCameraStatusMap.count(cameraId) == 0 || + mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) { + _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr); + return Void(); + } + + sp device = + new android::hardware::camera::device::V1_0::implementation::CameraDevice( + mModule, cameraId, mCameraDeviceNames); + + if (device == nullptr) { + ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str()); + _hidl_cb(Status::INTERNAL_ERROR, nullptr); + return Void(); + } + + if (device->isInitFailed()) { + ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str()); + device = nullptr; + _hidl_cb(Status::INTERNAL_ERROR, nullptr); + return Void(); + } + + _hidl_cb (Status::OK, device); + return Void(); +} + +Return CameraProvider::getCameraDeviceInterface_V3_x( + const hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb) { + std::string cameraId, deviceVersion; + bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId); + if (!match) { + _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr); + return Void(); + } + + std::string deviceName(cameraDeviceName.c_str()); + ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName)); + if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch + Status status = Status::OK; + ssize_t idx = mCameraIds.indexOf(cameraId); + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str()); + status = Status::ILLEGAL_ARGUMENT; + } else { // invalid version + ALOGE("%s: camera device %s does not support version %s!", + __FUNCTION__, cameraId.c_str(), deviceVersion.c_str()); + status = Status::OPERATION_NOT_SUPPORTED; + } + _hidl_cb(status, nullptr); + return Void(); + } + + if (mCameraStatusMap.count(cameraId) == 0 || + mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) { + _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr); + return Void(); + } + + sp device = + new android::hardware::camera::device::V3_2::implementation::CameraDevice( + mModule, cameraId, mCameraDeviceNames); + + if (device == nullptr) { + ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str()); + _hidl_cb(Status::INTERNAL_ERROR, nullptr); + return Void(); + } + + if (device->isInitFailed()) { + ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str()); + device = nullptr; + _hidl_cb(Status::INTERNAL_ERROR, nullptr); + return Void(); + } + + _hidl_cb (Status::OK, device); + return Void(); +} + +ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) { + if (strcmp(name, kLegacyProviderName) != 0) { + return nullptr; + } + CameraProvider* provider = new CameraProvider(); + if (provider == nullptr) { + ALOGE("%s: cannot allocate camera provider!", __FUNCTION__); + return nullptr; + } + if (provider->isInitFailed()) { + ALOGE("%s: camera provider init failed!", __FUNCTION__); + delete provider; + return nullptr; + } + return provider; +} + +} // namespace implementation +} // namespace V2_4 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/provider/2.4/CameraProvider.h b/camera/provider/2.4/CameraProvider.h new file mode 100644 index 0000000..75971fa --- /dev/null +++ b/camera/provider/2.4/CameraProvider.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H +#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H + +#include +#include "hardware/camera_common.h" +#include "utils/Mutex.h" +#include "utils/SortedVector.h" +#include +#include +#include +#include "CameraModule.h" +#include "VendorTagDescriptor.h" + +namespace android { +namespace hardware { +namespace camera { +namespace provider { +namespace V2_4 { +namespace implementation { + +using ::android::hardware::camera::common::V1_0::CameraDeviceStatus; +using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::TorchModeStatus; +using ::android::hardware::camera::common::V1_0::VendorTag; +using ::android::hardware::camera::common::V1_0::VendorTagSection; +using ::android::hardware::camera::common::V1_0::helper::CameraModule; +using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor; +using ::android::hardware::camera::provider::V2_4::ICameraProvider; +using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; +using ::android::Mutex; + +struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t { + CameraProvider(); + ~CameraProvider(); + + // Caller must use this method to check if CameraProvider ctor failed + bool isInitFailed() { return mInitFailed; } + + // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow. + Return setCallback(const sp& callback) override; + Return getVendorTags(getVendorTags_cb _hidl_cb) override; + Return getCameraIdList(getCameraIdList_cb _hidl_cb) override; + Return isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override; + Return getCameraDeviceInterface_V1_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V1_x_cb _hidl_cb) override; + Return getCameraDeviceInterface_V3_x( + const hidl_string& cameraDeviceName, + getCameraDeviceInterface_V3_x_cb _hidl_cb) override; + +private: + Mutex mCbLock; + sp mCallbacks = nullptr; + + sp mModule; + + int mNumberOfLegacyCameras; + std::map mCameraStatusMap; // camera id -> status + std::map mOpenLegacySupported; // camera id -> open_legacy HAL1.0 supported + SortedVector mCameraIds; // the "0"/"1" legacy camera Ids + // (cameraId string, hidl device name) pairs + SortedVector> mCameraDeviceNames; + + // Must be queried before using any APIs. + // APIs will only work when this returns true + bool mInitFailed; + bool initialize(); + + hidl_vec mVendorTagSections; + bool setUpVendorTags(); + int checkCameraVersion(int id, camera_info info); + + // extract legacy camera ID/device version from a HIDL device name + static std::string getLegacyCameraId(const hidl_string& deviceName); + static int getCameraDeviceVersion(const hidl_string& deviceName); + + // create HIDL device name from camera ID and device version + static std::string getHidlDeviceName(std::string cameraId, int deviceVersion); + + // convert conventional HAL status to HIDL Status + static Status getHidlStatus(int); + + // static callback forwarding methods + static void sCameraDeviceStatusChange( + const struct camera_module_callbacks* callbacks, + int camera_id, + int new_status); + static void sTorchModeStatusChange( + const struct camera_module_callbacks* callbacks, + const char* camera_id, + int new_status); +}; + +extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name); + +} // namespace implementation +} // namespace V2_4 +} // namespace provider +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H -- cgit v1.2.3