Merge "QCamera2: HAL3: Adjust buffer timeout depending on expected duration" into oc-dr1-dev
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index 7be6062..e75aff7 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -96,7 +96,7 @@
 #define MAX_HFR_BATCH_SIZE     (8)
 #define REGIONS_TUPLE_COUNT    5
 // Set a threshold for detection of missing buffers //seconds
-#define MISSING_REQUEST_BUF_TIMEOUT 10
+#define MISSING_REQUEST_BUF_TIMEOUT 5
 #define MISSING_HDRPLUS_REQUEST_BUF_TIMEOUT 30
 #define FLUSH_TIMEOUT 3
 #define METADATA_MAP_SIZE(MAP) (sizeof(MAP)/sizeof(MAP[0]))
@@ -478,6 +478,8 @@
       mMinProcessedFrameDuration(0),
       mMinJpegFrameDuration(0),
       mMinRawFrameDuration(0),
+      mExpectedFrameDuration(0),
+      mExpectedInflightDuration(0),
       mMetaFrameCount(0U),
       mUpdateDebugLevel(false),
       mCallbacks(callbacks),
@@ -799,6 +801,13 @@
     }
     if (i->settings != NULL)
         free_camera_metadata((camera_metadata_t*)i->settings);
+
+    mExpectedInflightDuration -= i->expectedFrameDuration;
+    if (mExpectedInflightDuration < 0) {
+        LOGE("Negative expected in-flight duration!");
+        mExpectedInflightDuration = 0;
+    }
+
     return mPendingRequestsList.erase(i);
 }
 
@@ -3023,6 +3032,8 @@
         req.mPendingBufferList.clear();
     }
     mPendingBuffersMap.mPendingBuffersInRequest.clear();
+    mExpectedInflightDuration = 0;
+    mExpectedFrameDuration = 0;
 
     mCurJpegMeta.clear();
     //Get min frame duration for this streams configuration
@@ -3651,6 +3662,9 @@
             // HDR+ request is done. So allow a longer timeout.
             timeout = (mHdrPlusPendingRequests.size() > 0) ?
                     MISSING_HDRPLUS_REQUEST_BUF_TIMEOUT : MISSING_REQUEST_BUF_TIMEOUT;
+            if (timeout < mExpectedInflightDuration) {
+                timeout = mExpectedInflightDuration;
+            }
         }
 
         if ( (currentSysTime - req.timestamp) > s2ns(timeout) ) {
@@ -5482,6 +5496,8 @@
     }
     pendingRequest.fwkCacMode = mCacMode;
     pendingRequest.hdrplus = hdrPlusRequest;
