Skip to content

Commit b0dcf5e

Browse files
Wu-cheng LiAndroid (Google) Code Review
authored andcommitted
Merge "Avoid deadlocks when calling autoFocus from onAutoFocus callback." into jb-dev
2 parents 610f310 + f05c1d6 commit b0dcf5e

File tree

1 file changed

+31
-30
lines changed

1 file changed

+31
-30
lines changed

core/java/android/hardware/Camera.java

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public class Camera {
155155
private boolean mOneShot;
156156
private boolean mWithBuffer;
157157
private boolean mFaceDetectionRunning = false;
158-
private ReentrantLock mFocusLock = new ReentrantLock();
158+
private Object mAutoFocusCallbackLock = new Object();
159159

160160
/**
161161
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -513,7 +513,9 @@ public final void stopPreview() {
513513
mRawImageCallback = null;
514514
mPostviewCallback = null;
515515
mJpegCallback = null;
516-
mAutoFocusCallback = null;
516+
synchronized (mAutoFocusCallbackLock) {
517+
mAutoFocusCallback = null;
518+
}
517519
mAutoFocusMoveCallback = null;
518520
}
519521

@@ -758,14 +760,13 @@ public void handleMessage(Message msg) {
758760
return;
759761

760762
case CAMERA_MSG_FOCUS:
761-
mFocusLock.lock();
762-
try {
763-
if (mAutoFocusCallback != null) {
764-
boolean success = msg.arg1 == 0 ? false : true;
765-
mAutoFocusCallback.onAutoFocus(success, mCamera);
766-
}
767-
} finally {
768-
mFocusLock.unlock();
763+
AutoFocusCallback cb = null;
764+
synchronized (mAutoFocusCallbackLock) {
765+
cb = mAutoFocusCallback;
766+
}
767+
if (cb != null) {
768+
boolean success = msg.arg1 == 0 ? false : true;
769+
cb.onAutoFocus(success, mCamera);
769770
}
770771
return;
771772

@@ -890,13 +891,10 @@ public interface AutoFocusCallback
890891
*/
891892
public final void autoFocus(AutoFocusCallback cb)
892893
{
893-
mFocusLock.lock();
894-
try {
894+
synchronized (mAutoFocusCallbackLock) {
895895
mAutoFocusCallback = cb;
896-
native_autoFocus();
897-
} finally {
898-
mFocusLock.unlock();
899896
}
897+
native_autoFocus();
900898
}
901899
private native final void native_autoFocus();
902900

@@ -910,14 +908,26 @@ public final void autoFocus(AutoFocusCallback cb)
910908
*/
911909
public final void cancelAutoFocus()
912910
{
913-
mFocusLock.lock();
914-
try {
911+
synchronized (mAutoFocusCallbackLock) {
915912
mAutoFocusCallback = null;
916-
native_cancelAutoFocus();
917-
removePendingAFCompletionMessages();
918-
} finally {
919-
mFocusLock.unlock();
920913
}
914+
native_cancelAutoFocus();
915+
// CAMERA_MSG_FOCUS should be removed here because the following
916+
// scenario can happen:
917+
// - An application uses the same thread for autoFocus, cancelAutoFocus
918+
// and looper thread.
919+
// - The application calls autoFocus.
920+
// - HAL sends CAMERA_MSG_FOCUS, which enters the looper message queue.
921+
// Before event handler's handleMessage() is invoked, the application
922+
// calls cancelAutoFocus and autoFocus.
923+
// - The application gets the old CAMERA_MSG_FOCUS and thinks autofocus
924+
// has been completed. But in fact it is not.
925+
//
926+
// As documented in the beginning of the file, apps should not use
927+
// multiple threads to call autoFocus and cancelAutoFocus at the same
928+
// time. It is HAL's responsibility not to send a CAMERA_MSG_FOCUS
929+
// message after native_cancelAutoFocus is called.
930+
mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
921931
}
922932
private native final void native_cancelAutoFocus();
923933

@@ -3640,13 +3650,4 @@ private boolean same(String s1, String s2) {
36403650
return false;
36413651
}
36423652
};
3643-
3644-
/*
3645-
* At any time, there should be at most one pending auto focus completion
3646-
* message, but we simply remove all pending AF completion messages in
3647-
* the looper's queue.
3648-
*/
3649-
private void removePendingAFCompletionMessages() {
3650-
mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
3651-
}
36523653
}

0 commit comments

Comments
 (0)