Loading camera/device/3.4/default/ExternalCameraDeviceSession.cpp +71 −34 Original line number Diff line number Diff line Loading @@ -51,10 +51,12 @@ constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to // webcam showing temporarily ioctl failures. constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds // Constants for tryLock during dumpstate static constexpr int kDumpLockRetries = 50; static constexpr int kDumpLockSleep = 60000; bool tryLock(Mutex& mutex) { static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 60000; bool locked = false; for (int i = 0; i < kDumpLockRetries; ++i) { if (mutex.tryLock() == NO_ERROR) { Loading @@ -66,6 +68,19 @@ bool tryLock(Mutex& mutex) return locked; } bool tryLock(std::mutex& mutex) { bool locked = false; for (int i = 0; i < kDumpLockRetries; ++i) { if (mutex.try_lock()) { locked = true; break; } usleep(kDumpLockSleep); } return locked; } } // Anonymous namespace // Static instances Loading Loading @@ -163,7 +178,6 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { bool streaming = false; size_t v4L2BufferCount = 0; SupportedV4L2Format streamingFmt; std::unordered_set<uint32_t> inflightFrames; { bool sessionLocked = tryLock(mLock); if (!sessionLocked) { Loading @@ -172,12 +186,25 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { streaming = mV4l2Streaming; streamingFmt = mV4l2StreamingFmt; v4L2BufferCount = mV4L2BufferCount; inflightFrames = mInflightFrames; if (sessionLocked) { mLock.unlock(); } } std::unordered_set<uint32_t> inflightFrames; { bool iffLocked = tryLock(mInflightFramesLock); if (!iffLocked) { dprintf(fd, "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n"); } inflightFrames = mInflightFrames; if (iffLocked) { mInflightFramesLock.unlock(); } } dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n", mCameraId.c_str(), mV4l2Fd.get(), (mCroppingType == VERTICAL) ? "vertical" : "horizontal", Loading Loading @@ -457,6 +484,7 @@ void ExternalCameraDeviceSession::cleanupInflightFences( } int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) { ATRACE_CALL(); std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec); mLock.unlock(); auto st = mV4L2BufferReturned.wait_for(lk, timeout); Loading Loading @@ -612,7 +640,10 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques halBuf.acquireFence = allFences[i]; halBuf.fenceTimeout = false; } { std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.insert(halReq->frameNumber); } // Send request to OutputThread for the rest of processing mOutputThread->submitRequest(halReq); mFirstRequest = false; Loading Loading @@ -670,7 +701,7 @@ Status ExternalCameraDeviceSession::processCaptureRequestError( // update inflight records { Mutex::Autolock _l(mLock); std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.erase(req->frameNumber); } Loading Loading @@ -724,7 +755,7 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequ // update inflight records { Mutex::Autolock _l(mLock); std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.erase(req->frameNumber); } Loading Loading @@ -2285,6 +2316,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t } } ATRACE_BEGIN("VIDIOC_DQBUF"); v4l2_buffer buffer{}; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; Loading @@ -2292,6 +2324,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno)); return ret; } ATRACE_END(); if (buffer.index >= mV4L2BufferCount) { ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index); Loading Loading @@ -2329,11 +2362,8 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { ATRACE_CALL(); { // Release mLock before acquiring mV4l2BufferLock to avoid potential // deadlock Mutex::Autolock _l(mLock); frame->unmap(); ATRACE_BEGIN("VIDIOC_QBUF"); v4l2_buffer buffer{}; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; Loading @@ -2343,7 +2373,7 @@ void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { frame->mBufferIndex, strerror(errno)); return; } } ATRACE_END(); { std::lock_guard<std::mutex> lk(mV4l2BufferLock); Loading Loading @@ -2396,13 +2426,17 @@ Status ExternalCameraDeviceSession::configureStreams( return status; } Mutex::Autolock _l(mLock); { std::lock_guard<std::mutex> lk(mInflightFramesLock); if (!mInflightFrames.empty()) { ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!", __FUNCTION__, mInflightFrames.size()); return Status::INTERNAL_ERROR; } } Mutex::Autolock _l(mLock); // Add new streams for (const auto& stream : config.streams) { if (mStreamMap.count(stream.id) == 0) { Loading Loading @@ -2702,9 +2736,11 @@ status_t ExternalCameraDeviceSession::fillCaptureResult( const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF; UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1); bool afTrigger = mAfTrigger; bool afTrigger = false; { std::lock_guard<std::mutex> lk(mAfTriggerLock); afTrigger = mAfTrigger; if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) { Mutex::Autolock _l(mLock); camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER); if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) { mAfTrigger = afTrigger = true; Loading @@ -2712,6 +2748,7 @@ status_t ExternalCameraDeviceSession::fillCaptureResult( mAfTrigger = afTrigger = false; } } } // For USB camera, the USB camera handles everything and we don't have control // over AF. We only simply fake the AF metadata based on the request Loading camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +6 −0 Original line number Diff line number Diff line Loading @@ -300,6 +300,9 @@ protected: const std::vector<SupportedV4L2Format> mSupportedFormats; const CroppingType mCroppingType; const std::string& mCameraId; // Not protected by mLock, this is almost a const. // Setup in constructor, reset in close() after OutputThread is joined unique_fd mV4l2Fd; // device is closed either Loading Loading @@ -327,6 +330,8 @@ protected: // Stream ID -> Camera3Stream cache std::unordered_map<int, Stream> mStreamMap; std::mutex mInflightFramesLock; // protect mInflightFrames std::unordered_set<uint32_t> mInflightFrames; // buffers currently circulating between HAL and camera service Loading @@ -338,6 +343,7 @@ protected: // Stream ID -> circulating buffers map std::map<int, CirculatingBuffers> mCirculatingBuffers; std::mutex mAfTriggerLock; // protect mAfTrigger bool mAfTrigger = false; static HandleImporter sHandleImporter; Loading Loading
camera/device/3.4/default/ExternalCameraDeviceSession.cpp +71 −34 Original line number Diff line number Diff line Loading @@ -51,10 +51,12 @@ constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to // webcam showing temporarily ioctl failures. constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds // Constants for tryLock during dumpstate static constexpr int kDumpLockRetries = 50; static constexpr int kDumpLockSleep = 60000; bool tryLock(Mutex& mutex) { static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 60000; bool locked = false; for (int i = 0; i < kDumpLockRetries; ++i) { if (mutex.tryLock() == NO_ERROR) { Loading @@ -66,6 +68,19 @@ bool tryLock(Mutex& mutex) return locked; } bool tryLock(std::mutex& mutex) { bool locked = false; for (int i = 0; i < kDumpLockRetries; ++i) { if (mutex.try_lock()) { locked = true; break; } usleep(kDumpLockSleep); } return locked; } } // Anonymous namespace // Static instances Loading Loading @@ -163,7 +178,6 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { bool streaming = false; size_t v4L2BufferCount = 0; SupportedV4L2Format streamingFmt; std::unordered_set<uint32_t> inflightFrames; { bool sessionLocked = tryLock(mLock); if (!sessionLocked) { Loading @@ -172,12 +186,25 @@ void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { streaming = mV4l2Streaming; streamingFmt = mV4l2StreamingFmt; v4L2BufferCount = mV4L2BufferCount; inflightFrames = mInflightFrames; if (sessionLocked) { mLock.unlock(); } } std::unordered_set<uint32_t> inflightFrames; { bool iffLocked = tryLock(mInflightFramesLock); if (!iffLocked) { dprintf(fd, "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n"); } inflightFrames = mInflightFrames; if (iffLocked) { mInflightFramesLock.unlock(); } } dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n", mCameraId.c_str(), mV4l2Fd.get(), (mCroppingType == VERTICAL) ? "vertical" : "horizontal", Loading Loading @@ -457,6 +484,7 @@ void ExternalCameraDeviceSession::cleanupInflightFences( } int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) { ATRACE_CALL(); std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec); mLock.unlock(); auto st = mV4L2BufferReturned.wait_for(lk, timeout); Loading Loading @@ -612,7 +640,10 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques halBuf.acquireFence = allFences[i]; halBuf.fenceTimeout = false; } { std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.insert(halReq->frameNumber); } // Send request to OutputThread for the rest of processing mOutputThread->submitRequest(halReq); mFirstRequest = false; Loading Loading @@ -670,7 +701,7 @@ Status ExternalCameraDeviceSession::processCaptureRequestError( // update inflight records { Mutex::Autolock _l(mLock); std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.erase(req->frameNumber); } Loading Loading @@ -724,7 +755,7 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequ // update inflight records { Mutex::Autolock _l(mLock); std::lock_guard<std::mutex> lk(mInflightFramesLock); mInflightFrames.erase(req->frameNumber); } Loading Loading @@ -2285,6 +2316,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t } } ATRACE_BEGIN("VIDIOC_DQBUF"); v4l2_buffer buffer{}; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; Loading @@ -2292,6 +2324,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno)); return ret; } ATRACE_END(); if (buffer.index >= mV4L2BufferCount) { ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index); Loading Loading @@ -2329,11 +2362,8 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { ATRACE_CALL(); { // Release mLock before acquiring mV4l2BufferLock to avoid potential // deadlock Mutex::Autolock _l(mLock); frame->unmap(); ATRACE_BEGIN("VIDIOC_QBUF"); v4l2_buffer buffer{}; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; Loading @@ -2343,7 +2373,7 @@ void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { frame->mBufferIndex, strerror(errno)); return; } } ATRACE_END(); { std::lock_guard<std::mutex> lk(mV4l2BufferLock); Loading Loading @@ -2396,13 +2426,17 @@ Status ExternalCameraDeviceSession::configureStreams( return status; } Mutex::Autolock _l(mLock); { std::lock_guard<std::mutex> lk(mInflightFramesLock); if (!mInflightFrames.empty()) { ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!", __FUNCTION__, mInflightFrames.size()); return Status::INTERNAL_ERROR; } } Mutex::Autolock _l(mLock); // Add new streams for (const auto& stream : config.streams) { if (mStreamMap.count(stream.id) == 0) { Loading Loading @@ -2702,9 +2736,11 @@ status_t ExternalCameraDeviceSession::fillCaptureResult( const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF; UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1); bool afTrigger = mAfTrigger; bool afTrigger = false; { std::lock_guard<std::mutex> lk(mAfTriggerLock); afTrigger = mAfTrigger; if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) { Mutex::Autolock _l(mLock); camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER); if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) { mAfTrigger = afTrigger = true; Loading @@ -2712,6 +2748,7 @@ status_t ExternalCameraDeviceSession::fillCaptureResult( mAfTrigger = afTrigger = false; } } } // For USB camera, the USB camera handles everything and we don't have control // over AF. We only simply fake the AF metadata based on the request Loading
camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +6 −0 Original line number Diff line number Diff line Loading @@ -300,6 +300,9 @@ protected: const std::vector<SupportedV4L2Format> mSupportedFormats; const CroppingType mCroppingType; const std::string& mCameraId; // Not protected by mLock, this is almost a const. // Setup in constructor, reset in close() after OutputThread is joined unique_fd mV4l2Fd; // device is closed either Loading Loading @@ -327,6 +330,8 @@ protected: // Stream ID -> Camera3Stream cache std::unordered_map<int, Stream> mStreamMap; std::mutex mInflightFramesLock; // protect mInflightFrames std::unordered_set<uint32_t> mInflightFrames; // buffers currently circulating between HAL and camera service Loading @@ -338,6 +343,7 @@ protected: // Stream ID -> circulating buffers map std::map<int, CirculatingBuffers> mCirculatingBuffers; std::mutex mAfTriggerLock; // protect mAfTrigger bool mAfTrigger = false; static HandleImporter sHandleImporter; Loading