diff options
| author | 2009-11-10 22:29:59 -0800 | |
|---|---|---|
| committer | 2009-11-10 22:29:59 -0800 | |
| commit | dd861689924198ed22115f0e21be1b81e159a7cc (patch) | |
| tree | 66c043528d943394b1b97db2056ecc22c5474ede | |
| parent | fe17db4c023ea39dcbd971d64c3a5bcc6dd6fab9 (diff) | |
| parent | 05fd0df0f3ec71ec6ea874439feda960ef882d0b (diff) | |
Merge change I05fd0df0 into eclair
* changes:
Fix potential deadlock in stopPreview/stopRecord.
| -rw-r--r-- | camera/libcameraservice/CameraService.cpp | 71 | ||||
| -rw-r--r-- | camera/libcameraservice/CameraService.h | 4 |
2 files changed, 46 insertions, 29 deletions
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index e54852446692..df59dcff0b29 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -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"); + mHardware->stopPreview(); + mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + LOGD("stopPreview(), hardware stopped OK"); - if (mSurface != 0 && !mUseOverlay) { - mSurface->unregisterBuffers(); + 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(); - } + if (mMediaPlayerBeep.get() != NULL) { + mMediaPlayerBeep->seekTo(0); + mMediaPlayerBeep->start(); + } - mHardware->stopRecording(); - mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME); - LOGD("stopRecording(), hardware stopped OK"); + mHardware->stopRecording(); + mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME); + LOGD("stopRecording(), hardware stopped OK"); + } - mPreviewBuffer.clear(); + // hold preview buffer lock + { + Mutex::Autolock lock(mPreviewLock); + 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()) { diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 41c5d99faaaa..3e3e54f0a950 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -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; }; // ---------------------------------------------------------------------------- |