From 0cf01cbcbc330c837ff779817f8f8d1efa2a05b1 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Thu, 5 Sep 2019 13:33:06 -0700 Subject: [PATCH] Camera: Drain attached and queued input buffers during reconfiguration Application may first call ImageWriter.queueInputImage without sending any capture request before reconfiguring capture session using the same ImageWriter. In this case, the stale buffers still exist in the buffer qeueue, and ImageWriter.queueInputImage may stuck at waiting for free slots in the new capture session. Clear up all such queued buffers in the input buffer queue during stream reconfiguration. Test: Run testMandatoryReprocessConfigurations 300 times Test: testQueueImageWithoutRequest Bug: 138729150 Change-Id: Ie102dd018983bbd972f7c647d8c86c976a44e754 --- .../device3/Camera3Device.cpp | 22 +++++++++++++++++++ .../device3/Camera3InputStream.cpp | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index dd5a62bed2..3188892481 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -2802,6 +2802,27 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode, mOperatingMode = operatingMode; } + // In case called from configureStreams, abort queued input buffers not belonging to + // any pending requests. + if (mInputStream != NULL && notifyRequestThread) { + while (true) { + camera3_stream_buffer_t inputBuffer; + status_t res = mInputStream->getInputBuffer(&inputBuffer, + /*respectHalLimit*/ false); + if (res != OK) { + // Exhausted acquiring all input buffers. + break; + } + + inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR; + res = mInputStream->returnInputBuffer(inputBuffer); + if (res != OK) { + ALOGE("%s: %d: couldn't return input buffer while clearing input queue: " + "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res); + } + } + } + if (!mNeedConfig) { ALOGV("%s: Skipping config, no stream changes", __FUNCTION__); return OK; @@ -5084,6 +5105,7 @@ status_t Camera3Device::RequestThread::clear( ALOGW("%s: %d: couldn't get input buffer while clearing the request " "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res); } else { + inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR; res = (*it)->mInputStream->returnInputBuffer(inputBuffer); if (res != OK) { ALOGE("%s: %d: couldn't return input buffer while clearing the request " diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp index fc83684601..cb59a76e2b 100644 --- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp @@ -71,7 +71,8 @@ status_t Camera3InputStream::getInputBufferLocked( res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false); if (res != OK) { - ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)", + // This may or may not be an error condition depending on caller. + ALOGV("%s: Stream %d: Can't acquire next output buffer: %s (%d)", __FUNCTION__, mId, strerror(-res), res); return res; }