Use fmq for camera capture result.
Test: camera works.
Bug: 35788245 [Treble] Pass camera metadata using shared memory
Change-Id: I344212cfd80f6df4e5aec01ec3f12f1ee9bb71c8
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 47c7e3f..ab077f0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -200,20 +200,36 @@
}
std::shared_ptr<RequestMetadataQueue> queue;
- auto getQueueRet = session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
- queue = std::make_shared<RequestMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
- ALOGW("HAL returns empty request metadata fmq, not use it");
- queue = nullptr;
- // don't use the queue onwards.
- }
- });
- if (!getQueueRet.isOk()) {
- ALOGW("Transaction error when getting request metadata fmq: %s, not use it",
- getQueueRet.description().c_str());
+ auto requestQueueRet = session->getCaptureRequestMetadataQueue(
+ [&queue](const auto& descriptor) {
+ queue = std::make_shared<RequestMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty request metadata fmq, not use it");
+ queue = nullptr;
+ // don't use the queue onwards.
+ }
+ });
+ if (!requestQueueRet.isOk()) {
+ ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
+ requestQueueRet.description().c_str());
queue = nullptr;
// Don't use the queue onwards.
}
+ auto resultQueueRet = session->getCaptureResultMetadataQueue(
+ [&queue = mResultMetadataQueue](const auto& descriptor) {
+ queue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty result metadata fmq, not use it");
+ queue = nullptr;
+ // Don't use the queue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+ resultQueueRet.description().c_str());
+ mResultMetadataQueue = nullptr;
+ // Don't use the queue onwards.
+ }
// TODO: camera service will absorb 3_2/3_3/3_4 differences in the future
// for now use 3_4 to keep legacy devices working
@@ -954,24 +970,56 @@
return res;
}
-
+// Only one processCaptureResult should be called at a time, so
+// the locks won't block. The locks are present here simply to enforce this.
hardware::Return<void> Camera3Device::processCaptureResult(
const hardware::hidl_vec<
hardware::camera::device::V3_2::CaptureResult>& results) {
- for (const auto& result : results) {
- processOneCaptureResult(result);
+
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ // This should never happen; it indicates a wrong client implementation
+ // that doesn't follow the contract. But, we can be tolerant here.
+ ALOGE("%s: callback overlapped! waiting 1s...",
+ __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, dropping results",
+ __FUNCTION__);
+ // really don't know what to do, so bail out.
+ return hardware::Void();
+ }
}
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(result);
+ }
+ mProcessCaptureResultLock.unlock();
return hardware::Void();
}
-void Camera3Device::processOneCaptureResult(
+void Camera3Device::processOneCaptureResultLocked(
const hardware::camera::device::V3_2::CaptureResult& result) {
camera3_capture_result r;
status_t res;
r.frame_number = result.frameNumber;
- if (result.result.size() != 0) {
- r.result = reinterpret_cast<const camera_metadata_t*>(result.result.data());
- size_t expected_metadata_size = result.result.size();
+
+ hardware::camera::device::V3_2::CameraMetadata resultMetadata;
+ if (result.fmqResultSize > 0) {
+ resultMetadata.resize(result.fmqResultSize);
+ if (mResultMetadataQueue == nullptr) {
+ return; // logged in initialize()
+ }
+ if (!mResultMetadataQueue->read(resultMetadata.data(), result.fmqResultSize)) {
+ ALOGE("%s: Frame %d: Cannot read camera metadata from fmq, size = %" PRIu64,
+ __FUNCTION__, result.frameNumber, result.fmqResultSize);
+ return;
+ }
+ } else {
+ resultMetadata.setToExternal(const_cast<uint8_t *>(result.result.data()),
+ result.result.size());
+ }
+
+ if (resultMetadata.size() != 0) {
+ r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+ size_t expected_metadata_size = resultMetadata.size();
if ((res = validate_camera_metadata_structure(r.result, &expected_metadata_size)) != OK) {
ALOGE("%s: Frame %d: Invalid camera metadata received by camera service from HAL: %s (%d)",
__FUNCTION__, result.frameNumber, strerror(-res), res);