mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Camera: default implementation of device 1.0
Also some updates to HIDL interface:
- Add releaseRecordingFrameHandle to ICameraDevice
for native handle metadata recording mode
- Add handleCallbackTimestamp to ICameraDevieCallback
for native handle metadata recording mode
- Add missing face detection metadata to
ICameraDeviceCallback::dataCallback
- Instead of passing native handle, pass buffer ID
in dequeueBuffer/enqueueBuffer/cancelBuffer in
ICameraDevicePreviewCallback
- Add CameraFrameMetadata in types.hal for face
metadata
Test: Camera CTS passing (except FlashLightTest) on Angler
Bug: 30985004
Change-Id: Idf72a4b5f4c934845ac698f0b13536608ffd0100
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
|
||||
190
camera/common/1.0/default/HandleImporter.cpp
Normal file
190
camera/common/1.0/default/HandleImporter.cpp
Normal file
@@ -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
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <hardware/camera.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include "CameraMetadata.h"
|
||||
|
||||
|
||||
73
camera/common/1.0/default/include/HandleImporter.h
Normal file
73
camera/common/1.0/default/include/HandleImporter.h
Normal file
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
27
camera/device/1.0/default/Android.bp
Normal file
27
camera/device/1.0/default/Android.bp
Normal file
@@ -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: ["."]
|
||||
}
|
||||
|
||||
948
camera/device/1.0/default/CameraDevice.cpp
Normal file
948
camera/device/1.0/default/CameraDevice.cpp
Normal file
@@ -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
|
||||
224
camera/device/1.0/default/CameraDevice_1_0.h
Normal file
224
camera/device/1.0/default/CameraDevice_1_0.h
Normal file
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user