Skip to content

Instantly share code, notes, and snippets.

@erfanoabdi
Last active September 15, 2019 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erfanoabdi/bd6baef41b575a9c2b86c46727a0a903 to your computer and use it in GitHub Desktop.
Save erfanoabdi/bd6baef41b575a9c2b86c46727a0a903 to your computer and use it in GitHub Desktop.
/*
* 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;
{
Mutex::Autolock _l(object->mMemoryMapLock);
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);
{
Mutex::Autolock _l(device->mMemoryMapLock);
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;
{
Mutex::Autolock _l(mMemoryMapLock);
auto it = mMemoryMap.find(memId);
if (it == mMemoryMap.end() || it->second == nullptr) {
ALOGE("%s unknown memoryId %d", __FUNCTION__, memId);
return;
}
camMemory = it->second;
}
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 (mCameraId == "0")
outStr = "ae-bracket-hdr=Off;ae-bracket-hdr-values=Off,AE-Bracket;af-bracket=af-bracket-off;af-bracket-values=af-bracket-off,af-bracket-on;antibanding=auto;antibanding-values=off,60hz,50hz,auto;auto-dc-offset-mode=on;auto-dc-offset-mode-values=off,on;auto-exposure=center-weighted;auto-exposure-lock=false;auto-exposure-lock-supported=true;auto-exposure-values=frame-average,center-weighted,spot-metering,center-weighted,spot-metering-adv,center-weighted-adv;auto-hdr-supported=true;auto-whitebalance-lock=false;auto-whitebalance-lock-supported=true;avtimer=disable;background-proc=on;brightness-step=1;burst-max-fps=80;burst-status=off;burst-status-values=off,on;cache-video-buffers=disable;camera-mode=0;cds-mode-values=off,on,auto;chroma-flash=chroma-flash-off;chroma-flash-values=chroma-flash-off,chroma-flash-on;contrast=5;contrast-step=1;dbg-log-aec=off;dbg-log-aec-values=on,off;dbg-log-af=off;dbg-log-af-values=on,off;dbg-log-awb=off;dbg-log-awb-values=on,off;denoise=denoise-on;denoise-values=denoise-off,denoise-on;dis=disable;dis-values=enable,disable;effect=none;effect-values=none,mono,negative,solarize,sepia,posterize,whiteboard,blackboard,aqua,emboss,sketch,neon;exposure-compensation=0;exposure-compensation-step=0.166667;face-detection=off;face-detection-values=off,on;flash-mode=off;flash-mode-values=off,auto,on,torch;flip-mode-values=off,flip-v,flip-h,flip-vh;focal-length=3.68;focus-areas=(0,0,0,0,0);focus-distances=Infinity,Infinity,Infinity;focus-mode=auto;focus-mode-values=auto,infinity,fixed,macro,continuous-video,continuous-picture,manual;hdr-mode=hdr-mode-multiframe;hdr-mode-values=hdr-mode-sensor,hdr-mode-multiframe;hdr-need-1x=false;hdr-need-1x-values=false,true;hfr-size-values=1920x1080,1280x720;histogram=disable;histogram-values=enable,disable;horizontal-view-angle=64.85;instant-aec-values=;instant-capture-values=;internal-restart=true;iso=auto;iso-values=auto,ISO_HJR,ISO50,ISO100,ISO200,ISO400,ISO800,ISO1600,ISO3200;jpeg-quality=95;jpeg-thumbnail-height=384;jpeg-thumbnail-quality=85;jpeg-thumbnail-size-values=512x384,512x288,0x0;jpeg-thumbnail-width=512;jsaudio=off;jsaudio-values=off,on;jsreplace=on;jsreplace-values=off,on;jsvideo=off;jsvideo-values=off,on;lensshade=enable;lensshade-values=enable,disable;long-shot=off;longshot-supported=true;luma-adaptation=3;manual-dc-offset=0;manual-dc-offset-max=0;manual-dc-offset-min=-40;manual-dc-offset-step=1;manual-exposure-modes=off,exp-time-priority,iso-priority,user-setting;manual-focus-modes=off,scale-mode,diopter-mode;manual-wb-modes=off,color-temperature,rbgb-gains;max-brightness=6;max-contrast=10;max-exposure-compensation=12;max-exposure-time=500.000000;max-focus-pos-dac=1023;max-focus-pos-diopter=10;max-focus-pos-index=1023;max-focus-pos-ratio=100;max-iso=4697;max-num-detected-faces-hw=32;max-num-detected-faces-sw=32;max-num-focus-areas=1;max-num-metering-areas=1;max-saturation=10;max-sce-factor=100;max-sharpness=36;max-wb-cct=8000;max-wb-gain=4;max-zoom=90;mce=enable;mce-values=enable,disable;metering-areas=(0,0,0,0,0);min-brightness=0;min-contrast=0;min-exposure-compensation=-12;min-exposure-time=0.010486;min-focus-pos-dac=0;min-focus-pos-diopter=0;min-focus-pos-index=0;min-focus-pos-ratio=0;min-iso=48;min-saturation=0;min-sce-factor=-100;min-sharpness=0;min-wb-cct=2000;min-wb-gain=1;mot-barcodes-supported=false;mot-beauty=off;mot-beauty-level=5;mot-beauty-limitfps-need=false;mot-beauty-maxfps=22;mot-beauty-values=off;mot-max-still-fps=30;mot-mcas-mode=on;mot-mcas-mode-values=off,on;mot-sensor-video-hdr-supported-sizes=1920x1080x30,3840x2160x30;num-retro-burst-per-shutter=0;num-snaps-per-shutter=1;opti-zoom=opti-zoom-off;opti-zoom-values=opti-zoom-off,opti-zoom-on;picture-format=jpeg;picture-format-values=jpeg;picture-size=4160x3120;picture-size-values=4160x3120,4160x2340,3840x2160,3264x2448,3264x1836,2592x1944,2592x1458,1920x1080,1440x1080,1280x960,1280x720,720x480,640x480,352x288,320x240,176x144;preferred-preview-size-for-video=1920x1080;preview-flip=off;preview-format=yuv420sp;preview-format-values=yuv420sp,yuv420p;preview-fps-range=4000,30000;preview-fps-range-values=(15000,15000),(15000,20000),(20000,20000),(4000,30000),(30000,30000),(9000,30000),(15000,30000),(24000,30000);preview-frame-rate=30;preview-frame-rate-values=4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30;preview-hist=preview-hist-off;preview-hist-values=preview-hist-off,preview-hist-on;preview-size=1920x1080;preview-size-values=1920x1080,1440x1080,1280x720,960x720,768x432,720x480,640x480,320x240,176x144;qc-camera-features=1011613183;qc-max-num-requested-faces=32;raw-size=4208x3120;rdi-mode=disable;rdi-mode-values=enable,disable;re-focus=re-focus-off;re-focus-values=re-focus-off,re-focus-on;redeye-reduction=disable;redeye-reduction-values=enable,disable;saturation=5;saturation-step=1;sce-factor-step=10;scene-detect=off;scene-detect-values=off,on;scene-mode=auto;scene-mode-values=auto,hdr,auto_hdr;scene-selection=disable;secure-mode=disable;secure-mode-values=enable,disable;selectable-zone-af=auto;selectable-zone-af-values=auto,spot-metering,center-weighted,frame-average;sensor-hdr=off;sensor-hdr-values=off,on;sharpness=12;sharpness-step=6;skinToneEnhancement=0;skinToneEnhancement-values=enable,disable;smooth-zoom-supported=true;snapshot-burst-num=0;snapshot-picture-flip=off;still-more=still-more-off;still-more-values=still-more-off,still-more-on;supported-live-snapshot-sizes=4160x2340,3840x2160,3264x2448,3264x1836,2592x1944,2592x1458,1920x1080,1440x1080,1280x960,1280x720,1024x768,864x480,720x480,640x480,352x288,320x240;tintless=on;tintless-values=off,on;tnr-mode-values=off,on;touch-af-aec=touch-off;touch-af-aec-values=touch-off,touch-on;true-portrait-values=true-portrait-off,true-portrait-on;vertical-view-angle=50.95;video-batch-size=0;video-cds-mode-values=off,on,auto;video-flip=off;video-frame-format=android-opaque;video-hdr=off;video-hdr-values=off,on;video-hfr=off;video-hfr-values=60,120,off;video-hsr=off;video-rotation=0;video-rotation-values=0,90,180,270;video-size-values=3840x2160,1920x1080,1280x720,864x480,720x480,640x480,352x288,320x240,176x144;video-snapshot-supported=true;video-stabilization=false;video-stabilization-supported=true;video-tnr-mode-values=off,on;visionfw=off;visionfw-values=off,on;whitebalance=auto;whitebalance-values=auto,incandescent,fluorescent,warm-fluorescent,daylight,cloudy-daylight,twilight,shade,manual;zoom=0;zoom-ratios=100,102,104,107,109,112,114,117,120,123,125,128,131,135,138,141,144,148,151,155,158,162,166,170,174,178,182,186,190,195,200,204,209,214,219,224,229,235,240,246,251,257,263,270,276,282,289,296,303,310,317,324,332,340,348,356,364,373,381,390,400,409,418,428,438,448,459,470,481,492,503,515,527,540,552,565,578,592,606,620,634,649,664,680,696,712,729,746,763,781,800;zoom-supported=true;zsl=on;zsl-hdr-supported=true;zsl-values=off,on";
if (mCameraId == "1")
outStr = "ae-bracket-hdr=Off;ae-bracket-hdr-values=Off,AE-Bracket;antibanding=auto;antibanding-values=off,60hz,50hz,auto;auto-dc-offset-mode=on;auto-dc-offset-mode-values=off,on;auto-exposure=center-weighted;auto-exposure-lock=false;auto-exposure-lock-supported=true;auto-exposure-values=frame-average,center-weighted,spot-metering,center-weighted,spot-metering-adv,center-weighted-adv;auto-hdr-supported=true;auto-whitebalance-lock=false;auto-whitebalance-lock-supported=true;avtimer=disable;background-proc=on;brightness-step=1;burst-max-fps=50;burst-status=off;burst-status-values=off,on;cache-video-buffers=disable;camera-mode=0;cds-mode-values=off,on,auto;chroma-flash=chroma-flash-off;chroma-flash-values=chroma-flash-off,chroma-flash-on;contrast=5;contrast-step=1;dbg-log-aec=off;dbg-log-aec-values=on,off;dbg-log-af=off;dbg-log-af-values=on,off;dbg-log-awb=off;dbg-log-awb-values=on,off;denoise=denoise-on;denoise-values=denoise-off,denoise-on;dis=disable;dis-values=enable,disable;effect=none;effect-values=none,mono,negative,solarize,sepia,posterize,whiteboard,blackboard,aqua,emboss,sketch,neon;exposure-compensation=0;exposure-compensation-step=0.166667;face-detection=off;face-detection-values=off,on;flash-mode=off;flash-mode-values=off,auto,on,torch;flip-mode-values=off,flip-v,flip-h,flip-vh;focal-length=2.448;focus-distances=Infinity,Infinity,Infinity;focus-mode=fixed;focus-mode-values=fixed;hdr-mode=hdr-mode-multiframe;hdr-mode-values=hdr-mode-multiframe;hdr-need-1x=false;hdr-need-1x-values=false,true;hfr-size-values=1280x720;histogram=disable;histogram-values=enable,disable;horizontal-view-angle=72.82;instant-aec-values=;instant-capture-values=;internal-restart=true;iso=auto;iso-values=auto,ISO_HJR,ISO50,ISO100,ISO200,ISO400,ISO800,ISO1600,ISO3200;jpeg-quality=95;jpeg-thumbnail-height=384;jpeg-thumbnail-quality=85;jpeg-thumbnail-size-values=512x384,512x288,0x0;jpeg-thumbnail-width=512;jsaudio=off;jsaudio-values=off,on;jsreplace=on;jsreplace-values=off,on;jsvideo=off;jsvideo-values=off,on;lensshade=enable;lensshade-values=enable,disable;long-shot=off;longshot-supported=true;luma-adaptation=3;manual-dc-offset=0;manual-dc-offset-max=0;manual-dc-offset-min=-40;manual-dc-offset-step=1;manual-exposure-modes=off,exp-time-priority,iso-priority,user-setting;manual-focus-modes=off;manual-wb-modes=off,color-temperature,rbgb-gains;max-brightness=6;max-contrast=10;max-exposure-compensation=12;max-exposure-time=521.395200;max-focus-pos-dac=1023;max-focus-pos-diopter=0;max-focus-pos-index=1023;max-focus-pos-ratio=100;max-iso=1979;max-num-detected-faces-hw=32;max-num-detected-faces-sw=32;max-num-focus-areas=0;max-num-metering-areas=1;max-saturation=10;max-sce-factor=100;max-sharpness=36;max-wb-cct=8000;max-wb-gain=4;max-zoom=90;mce=enable;mce-values=enable,disable;metering-areas=(0,0,0,0,0);min-brightness=0;min-contrast=0;min-exposure-compensation=-12;min-exposure-time=0.016802;min-focus-pos-dac=0;min-focus-pos-diopter=0;min-focus-pos-index=0;min-focus-pos-ratio=0;min-iso=59;min-saturation=0;min-sce-factor=-100;min-sharpness=0;min-wb-cct=2000;min-wb-gain=1;mot-barcodes-supported=false;mot-beauty=off;mot-beauty-level=5;mot-beauty-limitfps-need=false;mot-beauty-maxfps=22;mot-beauty-values=off;mot-max-still-fps=30;mot-mcas-mode=off;mot-mcas-mode-values=off;num-retro-burst-per-shutter=0;num-snaps-per-shutter=1;opti-zoom=opti-zoom-off;opti-zoom-values=opti-zoom-off,opti-zoom-on;picture-format=jpeg;picture-format-values=jpeg;picture-size=2592x1944;picture-size-values=2592x1944,2592x1458,1920x1080,1440x1080,1280x960,1280x720,720x480,640x480,352x288,320x240,176x144;preferred-preview-size-for-video=1920x1080;preview-flip=off;preview-format=yuv420sp;preview-format-values=yuv420sp,yuv420p;preview-fps-range=9000,30000;preview-fps-range-values=(15000,15000),(15000,20000),(20000,20000),(9000,30000),(30000,30000),(15000,30000),(24000,30000);preview-frame-rate=30;preview-frame-rate-values=9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30;preview-hist=preview-hist-off;preview-hist-values=preview-hist-off,preview-hist-on;preview-size=1920x1080;preview-size-values=1920x1080,1440x1080,1280x720,960x720,768x432,720x480,640x480,320x240,176x144;qc-camera-features=1011580159;qc-max-num-requested-faces=32;raw-size=2592x1944;rdi-mode=disable;rdi-mode-values=enable,disable;redeye-reduction=disable;redeye-reduction-values=enable,disable;saturation=5;saturation-step=1;sce-factor-step=10;scene-detect=off;scene-detect-values=off,on;scene-mode=auto;scene-mode-values=auto,hdr,auto_hdr;scene-selection=disable;secure-mode=disable;secure-mode-values=enable,disable;selectable-zone-af=auto;selectable-zone-af-values=auto,spot-metering,center-weighted,frame-average;sharpness=12;sharpness-step=6;skinToneEnhancement=0;skinToneEnhancement-values=enable,disable;smooth-zoom-supported=true;snapshot-burst-num=0;snapshot-picture-flip=off;still-more=still-more-off;still-more-values=still-more-off,still-more-on;supported-live-snapshot-sizes=2592x1944,2592x1458,1920x1080,1440x1080,1280x960,1280x720,1024x768,864x480,720x480,640x480,352x288,320x240;tintless=on;tintless-values=off,on;tnr-mode-values=off,on;touch-af-aec=touch-off;touch-af-aec-values=touch-off,touch-on;true-portrait-values=true-portrait-off,true-portrait-on;vertical-view-angle=57.9;video-batch-size=0;video-cds-mode-values=off,on,auto;video-flip=off;video-frame-format=android-opaque;video-hfr=off;video-hfr-values=120,off;video-hsr=off;video-rotation=0;video-rotation-values=0,90,180,270;video-size-values=1920x1080,1280x720,864x480,720x480,640x480,352x288,320x240,176x144;video-snapshot-supported=true;video-stabilization-supported=false;video-tnr-mode-values=off,on;visionfw=off;visionfw-values=off,on;whitebalance=auto;whitebalance-values=auto,incandescent,fluorescent,warm-fluorescent,daylight,cloudy-daylight,twilight,shade,manual;zoom=0;zoom-ratios=100,102,104,107,109,112,114,117,120,123,125,128,131,135,138,141,144,148,151,155,158,162,166,170,174,178,182,186,190,195,200,204,209,214,219,224,229,235,240,246,251,257,263,270,276,282,289,296,303,310,317,324,332,340,348,356,364,373,381,390,400,409,418,428,438,448,459,470,481,492,503,515,527,540,552,565,578,592,606,620,634,649,664,680,696,712,729,746,763,781,800;zoom-supported=true;zsl=on;zsl-hdr-supported=true;zsl-values=off,on";
_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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment