Merge "Fix camera app crash when failed open the camera." into ics-mr0
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 2c1662b..70f70c8 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -124,7 +124,6 @@
     private boolean mMeteringAreaSupported;
     private boolean mAeLockSupported;
     private boolean mAwbLockSupported;
-    private boolean mAeAwbLock;
 
     private MyOrientationEventListener mOrientationListener;
     // The degrees of the device rotated clockwise from its natural orientation.
@@ -385,6 +384,7 @@
         Util.initializeScreenBrightness(getWindow(), getContentResolver());
         installIntentFilter();
         initializeZoom();
+        startFaceDetection();
         // Show the tap to focus toast if this is the first start.
         if (mFocusAreaSupported &&
                 mPreferences.getBoolean(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN, true)) {
@@ -700,6 +700,7 @@
                 enableCameraControls(true);
 
                 startPreview();
+                startFaceDetection();
             }
 
             if (!mIsImageCaptureIntent) {
@@ -1258,6 +1259,7 @@
     public void onReviewRetakeClicked(View v) {
         hidePostCaptureAlert();
         startPreview();
+        startFaceDetection();
     }
 
     @OnClickAttr
@@ -1358,18 +1360,10 @@
         // Do not do focus if there is not enough storage.
         if (pressed && !canTakePicture()) return;
 
-        // Lock AE and AWB so users can half-press shutter and recompose.
-        mAeAwbLock = pressed;
-        if (mAeAwbLock && (mAeLockSupported || mAwbLockSupported)) {
-            setCameraParameters(UPDATE_PARAM_PREFERENCE);
-        }
-
-        mFocusManager.doFocus(pressed);
-
-        // Unlock AE and AWB after cancelAutoFocus. Camera API does not
-        // guarantee setParameters can be called during autofocus.
-        if (!mAeAwbLock && (mAeLockSupported || mAwbLockSupported)) {
-            setCameraParameters(UPDATE_PARAM_PREFERENCE);
+        if (pressed) {
+            mFocusManager.onShutterDown();
+        } else {
+            mFocusManager.onShutterUp();
         }
     }
 
@@ -1462,6 +1456,7 @@
                 initializeCapabilities();
                 resetExposureCompensation();
                 startPreview();
+                startFaceDetection();
             } catch (CameraHardwareException e) {
                 Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
                 return;
@@ -1685,6 +1680,7 @@
         // display rotation in onCreate may not be what we want.
         if (mCameraState == PREVIEW_STOPPED) {
             startPreview();
+            startFaceDetection();
         } else {
             if (Util.getDisplayRotation(this) != mDisplayRotation) {
                 setDisplayOrientation();
@@ -1758,7 +1754,8 @@
 
         setPreviewDisplay(mSurfaceHolder);
         setDisplayOrientation();
-        mAeAwbLock = false; // Unlock AE and AWB.
+
+        mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
         setCameraParameters(UPDATE_PARAM_ALL);
         // If the focus mode is continuous autofocus, call cancelAutoFocus to
         // resume it because it may have been paused by autoFocus call.
@@ -1781,7 +1778,6 @@
             throw new RuntimeException("startPreview failed", ex);
         }
 
-        startFaceDetection();
         mZoomState = ZOOM_STOPPED;
         mCameraState = IDLE;
         mFocusManager.onPreviewStarted();
@@ -1833,11 +1829,11 @@
 
     private void updateCameraParametersPreference() {
         if (mAeLockSupported) {
-            mParameters.setAutoExposureLock(mAeAwbLock);
+            mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock());
         }
 
         if (mAwbLockSupported) {
-            mParameters.setAutoWhiteBalanceLock(mAeAwbLock);
+            mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock());
         }
 
         if (mFocusAreaSupported) {
diff --git a/src/com/android/camera/FocusManager.java b/src/com/android/camera/FocusManager.java
index 6b9dbd6..228e2d1 100644
--- a/src/com/android/camera/FocusManager.java
+++ b/src/com/android/camera/FocusManager.java
@@ -55,6 +55,8 @@
     private boolean mInitialized;
     private boolean mFocusAreaSupported;
     private boolean mInLongPress;
+    private boolean mLockAeAwbNeeded;
+    private boolean mAeAwbLock;
     private SoundPlayer mSoundPlayer;
     private View mFocusIndicatorRotateLayout;
     private FocusIndicatorView mFocusIndicator;
@@ -104,6 +106,8 @@
         mFocusAreaSupported = (mParameters.getMaxNumFocusAreas() > 0
                 && isSupported(Parameters.FOCUS_MODE_AUTO,
                         mParameters.getSupportedFocusModes()));
+        mLockAeAwbNeeded = (mParameters.isAutoExposureLockSupported() ||
+                mParameters.isAutoWhiteBalanceLockSupported());
     }
 
     public void initialize(View focusIndicatorRotate, View previewFrame,
@@ -121,27 +125,42 @@
         }
     }
 
