media codec2: Expire waiters from HAL during stop()/release()
Expire C2Fence waiting from HAL during stop()/release().
Bug: 300350761
Test: atest android.media.decoder.cts.AdaptivePlaybackTest
Test: atest android.media.codec.cts.MediaCodecTest#testAsyncRelease
Test: atest android.media.codec.cts.MediaCodecTest#testAsyncStopAndReset
Change-Id: I68aeafee2c4be95b78dd2fc98db01f231748e5da
diff --git a/media/codec2/hal/client/output.cpp b/media/codec2/hal/client/output.cpp
index 4eebd1c..48f9756 100644
--- a/media/codec2/hal/client/output.cpp
+++ b/media/codec2/hal/client/output.cpp
@@ -336,9 +336,25 @@
}
void OutputBufferQueue::stop() {
- std::scoped_lock<std::mutex> l(mMutex);
- mStopped = true;
- mOwner.reset(); // destructor of the block will not triger IGBP::cancel()
+ std::shared_ptr<C2SurfaceSyncMemory> oldMem;
+ {
+ std::scoped_lock<std::mutex> l(mMutex);
+ if (mStopped) {
+ return;
+ }
+ mStopped = true;
+ mOwner.reset(); // destructor of the block will not trigger IGBP::cancel()
+ // basically configuring null surface
+ oldMem = mSyncMem;
+ mSyncMem.reset();
+ mIgbp.clear();
+ mGeneration = 0;
+ mBqId = 0;
+ }
+ {
+ std::scoped_lock<std::mutex> l(mOldMutex);
+ mOldMem = oldMem;
+ }
}
bool OutputBufferQueue::registerBuffer(const C2ConstGraphicBlock& block) {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 86fd8ab..8082dd7 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1915,8 +1915,16 @@
}
comp = state->comp;
}
- status_t err = comp->stop();
+
+ // Note: Logically mChannel->stopUseOutputSurface() should be after comp->stop().
+ // But in the case some HAL implementations hang forever on comp->stop().
+ // (HAL is waiting for C2Fence until fetchGraphicBlock unblocks and not
+ // completing stop()).
+ // So we reverse their order for stopUseOutputSurface() to notify C2Fence waiters
+ // prior to comp->stop().
+ // See also b/300350761.
mChannel->stopUseOutputSurface(pushBlankBuffer);
+ status_t err = comp->stop();
if (err != C2_OK) {
// TODO: convert err into status_t
mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
@@ -2004,8 +2012,15 @@
}
comp = state->comp;
}
- comp->release();
+ // Note: Logically mChannel->stopUseOutputSurface() should be after comp->release().
+ // But in the case some HAL implementations hang forever on comp->release().
+ // (HAL is waiting for C2Fence until fetchGraphicBlock unblocks and not
+ // completing release()).
+ // So we reverse their order for stopUseOutputSurface() to notify C2Fence waiters
+ // prior to comp->release().
+ // See also b/300350761.
mChannel->stopUseOutputSurface(pushBlankBuffer);
+ comp->release();
{
Mutexed<State>::Locked state(mState);