+    pendingRequest.expectedFrameDuration = mExpectedFrameDuration;
+    mExpectedInflightDuration += mExpectedFrameDuration;
 
     // extract enableZsl info
     if (gExposeEnableZslKey) {
@@ -11442,6 +11458,89 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : getExpectedFrameDuration
+ *
+ * DESCRIPTION: Extract the maximum frame duration from either exposure or frame
+ *              duration
+ *
+ * PARAMETERS :
+ *   @request   : request settings
+ *   @frameDuration : The maximum frame duration in nanoseconds
+ *
+ * RETURN     : None
+ *==========================================================================*/
+void QCamera3HardwareInterface::getExpectedFrameDuration(
+        const camera_metadata_t *request, nsecs_t *frameDuration /*out*/) {
+    if (nullptr == frameDuration) {
+        return;
+    }
+
+    camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
+    find_camera_metadata_ro_entry(request,
+            ANDROID_SENSOR_EXPOSURE_TIME,
+            &e);
+    if (e.count > 0) {
+        *frameDuration = e.data.i64[0];
+    }
+    find_camera_metadata_ro_entry(request,
+            ANDROID_SENSOR_FRAME_DURATION,
+            &e);
+    if (e.count > 0) {
+        *frameDuration = std::max(e.data.i64[0], *frameDuration);
+    }
+}
+
+/*===========================================================================
+ * FUNCTION   : calculateMaxExpectedDuration
+ *
+ * DESCRIPTION: Calculate the expected frame duration in nanoseconds given the
+ *              current camera settings.
+ *
+ * PARAMETERS :
+ *   @request   : request settings
+ *
+ * RETURN     : Expected frame duration in nanoseconds.
+ *==========================================================================*/
+nsecs_t QCamera3HardwareInterface::calculateMaxExpectedDuration(
+        const camera_metadata_t *request) {
+    nsecs_t maxExpectedDuration = kDefaultExpectedDuration;
+    camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
+    find_camera_metadata_ro_entry(request, ANDROID_CONTROL_MODE, &e);
+    if (e.count == 0) {
+        return maxExpectedDuration;
+    }
+
+    if (e.data.u8[0] == ANDROID_CONTROL_MODE_OFF) {
+        getExpectedFrameDuration(request, &maxExpectedDuration /*out*/);
+    }
+
+    if (e.data.u8[0] != ANDROID_CONTROL_MODE_AUTO) {
+        return maxExpectedDuration;
+    }
+
+    find_camera_metadata_ro_entry(request, ANDROID_CONTROL_AE_MODE, &e);
+    if (e.count == 0) {
+        return maxExpectedDuration;
+    }
+
+    switch (e.data.u8[0]) {
+        case ANDROID_CONTROL_AE_MODE_OFF:
+            getExpectedFrameDuration(request, &maxExpectedDuration /*out*/);
+            break;
+        default:
+            find_camera_metadata_ro_entry(request,
+                    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+                    &e);
+            if (e.count > 1) {
+                maxExpectedDuration = 1e9 / e.data.u8[0];
+            }
+            break;
+    }
+
+    return maxExpectedDuration;
+}
+
+/*===========================================================================
  * FUNCTION   : setFrameParameters
  *
  * DESCRIPTION: set parameters per frame as requested in the metadata from
@@ -11497,6 +11596,7 @@
     }
 
     if(request->settings != NULL){
+        mExpectedFrameDuration = calculateMaxExpectedDuration(request->settings);
         rc = translateToHalMetadata(request, mParameters, snapshotStreamId);
         if (blob_request)
             memcpy(mPrevParameters, mParameters, sizeof(metadata_buffer_t));
@@ -14133,6 +14233,8 @@
     mShutterDispatcher.clear();
     mOutputBufferDispatcher.clear(/*clearConfiguredStreams*/false);
     mPendingBuffersMap.mPendingBuffersInRequest.clear();
+    mExpectedFrameDuration = 0;
+    mExpectedInflightDuration = 0;
     LOGH("Cleared all the pending buffers ");
 
     return NO_ERROR;
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.h b/msm8998/QCamera2/HAL3/QCamera3HWI.h
index a3248a1..9ef806f 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.h
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.h
@@ -579,6 +579,7 @@
         int blob_request;
         uint8_t bUseFirstPartial; // Use first available partial result in case of jumpstart.
         nsecs_t timestamp;
+        nsecs_t expectedFrameDuration;
         camera3_stream_buffer_t *input_buffer;
         const camera_metadata_t *settings;
         const camera_metadata_t *resultMetadata; // Result metadata for this request.
@@ -639,6 +640,9 @@
     int64_t mMinProcessedFrameDuration;
     int64_t mMinJpegFrameDuration;
     int64_t mMinRawFrameDuration;
+    nsecs_t mExpectedFrameDuration;
+    nsecs_t mExpectedInflightDuration;
+    static const nsecs_t kDefaultExpectedDuration = 100000000; // 100 ms
 
     uint32_t mMetaFrameCount;
     bool    mUpdateDebugLevel;
@@ -820,6 +824,9 @@
             const camera_metadata_t &resultMetadata) override;
     void onFailedCaptureResult(pbcamera::CaptureResult *failedResult) override;
 
+    nsecs_t calculateMaxExpectedDuration(const camera_metadata_t *request);
+    void getExpectedFrameDuration(const camera_metadata_t *request, nsecs_t *frameDuration);
+
     // Map from frame number to frame. Must be protected by mHdrPlusPendingRequestsLock.
     std::map<uint32_t, HdrPlusPendingRequest> mHdrPlusPendingRequests;
     Mutex mHdrPlusPendingRequestsLock;