CameraHal: Sync AF cancel with incoming OMX events

- Cancel AF is made to wait on incoming OMX events
  when AF status changes. An AF timeout is introduced
  in order not to block this call indefinitely.
- Additionally calls to 'autoFocus()' will immediately
  trigger AF callbacks if fixed modes are being used.

Bug: 6949572

Change-Id: I5f240fb6fc7fe53aecaff76d75d608dd522c1e27
Signed-off-by: Emilian Peev <epeev@mm-sol.com>
diff --git a/camera/OMXCameraAdapter/OMXFocus.cpp b/camera/OMXCameraAdapter/OMXFocus.cpp
index be1dfc5..e50b005 100644
--- a/camera/OMXCameraAdapter/OMXFocus.cpp
+++ b/camera/OMXCameraAdapter/OMXFocus.cpp
@@ -36,6 +36,8 @@
 
 namespace android {
 
+const nsecs_t OMXCameraAdapter::CANCEL_AF_TIMEOUT =  seconds_to_nanoseconds(1);
+
 status_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
                                               BaseCameraAdapter::AdapterState state)
 {
@@ -108,6 +110,14 @@
        return NO_ERROR;
     }
 
+    // AF when fixed focus modes are set should be a no-op.
+    if ( ( mParameters3A.Focus == OMX_IMAGE_FocusControlOff ) ||
+         ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) ||
+         ( mParameters3A.Focus == OMX_IMAGE_FocusControlHyperfocal ) ) {
+        returnFocusStatus(true);
+        return NO_ERROR;
+    }
+
     OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
 
     // If the app calls autoFocus, the camera will stop sending face callbacks.
@@ -161,6 +171,12 @@
         eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
                                (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
                                &bOMX);
+        if ( OMX_ErrorNone != eError ) {
+            return ErrorUtils::omxToAndroidError(eError);
+        }
+
+        {
+        android::AutoMutex lock(mDoAFMutex);
 
         // force AF, Ducati will take care of whether CAF
         // or AF will be performed, depending on light conditions
@@ -175,24 +191,23 @@
             eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
                                     OMX_IndexConfigFocusControl,
                                     &focusControl);
+
+            if ( OMX_ErrorNone != eError ) {
+                CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
+                return INVALID_OPERATION;
+            } else {
+                CAMHAL_LOGDA("Autofocus started successfully");
             }
 
-        if ( OMX_ErrorNone != eError ) {
-            CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
-            return INVALID_OPERATION;
-        } else {
-            CAMHAL_LOGDA("Autofocus started successfully");
-        }
-
-        // configure focus timeout based on capture mode
-        timeout = (mCapMode == VIDEO_MODE) ?
+            // configure focus timeout based on capture mode
+            timeout = (mCapMode == VIDEO_MODE) ?
                         ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) :
                         ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 );
 
-            {
-            Mutex::Autolock lock(mDoAFMutex);
+
             ret = mDoAFCond.waitRelative(mDoAFMutex, timeout);
             }
+        } // mDoAFMutex lock ends here
 
         //If somethiing bad happened while we wait
         if (mComponentState == OMX_StateInvalid) {
@@ -222,6 +237,7 @@
 {
     OMX_ERRORTYPE eError = OMX_ErrorNone;
     OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
+    status_t ret = NO_ERROR;
 
     LOG_FUNCTION_NAME;
 
@@ -253,19 +269,11 @@
         {
         CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
         return ErrorUtils::omxToAndroidError(eError);
-    } else {
-        // This is a WA. Usually the OMX Camera component should
-        // generate AF status change OMX event fairly quickly
-        // ( after one preview frame ) and this notification should
-        // actually come from 'handleFocusCallback()'.
-        Mutex::Autolock lock(mDoAFMutex);
-        mDoAFCond.broadcast();
     }
 
-
     LOG_FUNCTION_NAME_EXIT;
 
-    return NO_ERROR;
+    return ret;
 }
 
 status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
@@ -311,14 +319,27 @@
     //Stop the AF only for modes other than CAF  or Inifinity
     if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
          ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
-                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
+                 OMX_IMAGE_FocusControlAutoInfinity ) &&
+         ( focusMode.eFocusControl != OMX_IMAGE_FocusControlOff ) ) {
+        android::AutoMutex lock(mCancelAFMutex);
         stopAutoFocus();
+        ret = mCancelAFCond.waitRelative(mCancelAFMutex, CANCEL_AF_TIMEOUT);
+        if ( NO_ERROR != ret ) {
+            CAMHAL_LOGEA("Cancel AF timeout!");
+        }
     } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
        // This re-enabling of CAF doesn't seem to
        // be needed any more.
        // re-apply CAF after unlocking and canceling
        // mPending3Asettings |= SetFocus;
     }
+
+    {
+        // Signal to 'doAutoFocus()'
+        android::AutoMutex lock(mDoAFMutex);
+        mDoAFCond.broadcast();
+    }
+
     // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
     pauseFaceDetection(false);
 
@@ -808,8 +829,13 @@
         return;
     }
 
-    if ( ( eFocusStatus.eFocusStatus != OMX_FocusStatusRequest ) &&
-         ( eFocusStatus.eFocusStatus != OMX_FocusStatusOff ) ) {
+    if ( eFocusStatus.eFocusStatus == OMX_FocusStatusOff ) {
+        android::AutoMutex lock(mCancelAFMutex);
+        mCancelAFCond.signal();
+        return;
+    }
+
+    if (eFocusStatus.eFocusStatus != OMX_FocusStatusRequest) {
         // signal doAutoFocus when a end of scan message comes
         // ignore start of scan
         Mutex::Autolock lock(mDoAFMutex);
diff --git a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
index 59c5efc..1f1fd9f 100644
--- a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
+++ b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
@@ -939,6 +939,10 @@
     Mutex mFrameCountMutex;
     Condition mFirstFrameCondition;
 
+    static const nsecs_t CANCEL_AF_TIMEOUT;
+    Mutex mCancelAFMutex;
+    Condition mCancelAFCond;
+
     Mutex mDoAFMutex;
     Condition mDoAFCond;