Camera2: Add trigger support, and implement autofocus

- Add skeletons for all triggering actions into Camera2Device
- Add support for AF triggers to HAL
- Add support for AF notifications from HAL

Bug: 6243944
Change-Id: I21025440849ae41f7083e1dcb72c99f8e5b2d5f7
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index cd74e6d..4566c75 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -88,6 +88,8 @@
         return NO_INIT;
     }
 
+    res = mDevice->setNotifyCallback(this);
+
     res = buildDefaultParameters();
     if (res != OK) {
         ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
@@ -846,6 +848,15 @@
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
 
+    int triggerId;
+    {
+        LockedParameters::Key k(mParameters);
+        k.mParameters.currentAfTriggerId = ++k.mParameters.afTriggerCounter;
+        triggerId = k.mParameters.currentAfTriggerId;
+    }
+
+    mDevice->triggerAutofocus(triggerId);
+
     return OK;
 }
 
@@ -855,6 +866,14 @@
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
 
+    int triggerId;
+    {
+        LockedParameters::Key k(mParameters);
+        triggerId = ++k.mParameters.afTriggerCounter;
+    }
+
+    mDevice->triggerCancelAutofocus(triggerId);
+
     return OK;
 }
 
@@ -1453,6 +1472,9 @@
     k.mParameters.sceneMode = sceneMode;
 
     k.mParameters.flashMode = flashMode;
+    if (focusMode != k.mParameters.focusMode) {
+        k.mParameters.currentAfTriggerId = -1;
+    }
     k.mParameters.focusMode = focusMode;
 
     k.mParameters.focusingAreas = focusingAreas;
@@ -1625,7 +1647,9 @@
 }
 
 status_t Camera2Client::commandEnableFocusMoveMsgL(bool enable) {
-    ALOGE("%s: Unimplemented!", __FUNCTION__);
+    LockedParameters::Key k(mParameters);
+    k.mParameters.enableFocusMoveMessages = enable;
+
     return OK;
 }
 
@@ -1678,6 +1702,102 @@
 void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
     ALOGV("%s: Autofocus state now %d, last trigger %d",
             __FUNCTION__, newState, triggerId);
+    bool sendCompletedMessage = false;
+    bool sendMovingMessage = false;
+
+    bool success = false;
+    bool afInMotion = false;
+    {
+        LockedParameters::Key k(mParameters);
+        switch (k.mParameters.focusMode) {
+            case Parameters::FOCUS_MODE_AUTO:
+            case Parameters::FOCUS_MODE_MACRO:
+                // Don't send notifications upstream if they're not for the current AF
+                // trigger. For example, if cancel was called in between, or if we
+                // already sent a notification about this AF call.
+                if (triggerId != k.mParameters.currentAfTriggerId) break;
+                switch (newState) {
+                    case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+                        success = true;
+                        // no break
+                    case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+                        sendCompletedMessage = true;
+                        k.mParameters.currentAfTriggerId = -1;
+                        break;
+                    case ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN:
+                        // Just starting focusing, ignore
+                        break;
+                    case ANDROID_CONTROL_AF_STATE_INACTIVE:
+                    case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+                    case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+                    default:
+                        // Unexpected in AUTO/MACRO mode
+                        ALOGE("%s: Unexpected AF state transition in AUTO/MACRO mode: %d",
+                                __FUNCTION__, newState);
+                        break;
+                }
+                break;
+            case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO:
+            case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE:
+                switch (newState) {
+                    case ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED:
+                        success = true;
+                        // no break
+                    case ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
+                        // Don't send notifications upstream if they're not for
+                        // the current AF trigger. For example, if cancel was
+                        // called in between, or if we already sent a
+                        // notification about this AF call.
+                        // Send both a 'AF done' callback and a 'AF move' callback
+                        if (triggerId != k.mParameters.currentAfTriggerId) break;
+                        sendCompletedMessage = true;
+                        afInMotion = false;
+                        if (k.mParameters.enableFocusMoveMessages &&
+                                k.mParameters.afInMotion) {
+                            sendMovingMessage = true;
+                        }
+                        k.mParameters.currentAfTriggerId = -1;
+                        break;
+                    case ANDROID_CONTROL_AF_STATE_INACTIVE:
+                        // Cancel was called, or we switched state; care if
+                        // currently moving
+                        afInMotion = false;
+                        if (k.mParameters.enableFocusMoveMessages &&
+                                k.mParameters.afInMotion) {
+                            sendMovingMessage = true;
+                        }
+                        break;
+                    case ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN:
+                        // Start passive scan, inform upstream
+                        afInMotion = true;
+                        // no break
+                    case ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED:
+                        // Stop passive scan, inform upstream
+                        if (k.mParameters.enableFocusMoveMessages) {
+                            sendMovingMessage = true;
+                        }
+                        break;
+                }
+                k.mParameters.afInMotion = afInMotion;
+                break;
+            case Parameters::FOCUS_MODE_EDOF:
+            case Parameters::FOCUS_MODE_INFINITY:
+            case Parameters::FOCUS_MODE_FIXED:
+            default:
+                if (newState != ANDROID_CONTROL_AF_STATE_INACTIVE) {
+                    ALOGE("%s: Unexpected AF state change %d (ID %d) in focus mode %d",
+                          __FUNCTION__, newState, triggerId, k.mParameters.focusMode);
+                }
+        }
+    }
+    if (sendCompletedMessage) {
+        mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, success ? 1 : 0, 0);
+    }
+    if (sendMovingMessage) {
+        mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
+                afInMotion ? 1 : 0, 0);
+    }
+
 }
 
 void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
@@ -2394,9 +2514,7 @@
         k.mParameters.focusMode = Parameters::FOCUS_MODE_AUTO;
         params.set(CameraParameters::KEY_FOCUS_MODE,
                 CameraParameters::FOCUS_MODE_AUTO);
-        String8 supportedFocusModes(CameraParameters::FOCUS_MODE_FIXED);
-        supportedFocusModes = supportedFocusModes + "," +
-            CameraParameters::FOCUS_MODE_INFINITY;
+        String8 supportedFocusModes(CameraParameters::FOCUS_MODE_INFINITY);
         bool addComma = true;
 
         for (size_t i=0; i < availableAfModes.count; i++) {
@@ -2573,6 +2691,8 @@
 
     k.mParameters.storeMetadataInBuffers = true;
     k.mParameters.playShutterSound = true;
+    k.mParameters.afTriggerCounter = 0;
+    k.mParameters.currentAfTriggerId = -1;
 
     k.mParameters.paramsFlattened = params.flatten();