Camera: support libhardware camera device 3.6
Add buffer management API support.
Test: VTS to be written. Need Pixel device impl to verify.
Bug: 120986771
Change-Id: Icdbc621f8cd17aa0868d3ac361867c44793a268c
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index fd785df..f2d7a47 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -44,13 +44,15 @@
static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
HandleImporter CameraDeviceSession::sHandleImporter;
+buffer_handle_t CameraDeviceSession::sEmptyBuffer = nullptr;
+
const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
CameraDeviceSession::CameraDeviceSession(
camera3_device_t* device,
const camera_metadata_t* deviceInfo,
const sp<ICameraDeviceCallback>& callback) :
- camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
+ camera3_callback_ops({&sProcessCaptureResult, &sNotify, nullptr, nullptr}),
mDevice(device),
mDeviceVersion(device->common.version),
mFreeBufEarly(shouldFreeBufEarly()),
@@ -246,10 +248,50 @@
}
}
+Status CameraDeviceSession::importBuffer(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf) {
+
+ if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) {
+ if (allowEmptyBuf) {
+ *outBufPtr = &sEmptyBuffer;
+ return Status::OK;
+ } else {
+ ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ }
+
+ Mutex::Autolock _l(mInflightLock);
+ CirculatingBuffers& cbs = mCirculatingBuffers[streamId];
+ if (cbs.count(bufId) == 0) {
+ // Register a newly seen buffer
+ buffer_handle_t importedBuf = buf;
+ sHandleImporter.importBuffer(importedBuf);
+ if (importedBuf == nullptr) {
+ ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId);
+ return Status::INTERNAL_ERROR;
+ } else {
+ cbs[bufId] = importedBuf;
+ }
+ }
+ *outBufPtr = &cbs[bufId];
+ return Status::OK;
+}
+
Status CameraDeviceSession::importRequest(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
hidl_vec<int>& allFences) {
+ return importRequestImpl(request, allBufPtrs, allFences);
+}
+
+Status CameraDeviceSession::importRequestImpl(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences,
+ bool allowEmptyBuf) {
bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
request.inputBuffer.bufferId != 0);
size_t numOutputBufs = request.outputBuffers.size();
@@ -277,25 +319,15 @@
}
for (size_t i = 0; i < numBufs; i++) {
- buffer_handle_t buf = allBufs[i];
- uint64_t bufId = allBufIds[i];
- CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
- if (cbs.count(bufId) == 0) {
- if (buf == nullptr) {
- ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
- return Status::ILLEGAL_ARGUMENT;
- }
- // Register a newly seen buffer
- buffer_handle_t importedBuf = buf;
- sHandleImporter.importBuffer(importedBuf);
- if (importedBuf == nullptr) {
- ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
- return Status::INTERNAL_ERROR;
- } else {
- cbs[bufId] = importedBuf;
- }
+ Status st = importBuffer(
+ streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i],
+ // Disallow empty buf for input stream, otherwise follow
+ // the allowEmptyBuf argument.
+ (hasInputBuf && i == numOutputBufs) ? false : allowEmptyBuf);
+ if (st != Status::OK) {
+ // Detailed error logs printed in importBuffer
+ return st;
}
- allBufPtrs[i] = &cbs[bufId];
}
// All buffers are imported. Now validate output buffer acquire fences
@@ -1271,18 +1303,26 @@
ATRACE_END();
// free all imported buffers
+ Mutex::Autolock _l(mInflightLock);
for(auto& pair : mCirculatingBuffers) {
CirculatingBuffers& buffers = pair.second;
for (auto& p2 : buffers) {
sHandleImporter.freeBuffer(p2.second);
}
+ buffers.clear();
}
+ mCirculatingBuffers.clear();
mClosed = true;
}
return Void();
}
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t&, int) {
+ // No need to fill in bufferId by default
+ return BUFFER_ID_NO_BUFFER;
+}
+
status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result,
const camera3_capture_result *hal_result) {
uint32_t frameNumber = hal_result->frame_number;
@@ -1396,6 +1436,14 @@
result.outputBuffers[i].streamId =
static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
result.outputBuffers[i].buffer = nullptr;
+ if (hal_result->output_buffers[i].buffer != nullptr) {
+ result.outputBuffers[i].bufferId = getCapResultBufferId(
+ *(hal_result->output_buffers[i].buffer),
+ result.outputBuffers[i].streamId);
+ } else {
+ result.outputBuffers[i].bufferId = 0;
+ }
+
result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
// skip acquire fence since it's of no use to camera service
if (hal_result->output_buffers[i].release_fence != -1) {
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index bcee259..a96c245 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -161,6 +161,7 @@
std::map<uint32_t, bool> mInflightRawBoostPresent;
::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
+ static const uint64_t BUFFER_ID_NO_BUFFER = 0;
// buffers currently ciculating between HAL and camera service
// key: bufferId sent via HIDL interface
// value: imported buffer_handle_t
@@ -171,6 +172,7 @@
std::map<int, CirculatingBuffers> mCirculatingBuffers;
static HandleImporter sHandleImporter;
+ static buffer_handle_t sEmptyBuffer;
bool mInitFail;
bool mFirstRequest = false;
@@ -301,11 +303,23 @@
Status initStatus() const;
// Validate and import request's input buffer and acquire fence
- Status importRequest(
+ virtual Status importRequest(
const CaptureRequest& request,
hidl_vec<buffer_handle_t*>& allBufPtrs,
hidl_vec<int>& allFences);
+ Status importRequestImpl(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences,
+ // Optional argument for ICameraDeviceSession@3.5 impl
+ bool allowEmptyBuf = false);
+
+ Status importBuffer(int32_t streamId,
+ uint64_t bufId, buffer_handle_t buf,
+ /*out*/buffer_handle_t** outBufPtr,
+ bool allowEmptyBuf);
+
static void cleanupInflightFences(
hidl_vec<int>& allFences, size_t numFences);
@@ -332,6 +346,11 @@
static callbacks_process_capture_result_t sProcessCaptureResult;
static callbacks_notify_t sNotify;
+ // By default camera service uses frameNumber/streamId pair to retrieve the buffer that
+ // was sent to HAL. Override this implementation if HAL is using buffers from buffer management
+ // APIs to send output buffer.
+ virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId);
+
status_t constructCaptureResult(CaptureResult& result,
const camera3_capture_result *hal_result);
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index f2e031c..e52577c 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -87,6 +87,14 @@
Return<void> CameraDeviceSession::configureStreams_3_4(
const StreamConfiguration& requestedConfiguration,
ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
+ configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
+ return Void();
+}
+
+void CameraDeviceSession::configureStreams_3_4_Impl(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+ uint32_t streamConfigCounter) {
Status status = initStatus();
HalStreamConfiguration outStreams;
@@ -97,7 +105,7 @@
ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
__FUNCTION__);
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
}
}
@@ -109,7 +117,7 @@
ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
__FUNCTION__, mInflightBuffers.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (!mInflightAETriggerOverrides.empty()) {
@@ -117,7 +125,7 @@
" trigger overrides!", __FUNCTION__,
mInflightAETriggerOverrides.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (!mInflightRawBoostPresent.empty()) {
@@ -125,12 +133,12 @@
" boost overrides!", __FUNCTION__,
mInflightRawBoostPresent.size());
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
if (status != Status::OK) {
_hidl_cb(status, outStreams);
- return Void();
+ return;
}
const camera_metadata_t *paramBuffer = nullptr;
@@ -139,11 +147,12 @@
}
camera3_stream_configuration_t stream_list{};
+ stream_list.stream_configuration_counter = streamConfigCounter;
hidl_vec<camera3_stream_t*> streams;
stream_list.session_parameters = paramBuffer;
if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
_hidl_cb(Status::INTERNAL_ERROR, outStreams);
- return Void();
+ return;
}
ATRACE_BEGIN("camera3->configure_streams");
@@ -168,7 +177,7 @@
}
_hidl_cb(status, outStreams);
- return Void();
+ return;
}
bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index fdc8a5a..00500b1 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -87,6 +87,12 @@
void postProcessConfigurationFailureLocked_3_4(
const StreamConfiguration& requestedConfiguration);
+ void configureStreams_3_4_Impl(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+ // Optional argument for ICameraDeviceSession@3.5 impl
+ uint32_t streamConfigCounter = 0);
+
Return<void> processCaptureRequest_3_4(
const hidl_vec<V3_4::CaptureRequest>& requests,
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 963893a..0770f04 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -15,8 +15,10 @@
*/
#define LOG_TAG "CamDevSession@3.5-impl"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <android/log.h>
+#include <vector>
#include <utils/Trace.h>
#include "CameraDeviceSession.h"
@@ -33,13 +35,26 @@
const sp<V3_2::ICameraDeviceCallback>& callback) :
V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
- mHasCallback_3_5 = false;
+ mCallback_3_5 = nullptr;
auto castResult = ICameraDeviceCallback::castFrom(callback);
if (castResult.isOk()) {
sp<ICameraDeviceCallback> callback3_5 = castResult;
if (callback3_5 != nullptr) {
- mHasCallback_3_5 = true;
+ mCallback_3_5 = callback3_5;
+ }
+ }
+
+ if (mCallback_3_5 != nullptr) {
+ camera_metadata_entry bufMgrVersion = mDeviceInfo.find(
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+ if (bufMgrVersion.count > 0) {
+ mSupportBufMgr = (bufMgrVersion.data.u8[0] ==
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+ if (mSupportBufMgr) {
+ request_stream_buffers = sRequestStreamBuffers;
+ return_stream_buffers = sReturnStreamBuffers;
+ }
}
}
}
@@ -50,14 +65,297 @@
Return<void> CameraDeviceSession::configureStreams_3_5(
const StreamConfiguration& requestedConfiguration,
ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) {
- return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+ configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
+ requestedConfiguration.streamConfigCounter);
+ return Void();
}
Return<void> CameraDeviceSession::signalStreamFlush(
- const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+ const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) {
+ std::vector<camera3_stream_t*> streams(streamIds.size());
+ {
+ Mutex::Autolock _l(mInflightLock);
+ for (size_t i = 0; i < streamIds.size(); i++) {
+ int32_t id = streamIds[i];
+ if (mStreamMap.count(id) == 0) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, id);
+ return Void();
+ }
+ streams[i] = &mStreamMap[id];
+ }
+ }
+ if (mDevice->ops->signal_stream_flush != nullptr) {
+ mDevice->ops->signal_stream_flush(mDevice,
+ streamConfigCounter, streams.size(), streams.data());
+ }
return Void();
}
+Status CameraDeviceSession::importRequest(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) {
+ if (mSupportBufMgr) {
+ return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
+ }
+ return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
+}
+
+void CameraDeviceSession::pushBufferId(
+ const buffer_handle_t& buf, uint64_t bufferId, int streamId) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+ // emplace will return existing entry if there is one.
+ auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{});
+ BufferIdMap& bIdMap = pair.first->second;
+ bIdMap[buf] = bufferId;
+}
+
+uint64_t CameraDeviceSession::popBufferId(
+ const buffer_handle_t& buf, int streamId) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+ auto streamIt = mBufferIdMaps.find(streamId);
+ if (streamIt == mBufferIdMaps.end()) {
+ return BUFFER_ID_NO_BUFFER;
+ }
+ BufferIdMap& bIdMap = streamIt->second;
+ auto it = bIdMap.find(buf);
+ if (it == bIdMap.end()) {
+ return BUFFER_ID_NO_BUFFER;
+ }
+ uint64_t bufId = it->second;
+ bIdMap.erase(it);
+ if (bIdMap.empty()) {
+ mBufferIdMaps.erase(streamIt);
+ }
+ return bufId;
+}
+
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) {
+ if (mSupportBufMgr) {
+ return popBufferId(buf, streamId);
+ }
+ return BUFFER_ID_NO_BUFFER;
+}
+
+Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) {
+ Mutex::Autolock _l(mInflightLock);
+ if (mStreamMap.count(streamId) == 0) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId);
+ return nullptr;
+ }
+ return &mStreamMap[streamId];
+}
+
+void CameraDeviceSession::cleanupInflightBufferFences(
+ std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs) {
+ hidl_vec<int> hFences = fences;
+ cleanupInflightFences(hFences, fences.size());
+ for (auto& p : bufs) {
+ popBufferId(p.first, p.second);
+ }
+}
+
+camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers(
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+ ATRACE_CALL();
+ *num_returned_buf_reqs = 0;
+ hidl_vec<BufferRequest> hBufReqs(num_buffer_reqs);
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ hBufReqs[i].streamId =
+ static_cast<Camera3Stream*>(buffer_reqs[i].stream)->mId;
+ hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested;
+ }
+
+ ATRACE_BEGIN("HIDL requestStreamBuffers");
+ BufferRequestStatus status;
+ hidl_vec<StreamBufferRet> bufRets;
+ auto err = mCallback_3_5->requestStreamBuffers(hBufReqs,
+ [&status, &bufRets]
+ (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
+ status = s;
+ bufRets = std::move(rets);
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ ATRACE_END();
+
+ if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
+ if (bufRets.size() != num_buffer_reqs) {
+ ALOGE("%s: expect %d buffer requests returned, only got %zu",
+ __FUNCTION__, num_buffer_reqs, bufRets.size());
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ // maybe we can query all streams in one call to avoid frequent locking device here?
+ Camera3Stream* stream = getStreamPointer(bufRets[i].streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ returned_buf_reqs[i].stream = stream;
+ }
+
+ std::vector<int> importedFences;
+ std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
+ for (size_t i = 0; i < num_buffer_reqs; i++) {
+ int streamId = bufRets[i].streamId;
+ switch (bufRets[i].val.getDiscriminator()) {
+ case StreamBuffersVal::hidl_discriminator::error:
+ returned_buf_reqs[i].num_output_buffers = 0;
+ switch (bufRets[i].val.error()) {
+ case StreamBufferRequestError::NO_BUFFER_AVAILABLE:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE;
+ break;
+ case StreamBufferRequestError::MAX_BUFFER_EXCEEDED:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED;
+ break;
+ case StreamBufferRequestError::STREAM_DISCONNECTED:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED;
+ break;
+ case StreamBufferRequestError::UNKNOWN_ERROR:
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR;
+ break;
+ default:
+ ALOGE("%s: Unknown StreamBufferRequestError %d",
+ __FUNCTION__, bufRets[i].val.error());
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ break;
+ case StreamBuffersVal::hidl_discriminator::buffers: {
+ const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers();
+ camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers;
+ for (size_t b = 0; b < hBufs.size(); b++) {
+ const StreamBuffer& hBuf = hBufs[b];
+ camera3_stream_buffer_t& outBuf = outBufs[b];
+ // maybe add importBuffers API to avoid frequent locking device?
+ Status s = importBuffer(streamId,
+ hBuf.bufferId, hBuf.buffer.getNativeHandle(),
+ /*out*/&(outBuf.buffer),
+ /*allowEmptyBuf*/false);
+ if (s != Status::OK) {
+ ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!",
+ __FUNCTION__, streamId, hBuf.bufferId);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ // Buffer import should never fail - restart HAL since something is very
+ // wrong.
+ assert(false);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+
+ pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId);
+ importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId));
+
+ if (!sHandleImporter.importFence(
+ hBuf.acquireFence,
+ outBuf.acquire_fence)) {
+ ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid",
+ __FUNCTION__, streamId, hBuf.bufferId);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ importedFences.push_back(outBuf.acquire_fence);
+ outBuf.stream = returned_buf_reqs[i].stream;
+ outBuf.status = CAMERA3_BUFFER_STATUS_OK;
+ outBuf.release_fence = -1;
+ }
+ returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK;
+ } break;
+ default:
+ ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__);
+ cleanupInflightBufferFences(importedFences, importedBuffers);
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+ }
+
+ *num_returned_buf_reqs = num_buffer_reqs;
+
+ return (status == BufferRequestStatus::OK) ?
+ CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
+ }
+
+ switch (status) {
+ case BufferRequestStatus::FAILED_CONFIGURING:
+ return CAMERA3_BUF_REQ_FAILED_CONFIGURING;
+ case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS:
+ return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+ case BufferRequestStatus::FAILED_UNKNOWN:
+ default:
+ return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+ }
+}
+
+void CameraDeviceSession::returnStreamBuffers(
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers) {
+ ATRACE_CALL();
+ hidl_vec<StreamBuffer> hBufs(num_buffers);
+
+ for (size_t i = 0; i < num_buffers; i++) {
+ hBufs[i].streamId =
+ static_cast<Camera3Stream*>(buffers[i]->stream)->mId;
+ hBufs[i].buffer = nullptr; // use bufferId
+ hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId);
+ if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) {
+ ALOGE("%s: unknown buffer is returned to stream %d",
+ __FUNCTION__, hBufs[i].streamId);
+ }
+ // ERROR since the buffer is not for application to consume
+ hBufs[i].status = BufferStatus::ERROR;
+ // skip acquire fence since it's of no use to camera service
+ if (buffers[i]->release_fence != -1) {
+ native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+ handle->data[0] = buffers[i]->release_fence;
+ hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+ }
+ }
+
+ mCallback_3_5->returnStreamBuffers(hBufs);
+ return;
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers(
+ const struct camera3_callback_ops *cb,
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr ||
+ returned_buf_reqs == nullptr) {
+ ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p",
+ __FUNCTION__, num_buffer_reqs, buffer_reqs,
+ num_returned_buf_reqs, returned_buf_reqs);
+ return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+ }
+
+ return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs,
+ num_returned_buf_reqs, returned_buf_reqs);
+}
+
+void CameraDeviceSession::sReturnStreamBuffers(
+ const struct camera3_callback_ops *cb,
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers) {
+ CameraDeviceSession *d =
+ const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+ d->returnStreamBuffers(num_buffers, buffers);
+}
+
} // namespace implementation
} // namespace V3_5
} // namespace device
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
index ec34769..4f7284c 100644
--- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -21,6 +21,7 @@
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
#include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+#include <unordered_map>
namespace android {
namespace hardware {
@@ -30,11 +31,14 @@
namespace implementation {
using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
using ::android::hardware::camera::device::V3_5::StreamConfiguration;
using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
using ::android::hardware::Return;
@@ -44,6 +48,25 @@
using ::android::sp;
using ::android::Mutex;
+
+/**
+ * Function pointer types with C calling convention to
+ * use for HAL callback functions.
+ */
+extern "C" {
+ typedef camera3_buffer_request_status_t (callbacks_request_stream_buffer_t)(
+ const struct camera3_callback_ops *,
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+ typedef void (callbacks_return_stream_buffer_t)(
+ const struct camera3_callback_ops *,
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers);
+}
+
struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
CameraDeviceSession(camera3_device_t*,
@@ -62,12 +85,85 @@
ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
Return<void> signalStreamFlush(
- const hidl_vec<int32_t>& requests,
+ const hidl_vec<int32_t>& streamIds,
uint32_t streamConfigCounter);
+ virtual Status importRequest(
+ const CaptureRequest& request,
+ hidl_vec<buffer_handle_t*>& allBufPtrs,
+ hidl_vec<int>& allFences) override;
- // Whether this camera device session is created with version 3.5 callback.
- bool mHasCallback_3_5;
+ /**
+ * Static callback forwarding methods from HAL to instance
+ */
+ static callbacks_request_stream_buffer_t sRequestStreamBuffers;
+ static callbacks_return_stream_buffer_t sReturnStreamBuffers;
+
+ camera3_buffer_request_status_t requestStreamBuffers(
+ uint32_t num_buffer_reqs,
+ const camera3_buffer_request_t *buffer_reqs,
+ /*out*/uint32_t *num_returned_buf_reqs,
+ /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+ void returnStreamBuffers(
+ uint32_t num_buffers,
+ const camera3_stream_buffer_t* const* buffers);
+
+ struct BufferHasher {
+ size_t operator()(const buffer_handle_t& buf) const {
+ if (buf == nullptr)
+ return 0;
+
+ size_t result = 1;
+ result = 31 * result + buf->numFds;
+ for (int i = 0; i < buf->numFds; i++) {
+ result = 31 * result + buf->data[i];
+ }
+ return result;
+ }
+ };
+
+ struct BufferComparator {
+ bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+ if (buf1->numFds == buf2->numFds) {
+ for (int i = 0; i < buf1->numFds; i++) {
+ if (buf1->data[i] != buf2->data[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ Camera3Stream* getStreamPointer(int32_t streamId);
+
+ // Register buffer to mBufferIdMaps so we can find corresponding bufferId
+ // when the buffer is returned to camera service
+ void pushBufferId(const buffer_handle_t& buf, uint64_t bufferId, int streamId);
+
+ // Method to pop buffer's bufferId from mBufferIdMaps
+ // BUFFER_ID_NO_BUFFER is returned if no matching buffer is found
+ uint64_t popBufferId(const buffer_handle_t& buf, int streamId);
+
+ // Method to cleanup imported buffer/fences if requestStreamBuffers fails half way
+ void cleanupInflightBufferFences(
+ std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs);
+
+ // Overrides the default constructCaptureResult behavior for buffer management APIs
+ virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId) override;
+
+ std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
+ typedef std::unordered_map<const buffer_handle_t, uint64_t,
+ BufferHasher, BufferComparator> BufferIdMap;
+ // stream ID -> per stream buffer ID map for buffers coming from requestStreamBuffers API
+ // Entries are created during requestStreamBuffers when a stream first request a buffer, and
+ // deleted in returnStreamBuffers/processCaptureResult* when all buffers are returned
+ std::unordered_map<int, BufferIdMap> mBufferIdMaps;
+
+ sp<ICameraDeviceCallback> mCallback_3_5;
+ bool mSupportBufMgr;
private:
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 488b9af..30f2bfb 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -41,11 +41,8 @@
const char *kExternalProviderName = "external/0";
// "device@<version>/legacy/<id>"
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
-const char *kHAL3_2 = "3.2";
-const char *kHAL3_3 = "3.3";
const char *kHAL3_4 = "3.4";
const char *kHAL3_5 = "3.5";
-const char *kHAL1_0 = "1.0";
const int kMaxCameraDeviceNameLen = 128;
const int kMaxCameraIdLen = 16;
@@ -222,22 +219,6 @@
return cameraId;
}
-int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) {
- std::string deviceVersion;
- bool match = matchDeviceName(deviceName, &deviceVersion, nullptr);
- if (!match) {
- return -1;
- }
- if (deviceVersion == kHAL3_3) {
- return CAMERA_DEVICE_API_VERSION_3_3;
- } else if (deviceVersion == kHAL3_2) {
- return CAMERA_DEVICE_API_VERSION_3_2;
- } else if (deviceVersion == kHAL1_0) {
- return CAMERA_DEVICE_API_VERSION_1_0;
- }
- return 0;
-}
-
std::string CameraProvider::getHidlDeviceName(
std::string cameraId, int deviceVersion) {
// Maybe consider create a version check method and SortedVec to speed up?
@@ -245,9 +226,16 @@
deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 &&
deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 &&
deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 &&
- deviceVersion != CAMERA_DEVICE_API_VERSION_3_5) {
+ deviceVersion != CAMERA_DEVICE_API_VERSION_3_5 &&
+ deviceVersion != CAMERA_DEVICE_API_VERSION_3_6) {
return hidl_string("");
}
+
+ // Supported combinations:
+ // CAMERA_DEVICE_API_VERSION_1_0 -> ICameraDevice@1.0
+ // CAMERA_DEVICE_API_VERSION_3_[2-4] -> ICameraDevice@[3.2|3.3]
+ // CAMERA_DEVICE_API_VERSION_3_5 + CAMERA_MODULE_API_VERSION_2_4 -> ICameraDevice@3.4
+ // CAMERA_DEVICE_API_VERSION_3_[5-6] + CAMERA_MODULE_API_VERSION_2_5 -> ICameraDevice@3.5
bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0;
int versionMajor = isV1 ? 1 : 3;
int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
@@ -257,6 +245,8 @@
} else {
versionMinor = 4;
}
+ } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) {
+ versionMinor = 5;
}
char deviceName[kMaxCameraDeviceNameLen];
snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
@@ -356,7 +346,8 @@
// device_version undefined in CAMERA_MODULE_API_VERSION_1_0,
// All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible
- if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
+ uint16_t moduleVersion = mModule->getModuleApiVersion();
+ if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) {
// Verify the device version is in the supported range
switch (info.device_version) {
case CAMERA_DEVICE_API_VERSION_1_0:
@@ -366,6 +357,20 @@
case CAMERA_DEVICE_API_VERSION_3_5:
// in support
break;
+ case CAMERA_DEVICE_API_VERSION_3_6:
+ /**
+ * ICameraDevice@3.5 contains APIs from both
+ * CAMERA_DEVICE_API_VERSION_3_6 and CAMERA_MODULE_API_VERSION_2_5
+ * so we require HALs to uprev both for simplified supported combinations.
+ * HAL can still opt in individual new APIs indepedently.
+ */
+ if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) {
+ ALOGE("%s: Device %d has unsupported version combination:"
+ "HAL version %x and module version %x",
+ __FUNCTION__, id, info.device_version, moduleVersion);
+ return NO_INIT;
+ }
+ break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
@@ -552,10 +557,11 @@
return Void();
}
- // ICameraDevice 3.4 or upper
sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl;
+
+ // ICameraDevice 3.4 or upper
if (deviceVersion >= kHAL3_4) {
- ALOGV("Constructing v3.4 camera device");
+ ALOGV("Constructing v3.4+ camera device");
if (deviceVersion == kHAL3_4) {
deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
index 0f0959f..10e9b0d 100644
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -98,7 +98,6 @@
// extract legacy camera ID/device version from a HIDL device name
static std::string getLegacyCameraId(const hidl_string& deviceName);
- static int getCameraDeviceVersion(const hidl_string& deviceName);
// convert conventional HAL status to HIDL Status
static Status getHidlStatus(int);