CameraService: Add support for burst capture and repeating burst.

Bug: 10749500
Change-Id: I292a485b222e5cf97388d76bf0d956a6ac54bb2f
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 187220e..a02381d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -159,7 +159,7 @@
 
     int32_t requestId = mRequestIdCounter++;
     metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
-    ALOGV("%s: Camera %d: Submitting request with ID %d",
+    ALOGV("%s: Camera %d: Creating request with ID %d",
           __FUNCTION__, mCameraId, requestId);
 
     if (streaming) {
@@ -186,6 +186,116 @@
     return res;
 }
 
+status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests,
+                                               bool streaming) {
+    ATRACE_CALL();
+    ALOGV("%s-start of function", __FUNCTION__);
+
+    status_t res;
+    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) return DEAD_OBJECT;
+
+    if (requests.empty()) {
+        ALOGE("%s: Camera %d: Sent null request. Rejecting request.",
+              __FUNCTION__, mCameraId);
+        return BAD_VALUE;
+    }
+
+    List<const CameraMetadata> metadataRequestList;
+    int32_t requestId = mRequestIdCounter;
+    uint32_t loopCounter = 0;
+
+    for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) {
+        sp<CaptureRequest> request = *it;
+        if (request == 0) {
+            ALOGE("%s: Camera %d: Sent null request.",
+                    __FUNCTION__, mCameraId);
+            return BAD_VALUE;
+        }
+
+        CameraMetadata metadata(request->mMetadata);
+        if (metadata.isEmpty()) {
+            ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.",
+                   __FUNCTION__, mCameraId);
+            return BAD_VALUE;
+        } else if (request->mSurfaceList.isEmpty()) {
+            ALOGE("%s: Camera %d: Requests must have at least one surface target. "
+                  "Rejecting request.", __FUNCTION__, mCameraId);
+            return BAD_VALUE;
+        }
+
+        if (!enforceRequestPermissions(metadata)) {
+            // Callee logs
+            return PERMISSION_DENIED;
+        }
+
+        /**
+         * Write in the output stream IDs which we calculate from
+         * the capture request's list of surface targets
+         */
+        Vector<int32_t> outputStreamIds;
+        outputStreamIds.setCapacity(request->mSurfaceList.size());
+        for (Vector<sp<Surface> >::iterator surfaceIt = 0;
+                surfaceIt != request->mSurfaceList.end(); ++surfaceIt) {
+            sp<Surface> surface = *surfaceIt;
+            if (surface == 0) continue;
+
+            sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
+            int idx = mStreamMap.indexOfKey(gbp->asBinder());
+
+            // Trying to submit request with surface that wasn't created
+            if (idx == NAME_NOT_FOUND) {
+                ALOGE("%s: Camera %d: Tried to submit a request with a surface that"
+                      " we have not called createStream on",
+                      __FUNCTION__, mCameraId);
+                return BAD_VALUE;
+            }
+
+            int streamId = mStreamMap.valueAt(idx);
+            outputStreamIds.push_back(streamId);
+            ALOGV("%s: Camera %d: Appending output stream %d to request",
+                  __FUNCTION__, mCameraId, streamId);
+        }
+
+        metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
+                        outputStreamIds.size());
+
+        metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
+        loopCounter++; // loopCounter starts from 1
+        ALOGV("%s: Camera %d: Creating request with ID %d (%d of %d)",
+              __FUNCTION__, mCameraId, requestId, loopCounter, requests.size());
+
+        metadataRequestList.push_back(metadata);
+    }
+    mRequestIdCounter++;
+
+    if (streaming) {
+        res = mDevice->setStreamingRequestList(metadataRequestList);
+        if (res != OK) {
+            ALOGE("%s: Camera %d:  Got error %d after trying to set streaming "
+                  "request", __FUNCTION__, mCameraId, res);
+        } else {
+            mStreamingRequestList.push_back(requestId);
+        }
+    } else {
+        res = mDevice->captureList(metadataRequestList);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Got error %d after trying to set capture",
+                __FUNCTION__, mCameraId, res);
+        }
+    }
+
+    ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId);
+    if (res == OK) {
+        return requestId;
+    }
+
+    return res;
+}
+
 status_t CameraDeviceClient::cancelRequest(int requestId) {
     ATRACE_CALL();
     ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index b9c16aa..e96e1ae 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -63,8 +63,11 @@
      */
 
     // Note that the callee gets a copy of the metadata.
-    virtual int           submitRequest(sp<CaptureRequest> request,
-                                        bool streaming = false);
+    virtual status_t           submitRequest(sp<CaptureRequest> request,
+                                             bool streaming = false);
+    // List of requests are copied.
+    virtual status_t           submitRequestList(List<sp<CaptureRequest> > requests,
+                                                 bool streaming = false);
     virtual status_t      cancelRequest(int requestId);
 
     // Returns -EBUSY if device is not idle