summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware/Camera.java
diff options
context:
space:
mode:
authorWu-cheng Li <wuchengli@google.com>2012-05-02 23:29:47 +0800
committerWu-cheng Li <wuchengli@google.com>2012-05-04 01:01:46 +0800
commitf05c1d63d16e790ac78c5854bb12374f45d6118e (patch)
tree89a088e71b5290b15d3e42b3980c1009c58e42d4 /core/java/android/hardware/Camera.java
parent39f412d8deed2ba46153c8a819bc8635979cec6b (diff)
downloadframeworks_base-f05c1d63d16e790ac78c5854bb12374f45d6118e.zip
frameworks_base-f05c1d63d16e790ac78c5854bb12374f45d6118e.tar.gz
frameworks_base-f05c1d63d16e790ac78c5854bb12374f45d6118e.tar.bz2
Avoid deadlocks when calling autoFocus from onAutoFocus callback.
Applicatons may use different threads for calling autoFocus and onAutoFocus callback. bug:6026574 Change-Id: I114a60240e22af15ca469b591e080121367db8e2
Diffstat (limited to 'core/java/android/hardware/Camera.java')
-rw-r--r--core/java/android/hardware/Camera.java61
1 files changed, 31 insertions, 30 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 5ed8dd1..63b0102 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -155,7 +155,7 @@ public class Camera {
private boolean mOneShot;
private boolean mWithBuffer;
private boolean mFaceDetectionRunning = false;
- private ReentrantLock mFocusLock = new ReentrantLock();
+ private Object mAutoFocusCallbackLock = new Object();
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -508,7 +508,9 @@ public class Camera {
mRawImageCallback = null;
mPostviewCallback = null;
mJpegCallback = null;
- mAutoFocusCallback = null;
+ synchronized (mAutoFocusCallbackLock) {
+ mAutoFocusCallback = null;
+ }
mAutoFocusMoveCallback = null;
}
@@ -748,14 +750,13 @@ public class Camera {
return;
case CAMERA_MSG_FOCUS:
- mFocusLock.lock();
- try {
- if (mAutoFocusCallback != null) {
- boolean success = msg.arg1 == 0 ? false : true;
- mAutoFocusCallback.onAutoFocus(success, mCamera);
- }
- } finally {
- mFocusLock.unlock();
+ AutoFocusCallback cb = null;
+ synchronized (mAutoFocusCallbackLock) {
+ cb = mAutoFocusCallback;
+ }
+ if (cb != null) {
+ boolean success = msg.arg1 == 0 ? false : true;
+ cb.onAutoFocus(success, mCamera);
}
return;
@@ -880,13 +881,10 @@ public class Camera {
*/
public final void autoFocus(AutoFocusCallback cb)
{
- mFocusLock.lock();
- try {
+ synchronized (mAutoFocusCallbackLock) {
mAutoFocusCallback = cb;
- native_autoFocus();
- } finally {
- mFocusLock.unlock();
}
+ native_autoFocus();
}
private native final void native_autoFocus();
@@ -900,14 +898,26 @@ public class Camera {
*/
public final void cancelAutoFocus()
{
- mFocusLock.lock();
- try {
+ synchronized (mAutoFocusCallbackLock) {
mAutoFocusCallback = null;
- native_cancelAutoFocus();
- removePendingAFCompletionMessages();
- } finally {
- mFocusLock.unlock();
}
+ native_cancelAutoFocus();
+ // CAMERA_MSG_FOCUS should be removed here because the following
+ // scenario can happen:
+ // - An application uses the same thread for autoFocus, cancelAutoFocus
+ // and looper thread.
+ // - The application calls autoFocus.
+ // - HAL sends CAMERA_MSG_FOCUS, which enters the looper message queue.
+ // Before event handler's handleMessage() is invoked, the application
+ // calls cancelAutoFocus and autoFocus.
+ // - The application gets the old CAMERA_MSG_FOCUS and thinks autofocus
+ // has been completed. But in fact it is not.
+ //
+ // As documented in the beginning of the file, apps should not use
+ // multiple threads to call autoFocus and cancelAutoFocus at the same
+ // time. It is HAL's responsibility not to send a CAMERA_MSG_FOCUS
+ // message after native_cancelAutoFocus is called.
+ mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
}
private native final void native_cancelAutoFocus();
@@ -3596,13 +3606,4 @@ public class Camera {
return false;
}
};
-
- /*
- * At any time, there should be at most one pending auto focus completion
- * message, but we simply remove all pending AF completion messages in
- * the looper's queue.
- */
- private void removePendingAFCompletionMessages() {
- mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
- }
}