-    public void doFocus(boolean pressed) {
+    public void onShutterDown() {
         if (!mInitialized) return;
 
-        if (!(getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY)
-                || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED)
-                || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF))) {
-            if (pressed) {  // Focus key down.
-                // Do not focus if touch focus has been triggered.
-                if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
-                    autoFocus();
-                }
-            } else {  // Focus key up.
-                // User releases half-pressed focus key.
-                if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
-                        || mState == STATE_FAIL) {
-                    cancelAutoFocus();
-                }
+        // Lock AE and AWB so users can half-press shutter and recompose.
+        if (mLockAeAwbNeeded && !mAeAwbLock) {
+            mAeAwbLock = true;
+            mListener.setFocusParameters();
+        }
+
+        if (needAutoFocusCall()) {
+            // Do not focus if touch focus has been triggered.
+            if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
+                autoFocus();
             }
         }
     }
 
+    public void onShutterUp() {
+        if (!mInitialized) return;
+
+        if (needAutoFocusCall()) {
+            // User releases half-pressed focus key.
+            if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
+                    || mState == STATE_FAIL) {
+                cancelAutoFocus();
+            }
+        }
+
+        // Unlock AE and AWB after cancelAutoFocus. Camera API does not
+        // guarantee setParameters can be called during autofocus.
+        if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
+            mAeAwbLock = false;
+            mListener.setFocusParameters();
+        }
+    }
+
     public void shutterLongPressed() {
         if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)
                 && isSupported(Parameters.FOCUS_MODE_AUTO, mParameters.getSupportedFocusModes())) {
@@ -151,9 +170,9 @@
             mInLongPress = true;
             // Cancel any outstanding Auto focus requests. The auto focus mode
             // will be changed from CAF to auto in cancelAutoFocus.
-            doFocus(false);
+            onShutterUp();
             // Call Autofocus
-            doFocus(true);
+            onShutterDown();
             mInLongPress = false;
         }
     }
@@ -164,11 +183,7 @@
         // If the user has half-pressed the shutter and focus is completed, we
         // can take the photo right away. If the focus mode is infinity, we can
         // also take the photo.
-        if (getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY)
-                || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED)
-                || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF)
-                || (mState == STATE_SUCCESS
-                || mState == STATE_FAIL)) {
+        if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
             capture();
         } else if (mState == STATE_FOCUSING) {
             // Half pressing the shutter (i.e. the focus button event) will
@@ -467,7 +482,22 @@
         mOverrideFocusMode = focusMode;
     }
 
+    public void setAeAwbLock(boolean lock) {
+        mAeAwbLock = lock;
+    }
+
+    public boolean getAeAwbLock() {
+        return mAeAwbLock;
+    }
+
     private static boolean isSupported(String value, List<String> supported) {
         return supported == null ? false : supported.indexOf(value) >= 0;
     }
+
+    private boolean needAutoFocusCall() {
+        String focusMode = getFocusMode();
+        return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
+                || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
+                || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
+    }
 }