diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2019-07-02 07:41:24 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-07-02 07:41:24 +0000 |
| commit | 26f1b51bfbd5e8d2d2e55247a8bae49ccd52872d (patch) | |
| tree | 0d99225e22e2956cf075fcf48527d0e17e872c0f /camera/device/3.5/default/CameraDeviceSession.cpp | |
| parent | 3adfddb29552dbf79387c23e10a9960d1f9c2f79 (diff) | |
| parent | 8b76f6692c718c21272d3585541b72fed7ac93f0 (diff) | |
Merge "DO NOT MERGE - Merge qt-dev-plus-aosp-without-vendor (5699924) into stage-aosp-master" into stage-aosp-master
Diffstat (limited to 'camera/device/3.5/default/CameraDeviceSession.cpp')
| -rw-r--r-- | camera/device/3.5/default/CameraDeviceSession.cpp | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp new file mode 100644 index 0000000000..44d067d475 --- /dev/null +++ b/camera/device/3.5/default/CameraDeviceSession.cpp @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2018 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 "CamDevSession@3.5-impl" +#define ATRACE_TAG ATRACE_TAG_CAMERA +#include <android/log.h> + +#include <vector> +#include <utils/Trace.h> +#include "CameraDeviceSession.h" + +namespace android { +namespace hardware { +namespace camera { +namespace device { +namespace V3_5 { +namespace implementation { + +CameraDeviceSession::CameraDeviceSession( + camera3_device_t* device, + const camera_metadata_t* deviceInfo, + const sp<V3_2::ICameraDeviceCallback>& callback) : + V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) { + + mCallback_3_5 = nullptr; + + auto castResult = ICameraDeviceCallback::castFrom(callback); + if (castResult.isOk()) { + sp<ICameraDeviceCallback> callback3_5 = castResult; + if (callback3_5 != nullptr) { + 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; + } + } + } +} + +CameraDeviceSession::~CameraDeviceSession() { +} + +Return<void> CameraDeviceSession::configureStreams_3_5( + const StreamConfiguration& requestedConfiguration, + ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) { + configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb, + requestedConfiguration.streamConfigCounter, false /*useOverriddenFields*/); + return Void(); +} + +Return<void> CameraDeviceSession::signalStreamFlush( + const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) { + if (mDevice->ops->signal_stream_flush == nullptr) { + return Void(); + } + + uint32_t currentCounter = 0; + { + Mutex::Autolock _l(mStreamConfigCounterLock); + currentCounter = mStreamConfigCounter; + } + + if (streamConfigCounter < currentCounter) { + ALOGV("%s: streamConfigCounter %d is stale (current %d), skipping signal_stream_flush call", + __FUNCTION__, streamConfigCounter, mStreamConfigCounter); + return Void(); + } + + 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]; + } + } + + mDevice->ops->signal_stream_flush(mDevice, 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(); + + switch (status) { + case BufferRequestStatus::FAILED_CONFIGURING: + return CAMERA3_BUF_REQ_FAILED_CONFIGURING; + case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS: + return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS; + default: + break; // Other status Handled by following code + } + + if (status != BufferRequestStatus::OK && status != BufferRequestStatus::FAILED_PARTIAL && + status != BufferRequestStatus::FAILED_UNKNOWN) { + ALOGE("%s: unknown buffer request error code %d", __FUNCTION__, status); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + // Only OK, FAILED_PARTIAL and FAILED_UNKNOWN reaches here + 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; + } + + *num_returned_buf_reqs = num_buffer_reqs; + 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; + } + + // Handle failed streams + for (size_t i = 0; i < num_buffer_reqs; i++) { + if (bufRets[i].val.getDiscriminator() == 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()); + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + } + } + + if (status == BufferRequestStatus::FAILED_UNKNOWN) { + return CAMERA3_BUF_REQ_FAILED_UNKNOWN; + } + + // Only BufferRequestStatus::OK and BufferRequestStatus::FAILED_PARTIAL reaches here + std::vector<int> importedFences; + std::vector<std::pair<buffer_handle_t, int>> importedBuffers; + for (size_t i = 0; i < num_buffer_reqs; i++) { + if (bufRets[i].val.getDiscriminator() != + StreamBuffersVal::hidl_discriminator::buffers) { + continue; + } + int streamId = bufRets[i].streamId; + const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers(); + camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers; + returned_buf_reqs[i].num_output_buffers = hBufs.size(); + 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); + // Buffer import should never fail - restart HAL since something is very wrong. + LOG_ALWAYS_FATAL_IF(s != Status::OK, + "%s: import stream %d bufferId %" PRIu64 " failed!", + __FUNCTION__, streamId, hBuf.bufferId); + + pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId); + importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId)); + + bool succ = sHandleImporter.importFence(hBuf.acquireFence, outBuf.acquire_fence); + // Fence import should never fail - restart HAL since something is very wrong. + LOG_ALWAYS_FATAL_IF(!succ, + "%s: stream %d bufferId %" PRIu64 "acquire fence is invalid", + __FUNCTION__, streamId, hBuf.bufferId); + 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; + } + + return (status == BufferRequestStatus::OK) ? + CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL; +} + +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); +} + +Return<void> CameraDeviceSession::isReconfigurationRequired( + const V3_2::CameraMetadata& oldSessionParams, const V3_2::CameraMetadata& newSessionParams, + ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) { + if (mDevice->ops->is_reconfiguration_required != nullptr) { + const camera_metadata_t *oldParams, *newParams; + V3_2::implementation::convertFromHidl(oldSessionParams, &oldParams); + V3_2::implementation::convertFromHidl(newSessionParams, &newParams); + auto ret = mDevice->ops->is_reconfiguration_required(mDevice, oldParams, newParams); + switch (ret) { + case 0: + _hidl_cb(Status::OK, true); + break; + case -EINVAL: + _hidl_cb(Status::OK, false); + break; + case -ENOSYS: + _hidl_cb(Status::METHOD_NOT_SUPPORTED, true); + break; + default: + _hidl_cb(Status::INTERNAL_ERROR, true); + break; + }; + } else { + _hidl_cb(Status::METHOD_NOT_SUPPORTED, true); + } + + return Void(); +} + +} // namespace implementation +} // namespace V3_5 +} // namespace device +} // namespace camera +} // namespace hardware +} // namespace android |
