Fix potential deadlock in stopPreview/stopRecord.
Some camera HALs spin up a preview thread and need to wait for the thread to exit. This can create a potential deadlock. In stopPreview, we take the main lock. If a preview callback occurs while the lock is held, the preview thread will block. If the camera HAL is waiting for the preview thread to exit, this will cause a deadlock. This patch breaks out the preview buffer heap into a separate mutex. This mutex is never held when the main lock is held, thus preventing the deadlock from occuring.
This commit is contained in:
parent
3bde289d23
commit
ff0f38e6fe
@ -683,22 +683,30 @@ void CameraService::Client::stopPreview()
|
||||
{
|
||||
LOGD("stopPreview (pid %d)", getCallingPid());
|
||||
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (checkPid() != NO_ERROR) return;
|
||||
// hold main lock during state transition
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (checkPid() != NO_ERROR) return;
|
||||
|
||||
if (mHardware == 0) {
|
||||
LOGE("mHardware is NULL, returning.");
|
||||
return;
|
||||
if (mHardware == 0) {
|
||||
LOGE("mHardware is NULL, returning.");
|
||||
return;
|
||||
}
|
||||
|
||||
mHardware->stopPreview();
|
||||
mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
|
||||
LOGD("stopPreview(), hardware stopped OK");
|
||||
|
||||
if (mSurface != 0 && !mUseOverlay) {
|
||||
mSurface->unregisterBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
mHardware->stopPreview();
|
||||
mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
|
||||
LOGD("stopPreview(), hardware stopped OK");
|
||||
|
||||
if (mSurface != 0 && !mUseOverlay) {
|
||||
mSurface->unregisterBuffers();
|
||||
// hold preview buffer lock
|
||||
{
|
||||
Mutex::Autolock lock(mPreviewLock);
|
||||
mPreviewBuffer.clear();
|
||||
}
|
||||
mPreviewBuffer.clear();
|
||||
}
|
||||
|
||||
// stop recording mode
|
||||
@ -706,24 +714,31 @@ void CameraService::Client::stopRecording()
|
||||
{
|
||||
LOGD("stopRecording (pid %d)", getCallingPid());
|
||||
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (checkPid() != NO_ERROR) return;
|
||||
// hold main lock during state transition
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (checkPid() != NO_ERROR) return;
|
||||
|
||||
if (mHardware == 0) {
|
||||
LOGE("mHardware is NULL, returning.");
|
||||
return;
|
||||
if (mHardware == 0) {
|
||||
LOGE("mHardware is NULL, returning.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMediaPlayerBeep.get() != NULL) {
|
||||
mMediaPlayerBeep->seekTo(0);
|
||||
mMediaPlayerBeep->start();
|
||||
}
|
||||
|
||||
mHardware->stopRecording();
|
||||
mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
|
||||
LOGD("stopRecording(), hardware stopped OK");
|
||||
}
|
||||
|
||||
if (mMediaPlayerBeep.get() != NULL) {
|
||||
mMediaPlayerBeep->seekTo(0);
|
||||
mMediaPlayerBeep->start();
|
||||
// hold preview buffer lock
|
||||
{
|
||||
Mutex::Autolock lock(mPreviewLock);
|
||||
mPreviewBuffer.clear();
|
||||
}
|
||||
|
||||
mHardware->stopRecording();
|
||||
mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
|
||||
LOGD("stopRecording(), hardware stopped OK");
|
||||
|
||||
mPreviewBuffer.clear();
|
||||
}
|
||||
|
||||
// release a recording frame
|
||||
@ -1216,10 +1231,10 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>&
|
||||
// provided it's big enough. Don't allocate the memory or
|
||||
// perform the copy if there's no callback.
|
||||
|
||||
// hold the lock while we grab a reference to the preview buffer
|
||||
// hold the preview lock while we grab a reference to the preview buffer
|
||||
sp<MemoryHeapBase> previewBuffer;
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
Mutex::Autolock lock(mPreviewLock);
|
||||
if (mPreviewBuffer == 0) {
|
||||
mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
|
||||
} else if (size > mPreviewBuffer->virtualSize()) {
|
||||
|
@ -181,7 +181,6 @@ private:
|
||||
mutable Condition mReady;
|
||||
sp<CameraService> mCameraService;
|
||||
sp<ISurface> mSurface;
|
||||
sp<MemoryHeapBase> mPreviewBuffer;
|
||||
int mPreviewCallbackFlag;
|
||||
|
||||
sp<MediaPlayer> mMediaPlayerClick;
|
||||
@ -197,6 +196,9 @@ private:
|
||||
sp<OverlayRef> mOverlayRef;
|
||||
int mOverlayW;
|
||||
int mOverlayH;
|
||||
|
||||
mutable Mutex mPreviewLock;
|
||||
sp<MemoryHeapBase> mPreviewBuffer;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user