Merge "Camera3: Support AE precapture trigger CANCEL" into mnc-dev
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 9d725de..4b55dad 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1787,12 +1787,14 @@
  */
 
 status_t Camera3Device::registerInFlight(uint32_t frameNumber,
-        int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput) {
+        int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
+        const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
     ATRACE_CALL();
     Mutex::Autolock l(mInFlightLock);
 
     ssize_t res;
-    res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput));
+    res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
+            aeTriggerCancelOverride));
     if (res < 0) return res;
 
     return OK;
@@ -2036,7 +2038,8 @@
         CaptureResultExtras &resultExtras,
         CameraMetadata &collectedPartialResult,
         uint32_t frameNumber,
-        bool reprocess) {
+        bool reprocess,
+        const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
     if (pendingMetadata.isEmpty())
         return;
 
@@ -2091,6 +2094,8 @@
         return;
     }
 
+    overrideResultForPrecaptureCancel(&captureResult.mMetadata, aeTriggerCancelOverride);
+
     // Valid result, insert into queue
     List<CaptureResult>::iterator queuedResult =
             mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
@@ -2269,7 +2274,8 @@
                 CameraMetadata metadata;
                 metadata = result->result;
                 sendCaptureResult(metadata, request.resultExtras,
-                    collectedPartialResult, frameNumber, hasInputBufferInRequest);
+                    collectedPartialResult, frameNumber, hasInputBufferInRequest,
+                    request.aeTriggerCancelOverride);
             }
         }
 
@@ -2432,7 +2438,7 @@
             // send pending result and buffers
             sendCaptureResult(r.pendingMetadata, r.resultExtras,
                 r.partialResult.collectedResult, msg.frame_number,
-                r.hasInputBuffer);
+                r.hasInputBuffer, r.aeTriggerCancelOverride);
             returnOutputBuffers(r.pendingOutputBuffers.array(),
                 r.pendingOutputBuffers.size(), r.shutterTimestamp);
             r.pendingOutputBuffers.clear();
@@ -2481,6 +2487,17 @@
         mCurrentPreCaptureTriggerId(0),
         mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
     mStatusId = statusTracker->addComponent();
+
+    mAeLockAvailable = false;
+    sp<Camera3Device> p = parent.promote();
+    if (p != NULL) {
+        camera_metadata_ro_entry aeLockAvailable =
+                p->info().find(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
+        if (aeLockAvailable.count > 0) {
+            mAeLockAvailable = (aeLockAvailable.data.u8[0] ==
+                    ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
+        }
+    }
 }
 
 void Camera3Device::RequestThread::setNotificationListener(
@@ -2687,6 +2704,65 @@
     mRequestSignal.signal();
 }
 
+
+/**
+ * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so
+ * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF
+ * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides
+ * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the
+ * request.
+ */
+void Camera3Device::RequestThread::handleAePrecaptureCancelRequest(sp<CaptureRequest> request) {
+    request->mAeTriggerCancelOverride.applyAeLock = false;
+    request->mAeTriggerCancelOverride.applyAePrecaptureTrigger = false;
+
+    if (mHal3Device->common.version > CAMERA_DEVICE_API_VERSION_3_2) {
+        return;
+    }
+
+    camera_metadata_entry_t aePrecaptureTrigger =
+            request->mSettings.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
+    if (aePrecaptureTrigger.count > 0 &&
+            aePrecaptureTrigger.data.u8[0] == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) {
+        // Always override CANCEL to IDLE
+        uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
+        request->mSettings.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger, 1);
+        request->mAeTriggerCancelOverride.applyAePrecaptureTrigger = true;
+        request->mAeTriggerCancelOverride.aePrecaptureTrigger =
+                ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL;
+
+        if (mAeLockAvailable == true) {
+            camera_metadata_entry_t aeLock = request->mSettings.find(ANDROID_CONTROL_AE_LOCK);
+            if (aeLock.count == 0 ||  aeLock.data.u8[0] == ANDROID_CONTROL_AE_LOCK_OFF) {
+                uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON;
+                request->mSettings.update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
+                request->mAeTriggerCancelOverride.applyAeLock = true;
+                request->mAeTriggerCancelOverride.aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+            }
+        }
+    }
+}
+
+/**
+ * Override result metadata for cancelling AE precapture trigger applied in
+ * handleAePrecaptureCancelRequest().
+ */
+void Camera3Device::overrideResultForPrecaptureCancel(
+        CameraMetadata *result, const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
+    if (aeTriggerCancelOverride.applyAeLock) {
+        // Only devices <= v3.2 should have this override
+        assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
+        result->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1);
+    }
+
+    if (aeTriggerCancelOverride.applyAePrecaptureTrigger) {
+        // Only devices <= v3.2 should have this override
+        assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
+        result->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+                &aeTriggerCancelOverride.aePrecaptureTrigger, 1);
+    }
+}
+
 bool Camera3Device::RequestThread::threadLoop() {
 
     status_t res;
@@ -2826,7 +2902,8 @@
 
     res = parent->registerInFlight(request.frame_number,
             totalNumBuffers, nextRequest->mResultExtras,
-            /*hasInput*/request.input_buffer != NULL);
+            /*hasInput*/request.input_buffer != NULL,
+            nextRequest->mAeTriggerCancelOverride);
     ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
            ", burstId = %" PRId32 ".",
             __FUNCTION__,
