diff options
| author | dd3boh <dade.garberi@gmail.com> | 2017-09-25 14:03:50 +0200 | 
|---|---|---|
| committer | dd3boh <dade.garberi@gmail.com> | 2017-10-31 12:34:43 +0100 | 
| commit | e550f1c8ce684372aacc8f872dc4072ec98cecfa (patch) | |
| tree | 8fe96755f9e8e5a788b4b1c482fb382e8b9710a2 /camera/zuk/CameraDevice.cpp | |
| parent | 579ac7db0d582756e63697664ec8faccf55fb11d (diff) | |
camera: Fork camera provider 2.4 and camera device 1.0 from hardware/interfaces/camera
camera/device/1.0/default -> camera/zuk
camera/provider/2.4/default -> camera/provider
Signed-off-by: dd3boh <dade.garberi@gmail.com>
Diffstat (limited to 'camera/zuk/CameraDevice.cpp')
| -rw-r--r-- | camera/zuk/CameraDevice.cpp | 1006 | 
1 files changed, 1006 insertions, 0 deletions
| diff --git a/camera/zuk/CameraDevice.cpp b/camera/zuk/CameraDevice.cpp new file mode 100644 index 0000000..c53c0d8 --- /dev/null +++ b/camera/zuk/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 <hardware/camera.h> +#include <hardware/gralloc1.h> +#include <hidlmemory/mapping.h> +#include <log/log.h> +#include <utils/Trace.h> + +#include <media/hardware/HardwareAPI.h> // 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<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; +    } + +    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<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*) { +    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((BufferUsage)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) { +    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<IAllocator> 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<CameraDevice*>(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<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::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<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*) +                    ((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<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. +            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); +        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<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<void> CameraDevice::releaseRecordingFrameHandleBatch( +        const hidl_vec<VideoFrameMessage>& 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<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() { +    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 | 
