diff options
18 files changed, 1647 insertions, 220 deletions
diff --git a/camera/Android.bp b/camera/Android.bp index e379e49d58..3869766db5 100644 --- a/camera/Android.bp +++ b/camera/Android.bp @@ -3,6 +3,7 @@ subdirs = [ "common/1.0", "common/1.0/default", "device/1.0", + "device/1.0/default", "device/3.2", "device/3.2/default", "metadata/3.2", diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp index af0ff6e2ae..9ec266c129 100644 --- a/camera/common/1.0/default/Android.bp +++ b/camera/common/1.0/default/Android.bp @@ -1,6 +1,10 @@ cc_library_static { name: "android.hardware.camera.common@1.0-helper", - srcs: ["CameraModule.cpp", "CameraMetadata.cpp", "VendorTagDescriptor.cpp"], + srcs: [ + "CameraModule.cpp", + "CameraMetadata.cpp", + "VendorTagDescriptor.cpp", + "HandleImporter.cpp"], cflags: [ "-Werror", "-Wextra", @@ -13,3 +17,4 @@ cc_library_static { include_dirs: ["system/media/private/camera/include"], export_include_dirs : ["include"] } + diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp new file mode 100644 index 0000000000..dee2973386 --- /dev/null +++ b/camera/common/1.0/default/HandleImporter.cpp @@ -0,0 +1,190 @@ +/* + * 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 "HandleImporter" +#include <utils/Log.h> +#include "HandleImporter.h" + +namespace android { +namespace hardware { +namespace camera { +namespace common { +namespace V1_0 { +namespace helper { + +HandleImporter HandleImporter::sHandleImporter; + +HandleImporter& HandleImporter::getInstance() { + sHandleImporter.initialize(); + return sHandleImporter; +} + +bool HandleImporter::initialize() { + // allow only one client + if (mInitialized) { + return false; + } + + if (!openGralloc()) { + return false; + } + + mInitialized = true; + return true; +} + +void HandleImporter::cleanup() { + if (!mInitialized) { + return; + } + + closeGralloc(); + mInitialized = false; +} + +// In IComposer, any buffer_handle_t is owned by the caller and we need to +// make a clone for hwcomposer2. We also need to translate empty handle +// to nullptr. This function does that, in-place. +bool HandleImporter::importBuffer(buffer_handle_t& handle) { + if (!handle->numFds && !handle->numInts) { + handle = nullptr; + return true; + } + + buffer_handle_t clone = cloneBuffer(handle); + if (!clone) { + return false; + } + + handle = clone; + return true; +} + +void HandleImporter::freeBuffer(buffer_handle_t handle) { + if (!handle) { + return; + } + + releaseBuffer(handle); +} + +bool HandleImporter::importFence(const native_handle_t* handle, int& fd) { + if (handle == nullptr || handle->numFds == 0) { + fd = -1; + } else if (handle->numFds == 1) { + fd = dup(handle->data[0]); + if (fd < 0) { + ALOGE("failed to dup fence fd %d", handle->data[0]); + return false; + } + } else { + ALOGE("invalid fence handle with %d file descriptors", + handle->numFds); + return false; + } + + return true; +} + +void HandleImporter::closeFence(int fd) { + if (fd >= 0) { + close(fd); + } +} + +bool HandleImporter::openGralloc() { + const hw_module_t* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + if (err) { + ALOGE("failed to get gralloc module"); + return false; + } + + uint8_t major = (module->module_api_version >> 8) & 0xff; + if (major > 1) { + ALOGE("unknown gralloc module major version %d", major); + return false; + } + + if (major == 1) { + err = gralloc1_open(module, &mDevice); + if (err) { + ALOGE("failed to open gralloc1 device"); + return false; + } + + mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>( + mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN)); + mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>( + mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE)); + if (!mRetain || !mRelease) { + ALOGE("invalid gralloc1 device"); + gralloc1_close(mDevice); + return false; + } + } else { + mModule = reinterpret_cast<const gralloc_module_t*>(module); + } + + return true; +} + +void HandleImporter::closeGralloc() { + if (mDevice) { + gralloc1_close(mDevice); + } +} + +buffer_handle_t HandleImporter::cloneBuffer(buffer_handle_t handle) { + native_handle_t* clone = native_handle_clone(handle); + if (!clone) { + ALOGE("failed to clone buffer %p", handle); + return nullptr; + } + + bool err; + if (mDevice) { + err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE); + } else { + err = (mModule->registerBuffer(mModule, clone) != 0); + } + + if (err) { + ALOGE("failed to retain/register buffer %p", clone); + native_handle_close(clone); + native_handle_delete(clone); + return nullptr; + } + + return clone; +} + +void HandleImporter::releaseBuffer(buffer_handle_t handle) { + if (mDevice) { + mRelease(mDevice, handle); + } else { + mModule->unregisterBuffer(mModule, handle); + } + native_handle_close(handle); + native_handle_delete(const_cast<native_handle_t*>(handle)); +} + +} // namespace helper +} // namespace V1_0 +} // namespace common +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h index 68d4f9051c..9fbfbd527b 100644 --- a/camera/common/1.0/default/include/CameraModule.h +++ b/camera/common/1.0/default/include/CameraModule.h @@ -20,6 +20,7 @@ #include <hardware/camera.h> #include <utils/Mutex.h> #include <utils/KeyedVector.h> +#include <utils/RefBase.h> #include "CameraMetadata.h" diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h new file mode 100644 index 0000000000..def898278c --- /dev/null +++ b/camera/common/1.0/default/include/HandleImporter.h @@ -0,0 +1,73 @@ +/* + * 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 CAMERA_COMMON_1_0_HANDLEIMPORTED_H +#define CAMERA_COMMON_1_0_HANDLEIMPORTED_H + +#include <hardware/gralloc.h> +#include <hardware/gralloc1.h> +#include <system/window.h> + +namespace android { +namespace hardware { +namespace camera { +namespace common { +namespace V1_0 { +namespace helper { + +// Borrowed from graphics HAL. Use this until gralloc mapper HAL is working +class HandleImporter { +public: + static HandleImporter& getInstance(); + + // In IComposer, any buffer_handle_t is owned by the caller and we need to + // make a clone for hwcomposer2. We also need to translate empty handle + // to nullptr. This function does that, in-place. + bool importBuffer(buffer_handle_t& handle); + void freeBuffer(buffer_handle_t handle); + bool importFence(const native_handle_t* handle, int& fd); + void closeFence(int fd); + +private: + + HandleImporter() : mInitialized(false) {} + bool initialize(); + void cleanup(); + bool openGralloc(); + void closeGralloc(); + buffer_handle_t cloneBuffer(buffer_handle_t handle); + void releaseBuffer(buffer_handle_t handle); + + static HandleImporter sHandleImporter; + bool mInitialized; + + // gralloc1 + gralloc1_device_t* mDevice; + GRALLOC1_PFN_RETAIN mRetain; + GRALLOC1_PFN_RELEASE mRelease; + + // gralloc0 + const gralloc_module_t* mModule; +}; + +} // namespace helper +} // namespace V1_0 +} // namespace common +} // namespace camera +} // namespace hardware +} // namespace android + +#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
\ No newline at end of file diff --git a/camera/device/1.0/ICameraDevice.hal b/camera/device/1.0/ICameraDevice.hal index d232a672a7..4a3a406aa3 100644 --- a/camera/device/1.0/ICameraDevice.hal +++ b/camera/device/1.0/ICameraDevice.hal @@ -298,7 +298,8 @@ interface ICameraDevice { recordingEnabled() generates (bool enabled); /** - * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME in + * dataCallbackTimestamp. * * It is camera HAL client's responsibility to release video recording * frames sent out by the camera HAL before the camera HAL receives a call @@ -306,10 +307,26 @@ interface ICameraDevice { * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's * responsibility to manage the life-cycle of the video recording frames. * - * @param data The memory buffer to release a recording frame from. + * @param memId The memory buffer to release a recording frame from. * @param bufferIndex The specific buffer index to return to the HAL. */ - releaseRecordingFrame(MemoryId data, uint32_t bufferIndex); + releaseRecordingFrame(MemoryId memId, uint32_t bufferIndex); + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME in + * handleCallbackTimestamp. + * + * It is camera HAL client's responsibility to release video recording + * frames sent out by the camera HAL before the camera HAL receives a call + * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames. + * + * @param memId The memory buffer to release a recording frame from. + * @param bufferIndex The specific buffer index to return to the HAL. + * @param frame The handle for a released video frame + */ + releaseRecordingFrameHandle(MemoryId memId, uint32_t bufferIndex, handle frame); /** * Start auto focus. @@ -352,14 +369,14 @@ interface ICameraDevice { /** * Set the camera parameters. * - * @param parms The parameter string, consisting of + * @param params The parameter string, consisting of * '<key1>=<value1>; ...;<keyN>=<valueN>'. * @return status The status code for this operation: * OK: Parameter update was successful * ILLEGAL_ARGUMENT: At least one parameter was invalid or not supported * */ - setParameters(string parms) generates (Status status); + setParameters(string params) generates (Status status); /** * Retrieve the camera parameters. diff --git a/camera/device/1.0/ICameraDeviceCallback.hal b/camera/device/1.0/ICameraDeviceCallback.hal index 97014ee3a6..1b0db244c8 100644 --- a/camera/device/1.0/ICameraDeviceCallback.hal +++ b/camera/device/1.0/ICameraDeviceCallback.hal @@ -42,8 +42,10 @@ interface ICameraDeviceCallback { * @param bufferCount The number of contiguous buffers that the descriptor * contains. * - * @return memId A integer identifier for this memory buffer, for use with - * data callbacks and unregistering memory. + * @return memId A positive integer identifier for this memory buffer, for + * use with data callbacks and unregistering memory. 0 must be returned + * in case of error, such as if the descriptor does not contain exactly + * one FD. */ registerMemory(handle descriptor, uint32_t bufferSize, uint32_t bufferCount) generates (MemoryId memId); @@ -62,7 +64,8 @@ interface ICameraDeviceCallback { * starts. * */ - dataCallback(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex); + dataCallback(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex, + CameraFrameMetadata metadata); /** * Send a buffer of image data to the camera service, with a timestamp @@ -78,4 +81,21 @@ interface ICameraDeviceCallback { dataCallbackTimestamp(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex, int64_t timestamp); + /** + * Send a buffer of image data to the camera service, with a timestamp + * + * @param msgType The kind of image buffer data this call represents. + * @param handle The handle of image buffer data this call represents. + * @param data A memory handle to the buffer containing the data. + * @param bufferIndex The offset into the memory handle where the buffer + * starts. + * @param timestamp The time this buffer was captured by the camera, in + * nanoseconds. + * + * @return frameId a frame ID to be used with releaseRecordingFrameId later + * + */ + handleCallbackTimestamp(DataCallbackMsg msgType, handle frameData, MemoryId data, + uint32_t bufferIndex, int64_t timestamp); + }; diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal index ebc74604b6..4c9b517265 100644 --- a/camera/device/1.0/ICameraDevicePreviewCallback.hal +++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal @@ -30,28 +30,31 @@ interface ICameraDevicePreviewCallback { * * @return status The status code for this operation. If not OK, then * buffer and stride must not be used. - * @return buffer A handle to the buffer to write into. + * @return bufferId A unique ID for the returned buffer. + * @return buffer A handle to the buffer to write into. Must be non-null if the bufferId has not + * been seen by HAL before. Must be null if the bufferId is seen before. HAL must keep track + * of the bufferId to actual buffer handle mapping. * @return stride The stride between two rows of pixels in this buffer. */ - dequeueBuffer() generates (Status status, handle buffer, uint32_t stride); + dequeueBuffer() generates (Status status, uint64_t bufferId, handle buffer, uint32_t stride); /** * Send a filled preview buffer to its consumer. * - * @param buffer The handle to the preview buffer that's been filled. + * @param bufferId The bufferId of the preview buffer * @return status The status code for this operation. */ - enqueueBuffer(handle buffer) generates (Status status); + enqueueBuffer(uint64_t bufferId) generates (Status status); /** * Return a preview buffer unfilled. This buffer must not be sent on to the * preview consumer as a valid buffer, but may be reused as if it were * empty. * - * @param buffer The handle to the preview buffer to return. + * @param bufferId The bufferId of the preview buffer * @return status The status code for this operation. */ - cancelBuffer(handle buffer) generates (Status status); + cancelBuffer(uint64_t bufferId) generates (Status status); /** * Set the number of preview buffers needed by the HAL. diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp new file mode 100644 index 0000000000..1663787159 --- /dev/null +++ b/camera/device/1.0/default/Android.bp @@ -0,0 +1,27 @@ +cc_library_shared { + name: "camera.device@1.0-impl", + srcs: [ + "CameraDevice.cpp", + ], + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libhwbinder", + "libutils", + "android.hardware.camera.device@1.0", + "android.hardware.camera.common@1.0", + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.common@1.0", + "android.hidl.base@1.0", + "libcutils", + "liblog", + "libhardware", + "libcamera_metadata", + "libbinder", + ], + static_libs: [ + "android.hardware.camera.common@1.0-helper" + ], + export_include_dirs: ["."] +} + diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp new file mode 100644 index 0000000000..819525be1e --- /dev/null +++ b/camera/device/1.0/default/CameraDevice.cpp @@ -0,0 +1,948 @@ +/* + * 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 <utils/Log.h> +#include <hardware/camera.h> +#include <hardware/gralloc1.h> +#include <utils/Trace.h> + +#include "CameraDevice_1_0.h" + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::graphics::allocator::V2_0::ProducerUsage; +using ::android::hardware::graphics::common::V1_0::PixelFormat; + +HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance(); + +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<CameraModule> module, const std::string& cameraId, + const SortedVector<std::pair<std::string, std::string>>& 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; + } +} + +CameraDevice::~CameraDevice() { + Mutex::Autolock _l(mLock); + if (mDevice != nullptr) { + ALOGW("%s: camera %s is deleted while open", __FUNCTION__, mCameraId.c_str()); + close(); + } + 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()); + close(); + } + 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<CameraPreviewWindow*>(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*) { + // TODO: make sure lock_buffer is indeed a no-op (and will always be) + return 0; +} + +int CameraDevice::sEnqueueBuffer(struct preview_stream_ops* w, buffer_handle_t* buffer) { + CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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<CameraPreviewWindow*>(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((ProducerUsage) usage)); +} + +int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) { + CameraPreviewWindow* object = static_cast<CameraPreviewWindow*>(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<const CameraPreviewWindow*>(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) { + mHeap = new MemoryHeapBase(fd, buf_size * num_buffers); + commonInitialization(); +} + +CameraDevice::CameraHeapMemory::CameraHeapMemory(size_t buf_size, uint_t num_buffers) : + mBufSize(buf_size), + mNumBufs(num_buffers) { + mHeap = new MemoryHeapBase(buf_size * num_buffers); + commonInitialization(); +} + +void CameraDevice::CameraHeapMemory::commonInitialization() { + handle.data = mHeap->base(); + handle.size = mBufSize * mNumBufs; + handle.handle = this; + + mBuffers = new sp<MemoryBase>[mNumBufs]; + for (uint_t i = 0; i < mNumBufs; i++) { + mBuffers[i] = new MemoryBase(mHeap, i * mBufSize, mBufSize); + } + + handle.release = sPutMemory; +} + +CameraDevice::CameraHeapMemory::~CameraHeapMemory() { + delete [] mBuffers; +} + +// 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<CameraDevice*>(user); + if (object->mDeviceCallback == nullptr) { + ALOGE("%s: camera HAL request memory while camera is not opened!", __FUNCTION__); + return nullptr; + } + + CameraHeapMemory* mem; + native_handle_t* handle = native_handle_create(1,0); + + if (handle == nullptr) { + ALOGE("%s: native_handle_create failed!", __FUNCTION__); + return nullptr; + } + + if (fd < 0) { + mem = new CameraHeapMemory(buf_size, num_bufs); + } else { + mem = new CameraHeapMemory(fd, buf_size, num_bufs); + } + handle->data[0] = mem->mHeap->getHeapID(); + mem->incStrong(mem); + + hidl_handle hidlHandle = handle; + 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; + native_handle_delete(handle); + return &mem->handle; +} + +void CameraDevice::sPutMemory(camera_memory_t *data) { + if (!data) + return; + + CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(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<CameraDevice*>(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<CameraDevice*>(user); + sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory*>(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<CameraHeapMemory *>(data->handle); + object->mDeviceCallback->dataCallback( + (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata); + } +} + +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<CameraDevice*>(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<CameraHeapMemory> mem(static_cast<CameraHeapMemory*>(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*) + mem->mBuffers[index]->pointer(); + if (md->eType == VideoNativeHandleMetadata::kMetadataBufferTypeNativeHandleSource) { + handle = md->pHandle; + } + } + } + + if (object->mDeviceCallback != nullptr) { + if (handle == nullptr) { + object->mDeviceCallback->dataCallbackTimestamp( + (DataCallbackMsg) msg_type, mem->handle.mId, index, timestamp); + } else { + object->mDeviceCallback->handleCallbackTimestamp( + (DataCallbackMsg) msg_type, handle, mem->handle.mId, index, timestamp); + } + } +} + +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<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { + Status status = initStatus(); + CameraResourceCost resCost; + if (status == Status::OK) { + int cost = 100; + std::vector<std::string> 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<void> 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. + // TODO: figure out should we override here or let + // camera service handle it. + 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<Status> 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<Status> 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<Status> CameraDevice::open(const sp<ICameraDeviceCallback>& 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<Status> CameraDevice::setPreviewWindow(const sp<ICameraDevicePreviewCallback>& 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<void> 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<void> 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<bool> 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<Status> 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<void> 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<bool> 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<Status> 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<Status> 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<void> 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<bool> 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); + sp<MemoryHeapBase> heap = camMemory->mHeap; + if (bufferIndex >= camMemory->mNumBufs) { + ALOGE("%s: bufferIndex %d exceeds number of buffers %d", + __FUNCTION__, bufferIndex, camMemory->mNumBufs); + return; + } + sp<IMemory> mem = camMemory->mBuffers[bufferIndex]; + // TODO: simplify below logic once we verify offset is indeed idx * mBufSize + // and heap == heap2 + ssize_t offset; + size_t size; + sp<IMemoryHeap> heap2 = mem->getMemory(&offset, &size); + if ((size_t)offset != bufferIndex * camMemory->mBufSize) { + ALOGI("%s: unexpected offset %zd (was expecting %zu)", + __FUNCTION__, offset, bufferIndex * camMemory->mBufSize); + } + if (heap != heap2) { + ALOGE("%s: heap mismatch!", __FUNCTION__); + return; + } + void *data = ((uint8_t *)heap->base()) + offset; + if (handle) { + VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) data; + if (md->eType == VideoNativeHandleMetadata::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<void> 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<void> 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<Status> 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<Status> 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<Status> 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<Status> 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<Status> 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<void> 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<Status> 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<void> CameraDevice::close() { + ALOGI("Closing camera %s", mCameraId.c_str()); + Mutex::Autolock _l(mLock); + 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; + } + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h new file mode 100644 index 0000000000..2568f86671 --- /dev/null +++ b/camera/device/1.0/default/CameraDevice_1_0.h @@ -0,0 +1,224 @@ +/* + * 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 <unordered_map> +#include "utils/Mutex.h" +#include "utils/SortedVector.h" +#include <binder/MemoryBase.h> +#include <binder/MemoryHeapBase.h> +#include "CameraModule.h" +#include "HandleImporter.h" + +#include <android/hardware/camera/device/1.0/ICameraDevice.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +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::base::V1_0::IBase; +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<CameraModule> module, + const std::string& cameraId, + const SortedVector<std::pair<std::string, std::string>>& 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<void> getResourceCost(getResourceCost_cb _hidl_cb) override; + Return<void> getCameraInfo(getCameraInfo_cb _hidl_cb) override; + Return<Status> setTorchMode(TorchMode mode) override; + Return<Status> dumpState(const hidl_handle& fd) override; + Return<Status> open(const sp<ICameraDeviceCallback>& callback) override; + Return<Status> setPreviewWindow(const sp<ICameraDevicePreviewCallback>& window) override; + Return<void> enableMsgType(uint32_t msgType) override; + Return<void> disableMsgType(uint32_t msgType) override; + Return<bool> msgTypeEnabled(uint32_t msgType) override; + Return<Status> startPreview() override; + Return<void> stopPreview() override; + Return<bool> previewEnabled() override; + Return<Status> storeMetaDataInBuffers(bool enable) override; + Return<Status> startRecording() override; + Return<void> stopRecording() override; + Return<bool> recordingEnabled() override; + Return<void> releaseRecordingFrame(uint32_t memId, uint32_t bufferIndex) override; + Return<void> releaseRecordingFrameHandle( + uint32_t memId, uint32_t bufferIndex, const hidl_handle& frame) override; + Return<Status> autoFocus() override; + Return<Status> cancelAutoFocus() override; + Return<Status> takePicture() override; + Return<Status> cancelPicture() override; + Return<Status> setParameters(const hidl_string& params) override; + Return<void> getParameters(getParameters_cb _hidl_cb) override; + Return<Status> sendCommand(CommandType cmd, int32_t arg1, int32_t arg2) override; + Return<void> 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(size_t buf_size, uint_t num_buffers = 1); + void commonInitialization(); + virtual ~CameraHeapMemory(); + + size_t mBufSize; + uint_t mNumBufs; + // TODO: b/35887419: use hidl_memory instead and get rid of libbinder + sp<MemoryHeapBase> mHeap; + sp<MemoryBase>* mBuffers; + CameraMemory handle; + }; + + // TODO: b/35625849 + // Meta data buffer layout for passing a native_handle to codec + // matching frameworks/native/include/media/hardware/MetadataBufferType.h and + // frameworks/native/include/media/hardware/HardwareAPI.h + struct VideoNativeHandleMetadata { + static const uint32_t kMetadataBufferTypeNativeHandleSource = 3; + uint32_t eType; // must be kMetadataBufferTypeNativeHandleSource + native_handle_t* pHandle; + }; + + const sp<CameraModule> 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<ICameraDevicePreviewCallback> mPreviewCallback = nullptr; + std::unordered_map<uint64_t, buffer_handle_t> mCirculatingBuffers; + std::unordered_map<buffer_handle_t*, uint64_t> 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<std::pair<std::string, std::string>>& mCameraDeviceNames; + + sp<ICameraDeviceCallback> mDeviceCallback = nullptr; + + std::unordered_map<MemoryId, CameraHeapMemory*> mMemoryMap; + + bool mMetadataMode = false; + + 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; +}; + +} // 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/device/1.0/types.hal b/camera/device/1.0/types.hal index 83c0be44ba..b32c938107 100644 --- a/camera/device/1.0/types.hal +++ b/camera/device/1.0/types.hal @@ -189,6 +189,66 @@ enum DataCallbackMsg : uint32_t { PREVIEW_METADATA = 0x0400 }; +/** + * Information for a single detected face. + */ + struct CameraFace { + /** + * Bounds of the face [left, top, right, bottom]. (-1000, -1000) represents + * the top-left of the camera field of view, and (1000, 1000) represents the + * bottom-right of the field of view. The width and height cannot be 0 or + * negative. This is supported by both hardware and software face detection. + * + * The direction is relative to the sensor orientation, that is, what the + * sensor sees. The direction is not affected by the rotation or mirroring + * of CAMERA_CMD_SET_DISPLAY_ORIENTATION. + */ + int32_t[4] rect; + + /** + * The confidence level of the face. The range is 1 to 100. 100 is the + * highest confidence. This is supported by both hardware and software + * face detection. + */ + int32_t score; + + /** + * An unique id per face while the face is visible to the tracker. If + * the face leaves the field-of-view and comes back, it will get a new + * id. If the value is 0, id is not supported. + */ + int32_t id; + + /** + * The coordinates of the center of the left eye. The range is -1000 to + * 1000. -2000, -2000 if this is not supported. + */ + int32_t[2] leftEye; + + /** + * The coordinates of the center of the right eye. The range is -1000 to + * 1000. -2000, -2000 if this is not supported. + */ + int32_t[2] rightEye; + + /** + * The coordinates of the center of the mouth. The range is -1000 to 1000. + * -2000, -2000 if this is not supported. + */ + int32_t[2] mouth; + +}; + +/** + * The metadata of the frame data, such as face detection result. + */ +struct CameraFrameMetadata { + /** + * A vector of the detected faces. + */ + vec<CameraFace> faces; +}; + /* * A simple integer handle to use to reference a particular memory buffer * between the HAL and the framework. diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp index 18e0e7bb87..0a457ad91d 100644 --- a/camera/device/3.2/default/CameraDevice.cpp +++ b/camera/device/3.2/default/CameraDevice.cpp @@ -15,11 +15,11 @@ */ #define LOG_TAG "CamDev@3.2-impl" -#include <android/log.h> +#include <utils/Log.h> #include <utils/Vector.h> #include <utils/Trace.h> -#include "CameraDevice.h" +#include "CameraDevice_3_2.h" #include <include/convert.h> namespace android { diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp index 0f3d97bdb3..3c3c078eb8 100644 --- a/camera/device/3.2/default/CameraDeviceSession.cpp +++ b/camera/device/3.2/default/CameraDeviceSession.cpp @@ -29,198 +29,13 @@ namespace device { namespace V3_2 { namespace implementation { -namespace { - -// Copy pasted from Hwc.cpp. Use this until gralloc mapper HAL is working -class HandleImporter { -public: - HandleImporter() : mInitialized(false) {} - - bool initialize() - { - // allow only one client - if (mInitialized) { - return false; - } - - if (!openGralloc()) { - return false; - } - - mInitialized = true; - return true; - } - - void cleanup() - { - if (!mInitialized) { - return; - } - - closeGralloc(); - mInitialized = false; - } - - // In IComposer, any buffer_handle_t is owned by the caller and we need to - // make a clone for hwcomposer2. We also need to translate empty handle - // to nullptr. This function does that, in-place. - bool importBuffer(buffer_handle_t& handle) - { - if (!handle->numFds && !handle->numInts) { - handle = nullptr; - return true; - } - - buffer_handle_t clone = cloneBuffer(handle); - if (!clone) { - return false; - } - - handle = clone; - return true; - } - - void freeBuffer(buffer_handle_t handle) - { - if (!handle) { - return; - } - - releaseBuffer(handle); - } - - bool importFence(const native_handle_t* handle, int& fd) - { - if (handle == nullptr || handle->numFds == 0) { - fd = -1; - } else if (handle->numFds == 1) { - fd = dup(handle->data[0]); - if (fd < 0) { - ALOGE("failed to dup fence fd %d", handle->data[0]); - return false; - } - } else { - ALOGE("invalid fence handle with %d file descriptors", - handle->numFds); - return false; - } - - return true; - } - - void closeFence(int fd) - { - if (fd >= 0) { - close(fd); - } - } - -private: - bool mInitialized; - - bool openGralloc() - { - const hw_module_t* module; - int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); - if (err) { - ALOGE("failed to get gralloc module"); - return false; - } - - uint8_t major = (module->module_api_version >> 8) & 0xff; - if (major > 1) { - ALOGE("unknown gralloc module major version %d", major); - return false; - } - - if (major == 1) { - err = gralloc1_open(module, &mDevice); - if (err) { - ALOGE("failed to open gralloc1 device"); - return false; - } - - mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>( - mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN)); - mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>( - mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE)); - if (!mRetain || !mRelease) { - ALOGE("invalid gralloc1 device"); - gralloc1_close(mDevice); - return false; - } - } else { - mModule = reinterpret_cast<const gralloc_module_t*>(module); - } - - return true; - } - - void closeGralloc() - { - if (mDevice) { - gralloc1_close(mDevice); - } - } - - buffer_handle_t cloneBuffer(buffer_handle_t handle) - { - native_handle_t* clone = native_handle_clone(handle); - if (!clone) { - ALOGE("failed to clone buffer %p", handle); - return nullptr; - } - - bool err; - if (mDevice) { - err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE); - } else { - err = (mModule->registerBuffer(mModule, clone) != 0); - } - - if (err) { - ALOGE("failed to retain/register buffer %p", clone); - native_handle_close(clone); - native_handle_delete(clone); - return nullptr; - } - - return clone; - } - - void releaseBuffer(buffer_handle_t handle) - { - if (mDevice) { - mRelease(mDevice, handle); - } else { - mModule->unregisterBuffer(mModule, handle); - } - native_handle_close(handle); - native_handle_delete(const_cast<native_handle_t*>(handle)); - } - - // gralloc1 - gralloc1_device_t* mDevice; - GRALLOC1_PFN_RETAIN mRetain; - GRALLOC1_PFN_RELEASE mRelease; - - // gralloc0 - const gralloc_module_t* mModule; -}; - -HandleImporter sHandleImporter; - -} // Anonymous namespace +HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance(); CameraDeviceSession::CameraDeviceSession( camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) : camera3_callback_ops({&sProcessCaptureResult, &sNotify}), mDevice(device), mCallback(callback) { - // For now, we init sHandleImporter but do not cleanup (keep it alive until - // HAL process ends) - sHandleImporter.initialize(); - mInitFail = initialize(); } diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h index f8689d3bd9..3786e4b2ba 100644 --- a/camera/device/3.2/default/CameraDeviceSession.h +++ b/camera/device/3.2/default/CameraDeviceSession.h @@ -26,6 +26,7 @@ #include <hidl/Status.h> #include <hidl/MQDescriptor.h> #include <include/convert.h> +#include "HandleImporter.h" namespace android { namespace hardware { @@ -39,6 +40,7 @@ using ::android::hardware::camera::device::V3_2::HalStreamConfiguration; using ::android::hardware::camera::device::V3_2::StreamConfiguration; using ::android::hardware::camera::device::V3_2::ICameraDeviceSession; using ::android::hardware::camera::common::V1_0::Status; +using ::android::hardware::camera::common::V1_0::helper::HandleImporter; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::hidl_vec; @@ -109,6 +111,8 @@ private: // Stream ID -> circulating buffers map std::map<int, CirculatingBuffers> mCirculatingBuffers; + static HandleImporter& sHandleImporter; + bool mInitFail; bool initialize(); diff --git a/camera/device/3.2/default/CameraDevice.h b/camera/device/3.2/default/CameraDevice_3_2.h index 317eea53f4..4e8606757c 100644 --- a/camera/device/3.2/default/CameraDevice.h +++ b/camera/device/3.2/default/CameraDevice_3_2.h @@ -55,7 +55,7 @@ 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 object in + // Also, provider will have to keep track of all CameraDevice objects in // order to notify CameraDevice when the underlying camera is detached CameraDevice(sp<CameraModule> module, const std::string& cameraId, @@ -81,8 +81,7 @@ struct CameraDevice : public ICameraDevice { /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */ private: - // Passed from provider HAL. Should not change. - sp<CameraModule> mModule; + const sp<CameraModule> mModule; const std::string mCameraId; // const after ctor int mCameraIdInt; diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp index 7315292282..a6febec832 100644 --- a/camera/provider/2.4/default/Android.bp +++ b/camera/provider/2.4/default/Android.bp @@ -10,6 +10,7 @@ cc_library_shared { "libcutils", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", + "camera.device@1.0-impl", "camera.device@3.2-impl", "android.hardware.camera.provider@2.4", "android.hardware.camera.common@1.0", @@ -34,15 +35,9 @@ cc_binary { "libhidltransport", "liblog", "libutils", - "libhardware", "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", "android.hardware.camera.provider@2.4", "android.hardware.camera.common@1.0", - "libcutils", - "libcamera_metadata" ], - static_libs: [ - "android.hardware.camera.common@1.0-helper" - ] } diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp index 5714f835be..ad9f0b8621 100644 --- a/camera/provider/2.4/default/CameraProvider.cpp +++ b/camera/provider/2.4/default/CameraProvider.cpp @@ -18,7 +18,8 @@ #include <android/log.h> #include "CameraProvider.h" -#include "CameraDevice.h" +#include "CameraDevice_1_0.h" +#include "CameraDevice_3_2.h" #include <string.h> #include <utils/Trace.h> @@ -59,8 +60,6 @@ void CameraProvider::sCameraDeviceStatusChange( return; } - ALOGI("%s resolved provider %p", __FUNCTION__, cp); - Mutex::Autolock _l(cp->mCbLock); char cameraId[kMaxCameraIdLen]; snprintf(cameraId, sizeof(cameraId), "%d", camera_id); @@ -89,8 +88,6 @@ void CameraProvider::sTorchModeStatusChange( return; } - ALOGI("%s resolved provider %p", __FUNCTION__, cp); - Mutex::Autolock _l(cp->mCbLock); if (cp->mCallbacks != nullptr) { std::string cameraIdStr(camera_id); @@ -323,9 +320,57 @@ Return<void> CameraProvider::isSetTorchModeSupported(isSetTorchModeSupported_cb } Return<void> CameraProvider::getCameraDeviceInterface_V1_x( - const hidl_string& /*cameraDeviceName*/, getCameraDeviceInterface_V1_x_cb _hidl_cb) { - // TODO implement after device 1.0 is implemented - _hidl_cb(Status::INTERNAL_ERROR, nullptr); + const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb) { + std::smatch sm; + bool match = matchDeviceName(cameraDeviceName, sm); + if (!match) { + _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr); + return Void(); + } + + std::string cameraId = sm[2]; + std::string deviceVersion = sm[1]; + 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<android::hardware::camera::device::V1_0::implementation::CameraDevice> 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(); } |