Camera: fix early timeout for long exposure captures

Bug: 21033386
Change-Id: Id25952fcf3ca7ff3b5cac80c3e90617bffb5859c
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 035e70b..ad9786e 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -49,6 +49,7 @@
 
     # Seconds timeout on each socket operation.
     SOCK_TIMEOUT = 10.0
+    SEC_TO_NSEC = 1000*1000*1000.0
 
     PACKAGE = 'com.android.cts.verifier.camera.its'
     INTENT_START = 'com.android.cts.verifier.camera.its.START'
@@ -483,6 +484,18 @@
                 "dng" in formats and "raw10" in formats or \
                 "raw" in formats and "raw10" in formats:
             raise its.error.Error('Different raw formats not supported')
+
+        # Detect long exposure time and set timeout accordingly
+        longest_exp_time = 0
+        for req in cmd["captureRequests"]:
+            if "android.sensor.exposureTime" in req and \
+                    req["android.sensor.exposureTime"] > longest_exp_time:
+                longest_exp_time = req["android.sensor.exposureTime"]
+
+        extended_timeout = longest_exp_time / self.SEC_TO_NSEC + \
+                self.SOCK_TIMEOUT
+        self.sock.settimeout(extended_timeout)
+
         print "Capturing %d frame%s with %d format%s [%s]" % (
                   ncap, "s" if ncap>1 else "", nsurf, "s" if nsurf>1 else "",
                   ",".join(formats))
@@ -524,6 +537,7 @@
                 obj["metadata"] = mds[i]
                 objs.append(obj)
             rets.append(objs if ncap>1 else objs[0])
+        self.sock.settimeout(self.SOCK_TIMEOUT)
         return rets if len(rets)>1 else rets[0]
 
 def report_result(camera_id, success, summary_path=None):
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index e3d0b6d..e83c40c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -1094,25 +1094,34 @@
             }
 
             // Initiate the captures.
+            long maxExpTimeNs = -1;
             for (int i = 0; i < requests.size(); i++) {
+                CaptureRequest.Builder req = requests.get(i);
                 // For DNG captures, need the LSC map to be available.
                 if (mCaptureRawIsDng) {
-                    requests.get(i).set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, 1);
+                    req.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, 1);
+                }
+                Long expTimeNs = req.get(CaptureRequest.SENSOR_EXPOSURE_TIME);
+                if (expTimeNs != null && expTimeNs > maxExpTimeNs) {
+                    maxExpTimeNs = expTimeNs;
                 }
 
-                CaptureRequest.Builder req = requests.get(i);
                 for (int j = 0; j < numSurfaces; j++) {
                     req.addTarget(mCaptureReaders[j].getSurface());
                 }
                 mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
             }
 
+            long timeout = TIMEOUT_CALLBACK * 1000;
+            if (maxExpTimeNs > 0) {
+                timeout += maxExpTimeNs / 1000000; // ns to ms
+            }
             // Make sure all callbacks have been hit (wait until captures are done).
             // If no timeouts are received after a timeout, then fail.
             int currentCount = mCountCallbacksRemaining.get();
             while (currentCount > 0) {
                 try {
-                    Thread.sleep(TIMEOUT_CALLBACK*1000);
+                    Thread.sleep(timeout);
                 } catch (InterruptedException e) {
                     throw new ItsException("Timeout failure", e);
                 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index d5bd4b5..598b7cb 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -1165,7 +1165,9 @@
                 changeExposure(requestBuilder, expTimes[i], sensitivities[j]);
                 mSession.capture(requestBuilder.build(), listener, mHandler);
 
-                CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+                // make sure timeout is long enough for long exposure time
+                long timeout = WAIT_FOR_RESULT_TIMEOUT_MS + expTimes[i];
+                CaptureResult result = listener.getCaptureResult(timeout);
                 long resultExpTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
                 int resultSensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
                 validateExposureTime(expTimes[i], resultExpTime);