/* * 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 #include #include #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& callback) : V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) { mCallback_3_5 = nullptr; auto castResult = ICameraDeviceCallback::castFrom(callback); if (castResult.isOk()) { sp 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 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 CameraDeviceSession::signalStreamFlush( const hidl_vec& 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 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& allBufPtrs, hidl_vec& 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 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 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& fences, std::vector>& bufs) { hidl_vec 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 hBufReqs(num_buffer_reqs); for (size_t i = 0; i < num_buffer_reqs; i++) { hBufReqs[i].streamId = static_cast(buffer_reqs[i].stream)->mId; hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested; } ATRACE_BEGIN("HIDL requestStreamBuffers"); BufferRequestStatus status; hidl_vec bufRets; auto err = mCallback_3_5->requestStreamBuffers(hBufReqs, [&status, &bufRets] (BufferRequestStatus s, const hidl_vec& 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 importedFences; std::vector> 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& 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 hBufs(num_buffers); for (size_t i = 0; i < num_buffers; i++) { hBufs[i].streamId = static_cast(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(static_cast(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(static_cast(cb)); d->returnStreamBuffers(num_buffers, buffers); } Return 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