Merge "Camera2: Add flush support" into klp-dev
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 73fec72..1e5822f 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -41,6 +41,7 @@
     CREATE_DEFAULT_REQUEST,
     GET_CAMERA_INFO,
     WAIT_UNTIL_IDLE,
+    FLUSH
 };
 
 namespace {
@@ -196,6 +197,16 @@
         return reply.readInt32();
     }
 
+    virtual status_t flush()
+    {
+        ALOGV("flush");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+        remote()->transact(FLUSH, data, &reply);
+        reply.readExceptionCode();
+        return reply.readInt32();
+    }
+
 private:
 
 
@@ -325,6 +336,12 @@
             reply->writeInt32(waitUntilIdle());
             return NO_ERROR;
         } break;
+        case FLUSH: {
+            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+            reply->writeNoException();
+            reply->writeInt32(flush());
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index 45988d0..f71f302 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -63,6 +63,9 @@
 
     // Wait until all the submitted requests have finished processing
     virtual status_t        waitUntilIdle() =  0;
+
+    // Flush all pending and in-progress work as quickly as possible.
+    virtual status_t        flush() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 414316d..289ba06 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -436,6 +436,20 @@
     return res;
 }
 
+status_t CameraDeviceClient::flush() {
+    ATRACE_CALL();
+    ALOGV("%s", __FUNCTION__);
+
+    status_t res = OK;
+    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) return DEAD_OBJECT;
+
+    return mDevice->flush();
+}
+
 status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
     String8 result;
     result.appendFormat("CameraDeviceClient[%d] (%p) PID: %d, dump:\n",
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 21d633c..c6b6336 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -89,6 +89,10 @@
 
     // Wait until all the submitted requests have finished processing
     virtual status_t      waitUntilIdle();
+
+    // Flush all active and pending requests as fast as possible
+    virtual status_t      flush();
+
     /**
      * Interface used by CameraService
      */
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index aa92bec..ebbd4ea 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -209,6 +209,13 @@
      */
     virtual status_t pushReprocessBuffer(int reprocessStreamId,
             buffer_handle_t *buffer, wp<BufferReleasedListener> listener) = 0;
+
+    /**
+     * Flush all pending and in-flight requests. Blocks until flush is
+     * complete.
+     */
+    virtual status_t flush() = 0;
+
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 710d0e9..fe2cd77 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -567,6 +567,13 @@
     return res;
 }
 
+status_t Camera2Device::flush() {
+    ATRACE_CALL();
+
+    mRequestQueue.clear();
+    return waitUntilDrained();
+}
+
 /**
  * Camera2Device::MetadataQueue
  */
@@ -591,9 +598,7 @@
 
 Camera2Device::MetadataQueue::~MetadataQueue() {
     ATRACE_CALL();
-    Mutex::Autolock l(mMutex);
-    freeBuffers(mEntries.begin(), mEntries.end());
-    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+    clear();
 }
 
 // Connect to camera2 HAL as consumer (input requests/reprocessing)
@@ -784,6 +789,23 @@
     return signalConsumerLocked();
 }
 
+status_t Camera2Device::MetadataQueue::clear()
+{
+    ATRACE_CALL();
+    ALOGV("%s: E", __FUNCTION__);
+
+    Mutex::Autolock l(mMutex);
+
+    // Clear streaming slot
+    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+    mStreamSlotCount = 0;
+
+    // Clear request queue
+    freeBuffers(mEntries.begin(), mEntries.end());
+    mCount = 0;
+    return OK;
+}
+
 status_t Camera2Device::MetadataQueue::dump(int fd,
         const Vector<String16>& /*args*/) {
     ATRACE_CALL();
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 8945ec2..2aa22a2 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -67,6 +67,8 @@
     virtual status_t triggerPrecaptureMetering(uint32_t id);
     virtual status_t pushReprocessBuffer(int reprocessStreamId,
             buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
+    // Flush implemented as just a wait
+    virtual status_t flush();
   private:
     const int mId;
     camera2_device_t *mHal2Device;
@@ -113,6 +115,9 @@
         status_t setStreamSlot(camera_metadata_t *buf);
         status_t setStreamSlot(const List<camera_metadata_t*> &bufs);
 
+        // Clear the request queue and the streaming slot
+        status_t clear();
+
         status_t dump(int fd, const Vector<String16>& args);
 
       private:
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0a4a24c..7f2ec7a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -952,6 +952,16 @@
     return INVALID_OPERATION;
 }
 
+status_t Camera3Device::flush() {
+    ATRACE_CALL();
+    ALOGV("%s: Camera %d: Flushing all requests", __FUNCTION__, mId);
+
+    Mutex::Autolock l(mLock);
+
+    mRequestThread->clear();
+    return mHal3Device->ops->flush(mHal3Device);
+}
+
 /**
  * Camera3Device private methods
  */
@@ -1488,6 +1498,14 @@
     return OK;
 }
 
+status_t Camera3Device::RequestThread::clear() {
+    Mutex::Autolock l(mRequestLock);
+    mRepeatingRequests.clear();
+    mRequestQueue.clear();
+    mTriggerMap.clear();
+    return OK;
+}
+
 void Camera3Device::RequestThread::setPaused(bool paused) {
     Mutex::Autolock l(mPauseLock);
     mDoPause = paused;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 76c08ae..99e1cc8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -124,6 +124,8 @@
     virtual status_t pushReprocessBuffer(int reprocessStreamId,
             buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
 
+    virtual status_t flush();
+
   private:
     static const size_t        kInFlightWarnLimit = 20;
     static const nsecs_t       kShutdownTimeout   = 5000000000; // 5 sec
@@ -249,6 +251,11 @@
         status_t queueRequest(sp<CaptureRequest> request);
 
         /**
+         * Remove all queued and repeating requests, and pending triggers
+         */
+        status_t clear();
+
+        /**
          * Queue a trigger to be dispatched with the next outgoing
          * process_capture_request. The settings for that request only
          * will be temporarily rewritten to add the trigger tag/value.