@@ -3052,6 +3129,9 @@
             }
         }
     }
+
+    handleAePrecaptureCancelRequest(nextRequest);
+
     mNextRequest = nextRequest;
 
     return nextRequest;
@@ -3441,6 +3521,7 @@
         const camera3_capture_result *result) {
     Camera3Device *d =
             const_cast<Camera3Device*>(static_cast<const Camera3Device*>(cb));
+
     d->processCaptureResult(result);
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e2fd8d4..bb4bcc4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -234,6 +234,13 @@
 
     /**** End scope for mLock ****/
 
+    typedef struct AeTriggerCancelOverride {
+        bool applyAeLock;
+        uint8_t aeLock;
+        bool applyAePrecaptureTrigger;
+        uint8_t aePrecaptureTrigger;
+    } AeTriggerCancelOverride_t;
+
     class CaptureRequest : public LightRefBase<CaptureRequest> {
       public:
         CameraMetadata                      mSettings;
@@ -242,6 +249,9 @@
         Vector<sp<camera3::Camera3OutputStreamInterface> >
                                             mOutputStreams;
         CaptureResultExtras                 mResultExtras;
+        // Used to cancel AE precapture trigger for devices doesn't support
+        // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
+        AeTriggerCancelOverride_t           mAeTriggerCancelOverride;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -492,6 +502,9 @@
         // If the input request is in mRepeatingRequests. Must be called with mRequestLock hold
         bool isRepeatingRequestLocked(const sp<CaptureRequest>);
 
+        // Handle AE precapture trigger cancel for devices <= CAMERA_DEVICE_API_VERSION_3_2.
+        void handleAePrecaptureCancelRequest(sp<CaptureRequest> request);
+
         wp<Camera3Device>  mParent;
         wp<camera3::StatusTracker>  mStatusTracker;
         camera3_device_t  *mHal3Device;
@@ -540,6 +553,9 @@
         uint32_t           mCurrentPreCaptureTriggerId;
 
         int64_t            mRepeatingLastFrameNumber;
+
+        // Whether the device supports AE lock
+        bool               mAeLockAvailable;
     };
     sp<RequestThread> mRequestThread;
 
@@ -562,7 +578,6 @@
         // If this request has any input buffer
         bool hasInputBuffer;
 
-
         // The last metadata that framework receives from HAL and
         // not yet send out because the shutter event hasn't arrived.
         // It's added by process_capture_result and sent when framework
@@ -575,6 +590,10 @@
         // the shutter event.
         Vector<camera3_stream_buffer_t> pendingOutputBuffers;
 
+        // Used to cancel AE precapture trigger for devices doesn't support
+        // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
+        AeTriggerCancelOverride_t aeTriggerCancelOverride;
+
 
         // Fields used by the partial result only
         struct PartialResultInFlight {
@@ -595,36 +614,20 @@
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(0),
-                hasInputBuffer(false){
+                hasInputBuffer(false),
+                aeTriggerCancelOverride({false, 0, false, 0}){
         }
 
-        InFlightRequest(int numBuffers) :
-                shutterTimestamp(0),
-                sensorTimestamp(0),
-                requestStatus(OK),
-                haveResultMetadata(false),
-                numBuffersLeft(numBuffers),
-                hasInputBuffer(false){
-        }
-
-        InFlightRequest(int numBuffers, CaptureResultExtras extras) :
+        InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
+                AeTriggerCancelOverride aeTriggerCancelOverride) :
                 shutterTimestamp(0),
                 sensorTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(numBuffers),
                 resultExtras(extras),
-                hasInputBuffer(false){
-        }
-
-        InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput) :
-                shutterTimestamp(0),
-                sensorTimestamp(0),
-                requestStatus(OK),
-                haveResultMetadata(false),
-                numBuffersLeft(numBuffers),
-                resultExtras(extras),
-                hasInputBuffer(hasInput){
+                hasInputBuffer(hasInput),
+                aeTriggerCancelOverride(aeTriggerCancelOverride){
         }
     };
 
@@ -635,7 +638,8 @@
     InFlightMap            mInFlightMap;
 
     status_t registerInFlight(uint32_t frameNumber,
-            int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput);
+            int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
+            const AeTriggerCancelOverride_t &aeTriggerCancelOverride);
 
     /**
      * For the partial result, check if all 3A state fields are available
@@ -653,6 +657,14 @@
     template<typename T>
     bool insert3AResult(CameraMetadata &result, int32_t tag, const T* value,
             uint32_t frameNumber);
+
+    /**
+     * Override result metadata for cancelling AE precapture trigger applied in
+     * handleAePrecaptureCancelRequest().
+     */
+    void overrideResultForPrecaptureCancel(CameraMetadata* result,
+            const AeTriggerCancelOverride_t &aeTriggerCancelOverride);
+
     /**
      * Tracking for idle detection
      */
@@ -738,7 +750,7 @@
     void sendCaptureResult(CameraMetadata &pendingMetadata,
             CaptureResultExtras &resultExtras,
             CameraMetadata &collectedPartialResult, uint32_t frameNumber,
-            bool reprocess);
+            bool reprocess, const AeTriggerCancelOverride_t &aeTriggerCancelOverride);
 
     /**** Scope for mInFlightLock ****/