Add experimental camera session prepare API.

Bug: 18949148
Change-Id: I8f73e68ea2e3acc60d98954106f364d13f439a82
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0a4440f..cf47bc8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1380,6 +1380,10 @@
 }
 
 status_t Camera3Device::prepare(int streamId) {
+    return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
+}
+
+status_t Camera3Device::prepare(int maxCount, int streamId) {
     ATRACE_CALL();
     ALOGV("%s: Camera %d: Preparing stream %d", __FUNCTION__, mId, streamId);
     Mutex::Autolock il(mInterfaceLock);
@@ -1404,7 +1408,7 @@
         return BAD_VALUE;
     }
 
-    return mPreparerThread->prepare(stream);
+    return mPreparerThread->prepare(maxCount, stream);
 }
 
 status_t Camera3Device::tearDown(int streamId) {
@@ -3455,12 +3459,12 @@
     clear();
 }
 
-status_t Camera3Device::PreparerThread::prepare(sp<Camera3StreamInterface>& stream) {
+status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
     status_t res;
 
     Mutex::Autolock l(mLock);
 
-    res = stream->startPrepare();
+    res = stream->startPrepare(maxCount);
     if (res == OK) {
         // No preparation needed, fire listener right off
         ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 8bd0f8e..3ce6b0d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -62,6 +62,7 @@
             public CameraDeviceBase,
             private camera3_callback_ops {
   public:
+
     Camera3Device(int id);
 
     virtual ~Camera3Device();
@@ -143,6 +144,8 @@
 
     virtual status_t tearDown(int streamId);
 
+    virtual status_t prepare(int maxCount, int streamId);
+
     virtual uint32_t getDeviceVersion();
 
     virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
@@ -687,10 +690,11 @@
         void setNotificationListener(NotificationListener *listener);
 
         /**
-         * Queue up a stream to be prepared. Streams are processed by
-         * a background thread in FIFO order
+         * Queue up a stream to be prepared. Streams are processed by a background thread in FIFO
+         * order.  Pre-allocate up to maxCount buffers for the stream, or the maximum number needed
+         * for the pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
          */
-        status_t prepare(sp<camera3::Camera3StreamInterface>& stream);
+        status_t prepare(int maxCount, sp<camera3::Camera3StreamInterface>& stream);
 
         /**
          * Cancel all current and pending stream preparation
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 2527fd6..7163d62 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -53,7 +53,8 @@
     mName(String8::format("Camera3Stream[%d]", id)),
     mMaxSize(maxSize),
     mState(STATE_CONSTRUCTED),
-    mStatusId(StatusTracker::NO_STATUS_ID) {
+    mStatusId(StatusTracker::NO_STATUS_ID),
+    mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) {
 
     camera3_stream::stream_type = type;
     camera3_stream::width = width;
@@ -252,12 +253,18 @@
     return mStreamUnpreparable;
 }
 
-status_t Camera3Stream::startPrepare() {
+status_t Camera3Stream::startPrepare(int maxCount) {
     ATRACE_CALL();
 
     Mutex::Autolock l(mLock);
     status_t res = OK;
 
+    if (maxCount < 0) {
+        ALOGE("%s: Stream %d: Can't prepare stream if max buffer count (%d) is < 0",
+                __FUNCTION__, mId, maxCount);
+        return BAD_VALUE;
+    }
+
     // This function should be only called when the stream is configured already.
     if (mState != STATE_CONFIGURED) {
         ALOGE("%s: Stream %d: Can't prepare stream if stream is not in CONFIGURED "
@@ -279,9 +286,19 @@
         return INVALID_OPERATION;
     }
 
+
+
+    size_t pipelineMax = getBufferCountLocked();
+    size_t clampedCount = (pipelineMax < static_cast<size_t>(maxCount)) ?
+            pipelineMax : static_cast<size_t>(maxCount);
+    size_t bufferCount = (maxCount == Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) ?
+            pipelineMax : clampedCount;
+
+    mPrepared = bufferCount <= mLastMaxCount;
+
     if (mPrepared) return OK;
 
-    size_t bufferCount = getBufferCountLocked();
+    mLastMaxCount = bufferCount;
 
     mPreparedBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
     mPreparedBufferIdx = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index bab2177..753280b 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -188,7 +188,9 @@
 
     /**
      * Start stream preparation. May only be called in the CONFIGURED state,
-     * when no valid buffers have yet been returned to this stream.
+     * when no valid buffers have yet been returned to this stream. Prepares
+     * up to maxCount buffers, or the maximum number of buffers needed by the
+     * pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
      *
      * If no prepartion is necessary, returns OK and does not transition to
      * PREPARING state. Otherwise, returns NOT_ENOUGH_DATA and transitions
@@ -204,7 +206,7 @@
      *    INVALID_OPERATION if called when not in CONFIGURED state, or a
      *        valid buffer has already been returned to this stream.
      */
-    status_t         startPrepare();
+    status_t         startPrepare(int maxCount);
 
     /**
      * Check if the stream is mid-preparing.
@@ -444,6 +446,9 @@
     Vector<camera3_stream_buffer_t> mPreparedBuffers;
     size_t mPreparedBufferIdx;
 
+    // Number of buffers allocated on last prepare call.
+    int mLastMaxCount;
+
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index c086eaf..54009ae 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -34,6 +34,11 @@
  */
 class Camera3StreamInterface : public virtual RefBase {
   public:
+
+    enum {
+        ALLOCATE_PIPELINE_MAX = 0, // Allocate max buffers used by a given surface
+    };
+
     /**
      * Get the stream's ID
      */
@@ -98,7 +103,9 @@
 
     /**
      * Start stream preparation. May only be called in the CONFIGURED state,
-     * when no valid buffers have yet been returned to this stream.
+     * when no valid buffers have yet been returned to this stream. Prepares
+     * up to maxCount buffers, or the maximum number of buffers needed by the
+     * pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
      *
      * If no prepartion is necessary, returns OK and does not transition to
      * PREPARING state. Otherwise, returns NOT_ENOUGH_DATA and transitions
@@ -112,7 +119,7 @@
      *    INVALID_OPERATION if called when not in CONFIGURED state, or a
      *        valid buffer has already been returned to this stream.
      */
-    virtual status_t startPrepare() = 0;
+    virtual status_t startPrepare(int maxCount) = 0;
 
     /**
      * Check if the stream is mid-preparing.