Merge "Camera: Try to remove inflight requests during error notifications" into oc-dev
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 511fe94..80b6252 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -27,6 +27,7 @@
 #define NUM_SECONDS   10
 #define NANOS_PER_MICROSECOND ((int64_t)1000)
 #define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
+#define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * 1000)
 
 static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
     const char *modeText = "unknown";
@@ -43,6 +44,15 @@
     return modeText;
 }
 
+static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+    struct timespec time;
+    int result = clock_gettime(clockId, &time);
+    if (result < 0) {
+        return -errno;
+    }
+    return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
+}
+
 int main(int argc, char **argv)
 {
     (void)argc; // unused
@@ -56,7 +66,8 @@
     const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
     aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_I16;
 
-    const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+    //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+    const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
     aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -172,6 +183,26 @@
             goto finish;
         }
         framesLeft -= actual;
+
+        // Use timestamp to estimate latency.
+        {
+            int64_t presentationFrame;
+            int64_t presentationTime;
+            result = AAudioStream_getTimestamp(aaudioStream,
+                                               CLOCK_MONOTONIC,
+                                               &presentationFrame,
+                                               &presentationTime
+                                               );
+            if (result == AAUDIO_OK) {
+                int64_t elapsedNanos = getNanoseconds() - presentationTime;
+                int64_t elapsedFrames = actualSampleRate * elapsedNanos / NANOS_PER_SECOND;
+                int64_t currentFrame = presentationFrame + elapsedFrames;
+                int64_t framesWritten = AAudioStream_getFramesWritten(aaudioStream);
+                int64_t estimatedLatencyFrames = framesWritten - currentFrame;
+                int64_t estimatedLatencyMillis = estimatedLatencyFrames * 1000 / actualSampleRate;
+                printf("estimatedLatencyMillis %d\n", (int)estimatedLatencyMillis);
+            }
+        }
     }
 
     xRunCount = AAudioStream_getXRunCount(aaudioStream);
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index af0593d..6ac8554 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -50,7 +50,6 @@
     virtual aaudio_result_t requestFlush() = 0;
     virtual aaudio_result_t requestStop() = 0;
 
-    // TODO use aaudio_clockid_t all the way down to AudioClock
     virtual aaudio_result_t getTimestamp(clockid_t clockId,
                                        int64_t *framePosition,
                                        int64_t *timeNanoseconds) = 0;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index dd040a0..d380eb8 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -25,6 +25,7 @@
 
 #include "AudioClock.h"
 #include "AudioStreamRecord.h"
+#include "utility/AAudioUtilities.h"
 
 using namespace android;
 using namespace aaudio;
@@ -224,5 +225,28 @@
     return 192; // TODO add query to AudioRecord.cpp
 }
 
-// TODO implement getTimestamp
-
+aaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId,
+                                               int64_t *framePosition,
+                                               int64_t *timeNanoseconds) {
+    ExtendedTimestamp extendedTimestamp;
+    status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
+    if (status != NO_ERROR) {
+        return AAudioConvert_androidToAAudioResult(status);
+    }
+    // TODO Merge common code into AudioStreamLegacy after rebasing.
+    int timebase;
+    switch(clockId) {
+        case CLOCK_BOOTTIME:
+            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
+            break;
+        case CLOCK_MONOTONIC:
+            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
+            break;
+        default:
+            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
+            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            break;
+    }
+    status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
+    return AAudioConvert_androidToAAudioResult(status);
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index c8d389b..4667f05 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -44,10 +44,8 @@
     virtual aaudio_result_t requestStop() override;
 
     virtual aaudio_result_t getTimestamp(clockid_t clockId,
-                                       int64_t *framePosition,
-                                       int64_t *timeNanoseconds) override {
-        return AAUDIO_ERROR_UNIMPLEMENTED; // TODO
-    }
+                                         int64_t *framePosition,
+                                         int64_t *timeNanoseconds) override;
 
     virtual aaudio_result_t read(void *buffer,
                              int32_t numFrames,
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index e0a04c3..8bb6aee 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -20,11 +20,11 @@
 
 #include <stdint.h>
 #include <media/AudioTrack.h>
-
 #include <aaudio/AAudio.h>
-#include "AudioClock.h"
-#include "AudioStreamTrack.h"
 
+#include "utility/AudioClock.h"
+#include "AudioStreamTrack.h"
+#include "utility/AAudioUtilities.h"
 
 using namespace android;
 using namespace aaudio;
@@ -292,3 +292,29 @@
     }
     return AudioStream::getFramesRead();
 }
+
+aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
+                                     int64_t *framePosition,
+                                     int64_t *timeNanoseconds) {
+    ExtendedTimestamp extendedTimestamp;
+    status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
+    if (status != NO_ERROR) {
+        return AAudioConvert_androidToAAudioResult(status);
+    }
+    // TODO Merge common code into AudioStreamLegacy after rebasing.
+    int timebase;
+    switch(clockId) {
+        case CLOCK_BOOTTIME:
+            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
+            break;
+        case CLOCK_MONOTONIC:
+            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
+            break;
+        default:
+            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
+            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            break;
+    }
+    status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
+    return AAudioConvert_androidToAAudioResult(status);
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 1de07ce..7a53022 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -47,9 +47,7 @@
 
     virtual aaudio_result_t getTimestamp(clockid_t clockId,
                                        int64_t *framePosition,
-                                       int64_t *timeNanoseconds) override {
-        return AAUDIO_ERROR_UNIMPLEMENTED; // TODO call getTimestamp(ExtendedTimestamp *timestamp);
-    }
+                                       int64_t *timeNanoseconds) override;
 
     virtual aaudio_result_t write(const void *buffer,
                              int32_t numFrames,
diff --git a/media/ndk/Android.mk b/media/ndk/Android.mk
index 0984ca4..2c070af 100644
--- a/media/ndk/Android.mk
+++ b/media/ndk/Android.mk
@@ -47,6 +47,9 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 
+LOCAL_STATIC_LIBRARIES := \
+    libgrallocusage \
+
 LOCAL_SHARED_LIBRARIES := \
     libbinder \
     libmedia \
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index c0aee90..c449611 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -27,6 +27,7 @@
 #include <android_media_Utils.h>
 #include <android_runtime/android_view_Surface.h>
 #include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <grallocusage/GrallocUsageConversion.h>
 
 using namespace android;
 
@@ -260,7 +261,8 @@
     uint64_t consumerUsage;
     android_hardware_HardwareBuffer_convertToGrallocUsageBits(
             &producerUsage, &consumerUsage, mUsage0, mUsage1);
-    mHalUsage = consumerUsage;
+    // Strip out producerUsage here.
+    mHalUsage = android_convertGralloc1To0Usage(0, consumerUsage);
 
     sp<IGraphicBufferProducer> gbProducer;
     sp<IGraphicBufferConsumer> gbConsumer;
@@ -411,11 +413,9 @@
         }
 
         // Check if the producer buffer configurations match what ImageReader configured.
-        if ((bufferFmt != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
-                (readerWidth != bufferWidth || readerHeight != bufferHeight)) {
-            ALOGW("%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
-                    __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
-        }
+        ALOGV_IF(readerWidth != bufferWidth || readerHeight != bufferHeight,
+                "%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
+                __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
 
         // Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that
         // ImageReader requested has been supported from the producer side.
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 2be9362..8a7bb86 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -57,6 +57,9 @@
     utils/AutoConditionLock.cpp \
     utils/TagMonitor.cpp
 
+LOCAL_STATIC_LIBRARIES:= \
+    libgrallocusage
+
 LOCAL_SHARED_LIBRARIES:= \
     libui \
     liblog \
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index e03ec66..bfae9e9 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -304,7 +304,7 @@
         sp<IGraphicBufferProducer> producer;
         sp<IGraphicBufferConsumer> consumer;
         BufferQueue::createBufferQueue(&producer, &consumer);
-        mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL,
+        mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_READ,
             mBufferQueueDepth);
         mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
         sp<Surface> outSurface = new Surface(producer);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index f9b062a..4f788ae 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -145,12 +145,6 @@
             int32_t format, /*out*/ int32_t *id) = 0;
 
     /**
-     * Create an input reprocess stream that uses buffers from an existing
-     * output stream.
-     */
-    virtual status_t createReprocessStreamFromStream(int outputId, int *id) = 0;
-
-    /**
      * Get information about a given stream.
      */
     virtual status_t getStreamInfo(int id,
@@ -169,12 +163,6 @@
     virtual status_t deleteStream(int id) = 0;
 
     /**
-     * Delete reprocess stream. Must not be called if there are requests in
-     * flight which reference that stream.
-     */
-    virtual status_t deleteReprocessStream(int id) = 0;
-
-    /**
      * Take the currently-defined set of streams and configure the HAL to use
      * them. This is a long-running operation (may be several hundered ms).
      *
@@ -289,21 +277,6 @@
     virtual status_t triggerPrecaptureMetering(uint32_t id) = 0;
 
     /**
-     * Abstract interface for clients that want to listen to reprocess buffer
-     * release events
-     */
-    struct BufferReleasedListener : public virtual RefBase {
-        virtual void onBufferReleased(buffer_handle_t *handle) = 0;
-    };
-
-    /**
-     * Push a buffer to be reprocessed into a reprocessing stream, and
-     * provide a listener to call once the buffer is returned by the HAL
-     */
-    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.
      * Output lastFrameNumber is the last frame number of the previous streaming request.
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 9c058bc..0b57c50 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -17,6 +17,8 @@
 //#define LOG_NDEBUG 0
 
 #include <inttypes.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
 #include "CameraHardwareInterface.h"
 
 namespace android {
@@ -395,14 +397,14 @@
 }
 
 hardware::Return<Status>
-CameraHardwareInterface::setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) {
+CameraHardwareInterface::setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) {
     Status s = Status::INTERNAL_ERROR;
     ANativeWindow *a = mPreviewWindow.get();
     if (a == nullptr) {
         ALOGE("%s: preview window is null", __FUNCTION__);
         return s;
     }
-    mPreviewUsage = (int) usage;
+    mPreviewUsage = ::android_convertGralloc1To0Usage(usage, /*consumerUsage*/ 0);
     int rc = native_window_set_usage(a, mPreviewUsage);
     if (rc == OK) {
         cleanupCirculatingBuffers();
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index c2b0e9c..caeacef 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -461,7 +461,7 @@
     hardware::Return<hardware::camera::common::V1_0::Status>
             setCrop(int32_t left, int32_t top, int32_t right, int32_t bottom) override;
     hardware::Return<hardware::camera::common::V1_0::Status>
-            setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) override;
+            setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) override;
     hardware::Return<hardware::camera::common::V1_0::Status>
             setSwapInterval(int32_t interval) override;
     hardware::Return<void> getMinUndequeuedBufferCount(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 93d3d7f..980ba39 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -44,6 +44,8 @@
 #include <utils/Timers.h>
 #include <cutils/properties.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 
 #include "utils/CameraTraces.h"
@@ -495,11 +497,6 @@
     return dataSpace;
 }
 
-ConsumerUsageFlags Camera3Device::mapToConsumerUsage(
-        uint32_t usage) {
-    return usage;
-}
-
 StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
     switch (rotation) {
         case CAMERA3_STREAM_ROTATION_0:
@@ -549,16 +546,6 @@
     return static_cast<uint32_t>(pixelFormat);
 }
 
-uint32_t Camera3Device::mapConsumerToFrameworkUsage(
-        ConsumerUsageFlags usage) {
-    return usage;
-}
-
-uint32_t Camera3Device::mapProducerToFrameworkUsage(
-        ProducerUsageFlags usage) {
-    return usage;
-}
-
 ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
     // Get max jpeg size (area-wise).
     Size maxJpegResolution = getMaxJpegResolution();
@@ -1399,15 +1386,6 @@
     return OK;
 }
 
-status_t Camera3Device::createReprocessStreamFromStream(int outputId, int *id) {
-    ATRACE_CALL();
-    (void)outputId; (void)id;
-
-    CLOGE("Unimplemented");
-    return INVALID_OPERATION;
-}
-
-
 status_t Camera3Device::getStreamInfo(int id,
         uint32_t *width, uint32_t *height,
         uint32_t *format, android_dataspace *dataSpace) {
@@ -1523,14 +1501,6 @@
     return res;
 }
 
-status_t Camera3Device::deleteReprocessStream(int id) {
-    ATRACE_CALL();
-    (void)id;
-
-    CLOGE("Unimplemented");
-    return INVALID_OPERATION;
-}
-
 status_t Camera3Device::configureStreams(int operatingMode) {
     ATRACE_CALL();
     ALOGV("%s: E", __FUNCTION__);
@@ -1856,15 +1826,6 @@
                                         sizeof(trigger)/sizeof(trigger[0]));
 }
 
-status_t Camera3Device::pushReprocessBuffer(int reprocessStreamId,
-        buffer_handle_t *buffer, wp<BufferReleasedListener> listener) {
-    ATRACE_CALL();
-    (void)reprocessStreamId; (void)buffer; (void)listener;
-
-    CLOGE("Unimplemented");
-    return INVALID_OPERATION;
-}
-
 status_t Camera3Device::flush(int64_t *frameNumber) {
     ATRACE_CALL();
     ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
@@ -3161,7 +3122,9 @@
             Stream &dst = requestedConfiguration.streams[i];
             camera3_stream_t *src = config->streams[i];
 
-            int streamId = Camera3Stream::cast(src)->getId();
+            Camera3Stream* cam3stream = Camera3Stream::cast(src);
+            cam3stream->setBufferFreedListener(this);
+            int streamId = cam3stream->getId();
             StreamType streamType;
             switch (src->stream_type) {
                 case CAMERA3_STREAM_OUTPUT:
@@ -3180,7 +3143,9 @@
             dst.width = src->width;
             dst.height = src->height;
             dst.format = mapToPixelFormat(src->format);
-            dst.usage = mapToConsumerUsage(src->usage);
+            uint64_t consumerUsage, producerUsage;
+            ::android_convertGralloc0To1Usage(src->usage, &producerUsage, &consumerUsage);
+            dst.usage = consumerUsage;
             dst.dataSpace = mapToHidlDataspace(src->data_space);
             dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
 
@@ -3262,7 +3227,6 @@
                             __FUNCTION__, streamId);
                     return INVALID_OPERATION;
                 }
-                dst->usage = mapConsumerToFrameworkUsage(src.consumerUsage);
             } else {
                 // OUTPUT
                 if (src.consumerUsage != 0) {
@@ -3270,8 +3234,8 @@
                             __FUNCTION__, streamId);
                     return INVALID_OPERATION;
                 }
-                dst->usage = mapProducerToFrameworkUsage(src.producerUsage);
             }
+            dst->usage = ::android_convertGralloc1To0Usage(src.producerUsage, src.consumerUsage);
             dst->max_buffers = src.maxBuffers;
         }
     }
@@ -3366,9 +3330,21 @@
         wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
     }
 
+    std::vector<device::V3_2::BufferCache> cachesToRemove;
+    {
+        std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+        for (auto& pair : mFreedBuffers) {
+            // The stream might have been removed since onBufferFreed
+            if (mBufferIdMaps.find(pair.first) != mBufferIdMaps.end()) {
+                cachesToRemove.push_back({pair.first, pair.second});
+            }
+        }
+        mFreedBuffers.clear();
+    }
+
     common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
     *numRequestProcessed = 0;
-    mHidlSession->processCaptureRequest(captureRequests,
+    mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
             [&status, &numRequestProcessed] (auto s, uint32_t n) {
                 status = s;
                 *numRequestProcessed = n;
@@ -3476,12 +3452,40 @@
     auto it = bIdMap.find(buf);
     if (it == bIdMap.end()) {
         bIdMap[buf] = mNextBufferId++;
+        ALOGV("stream %d now have %zu buffer caches, buf %p",
+                streamId, bIdMap.size(), buf);
         return std::make_pair(true, mNextBufferId - 1);
     } else {
         return std::make_pair(false, it->second);
     }
 }
 
+void Camera3Device::HalInterface::onBufferFreed(
+        int streamId, const native_handle_t* handle) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    uint64_t bufferId = BUFFER_ID_NO_BUFFER;
+    auto mapIt = mBufferIdMaps.find(streamId);
+    if (mapIt == mBufferIdMaps.end()) {
+        // streamId might be from a deleted stream here
+        ALOGI("%s: stream %d has been removed",
+                __FUNCTION__, streamId);
+        return;
+    }
+    BufferIdMap& bIdMap = mapIt->second;
+    auto it = bIdMap.find(handle);
+    if (it == bIdMap.end()) {
+        ALOGW("%s: cannot find buffer %p in stream %d",
+                __FUNCTION__, handle, streamId);
+        return;
+    } else {
+        bufferId =  it->second;
+        bIdMap.erase(it);
+        ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
+                __FUNCTION__, streamId, bIdMap.size(), handle);
+    }
+    mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
+}
+
 /**
  * RequestThread inner class methods
  */
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d873b27..d4b92cf 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -125,7 +125,6 @@
     status_t createInputStream(
             uint32_t width, uint32_t height, int format,
             int *id) override;
-    status_t createReprocessStreamFromStream(int outputId, int *id) override;
 
     status_t getStreamInfo(int id,
             uint32_t *width, uint32_t *height,
@@ -133,7 +132,6 @@
     status_t setStreamTransform(int id, int transform) override;
 
     status_t deleteStream(int id) override;
-    status_t deleteReprocessStream(int id) override;
 
     status_t configureStreams(int operatingMode =
             static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
@@ -155,9 +153,6 @@
     status_t triggerCancelAutofocus(uint32_t id) override;
     status_t triggerPrecaptureMetering(uint32_t id) override;
 
-    status_t pushReprocessBuffer(int reprocessStreamId,
-            buffer_handle_t *buffer, wp<BufferReleasedListener> listener) override;
-
     status_t flush(int64_t *lastFrameNumber = NULL) override;
 
     status_t prepare(int streamId) override;
@@ -228,7 +223,7 @@
      * Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
      * HIDL HALv3 interfaces.
      */
-    class HalInterface {
+    class HalInterface : public camera3::Camera3StreamBufferFreedListener {
       public:
         HalInterface(camera3_device_t *device);
         HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session);
@@ -326,6 +321,10 @@
         //       buffer_handle_t's FD won't change.
         // return pair of (newlySeenBuffer?, bufferId)
         std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
+
+        virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
+
+        std::vector<std::pair<int, uint64_t>> mFreedBuffers;
     };
 
     std::unique_ptr<HalInterface> mInterface;
@@ -598,7 +597,6 @@
     static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
     static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
             android_dataspace dataSpace);
-    static hardware::camera::device::V3_2::ConsumerUsageFlags mapToConsumerUsage(uint32_t usage);
     static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
             camera3_stream_rotation_t rotation);
     // Returns a negative error code if the passed-in operation mode is not valid.
@@ -606,10 +604,6 @@
             /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
     static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
-    static uint32_t mapConsumerToFrameworkUsage(
-            hardware::camera::device::V3_2::ConsumerUsageFlags usage);
-    static uint32_t mapProducerToFrameworkUsage(
-            hardware::camera::device::V3_2::ProducerUsageFlags usage);
 
     struct RequestTrigger {
         // Metadata tag number, e.g. android.control.aePrecaptureTrigger
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 1469b74..4eb15ad 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -263,6 +263,8 @@
         mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
 
         mProducer = producer;
+
+        mConsumer->setBufferFreedListener(this);
     }
 
     res = mConsumer->setDefaultBufferSize(camera3_stream::width,
@@ -288,6 +290,17 @@
     return OK;
 }
 
+void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
+    const sp<GraphicBuffer> buffer = gb.promote();
+    if (buffer != nullptr) {
+        if (mBufferFreedListener != nullptr) {
+            mBufferFreedListener->onBufferFreed(mId, buffer->handle);
+        }
+    } else {
+        ALOGE("%s: GraphicBuffer is freed before onBufferFreed callback finishes!", __FUNCTION__);
+    }
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 9f3de10..8f5b431 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -34,7 +34,8 @@
  * buffers by feeding them into the HAL, as well as releasing the buffers back
  * the buffers once the HAL is done with them.
  */
-class Camera3InputStream : public Camera3IOStreamBase {
+class Camera3InputStream : public Camera3IOStreamBase,
+                           public BufferItemConsumer::BufferFreedListener {
   public:
     /**
      * Set up a stream for formats that have fixed size, such as RAW and YUV.
@@ -77,6 +78,11 @@
 
     virtual status_t getEndpointUsage(uint32_t *usage) const;
 
+    /**
+     * BufferItemConsumer::BufferFreedListener interface
+     */
+    virtual void onBufferFreed(const wp<GraphicBuffer>&) override;
+
 }; // class Camera3InputStream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 51dc20a..c60a68c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -347,7 +347,9 @@
 
     // Configure consumer-side ANativeWindow interface. The listener may be used
     // to notify buffer manager (if it is used) of the returned buffers.
-    res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/mBufferReleasedListener);
+    res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA,
+            /*listener*/mBufferReleasedListener,
+            /*reportBufferRemoval*/true);
     if (res != OK) {
         ALOGE("%s: Unable to connect to native window for stream %d",
                 __FUNCTION__, mId);
@@ -543,6 +545,14 @@
         }
     }
 
+    if (res == OK) {
+        std::vector<sp<GraphicBuffer>> removedBuffers;
+        res = mConsumer->getAndFlushRemovedBuffers(&removedBuffers);
+        if (res == OK) {
+            onBuffersRemovedLocked(removedBuffers);
+        }
+    }
+
     return res;
 }
 
@@ -624,7 +634,7 @@
             NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
 
     // If an opaque output stream's endpoint is ImageReader, add
-    // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
+    // GRALLOC_USAGE_HW_CAMERA_READ to the usage so HAL knows it will be used
     // for the ZSL use case.
     // Assume it's for ImageReader if the consumer usage doesn't have any of these bits set:
     //     1. GRALLOC_USAGE_HW_TEXTURE
@@ -634,7 +644,7 @@
     if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
             (u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
             GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) {
-        u |= GRALLOC_USAGE_HW_CAMERA_ZSL;
+        u |= GRALLOC_USAGE_HW_CAMERA_READ;
     }
 
     *usage = u;
@@ -686,6 +696,16 @@
     }
 }
 
+void Camera3OutputStream::onBuffersRemovedLocked(
+        const std::vector<sp<GraphicBuffer>>& removedBuffers) {
+    Camera3StreamBufferFreedListener* callback = mBufferFreedListener;
+    if (callback != nullptr) {
+        for (auto gb : removedBuffers) {
+            callback->onBufferFreed(mId, gb->handle);
+        }
+    }
+}
+
 status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
     Mutex::Autolock l(mLock);
 
@@ -718,7 +738,12 @@
         }
     }
 
-    return OK;
+    std::vector<sp<GraphicBuffer>> removedBuffers;
+    res = mConsumer->getAndFlushRemovedBuffers(&removedBuffers);
+    if (res == OK) {
+        onBuffersRemovedLocked(removedBuffers);
+    }
+    return res;
 }
 
 status_t Camera3OutputStream::notifyBufferReleased(ANativeWindowBuffer* /*anwBuffer*/) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 24e4e05..86676e4 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -263,6 +263,8 @@
 
     virtual status_t getEndpointUsage(uint32_t *usage) const;
 
+    void onBuffersRemovedLocked(const std::vector<sp<GraphicBuffer>>&);
+
 }; // class Camera3OutputStream
 
 } // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 53a3168..2b1a899 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -812,6 +812,18 @@
     }
 }
 
+void Camera3Stream::setBufferFreedListener(
+        Camera3StreamBufferFreedListener* listener) {
+    Mutex::Autolock l(mLock);
+    // Only allow set listener during stream configuration because stream is guaranteed to be IDLE
+    // at this state, so setBufferFreedListener won't collide with onBufferFreed callbacks
+    if (mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) {
+        ALOGE("%s: listener must be set during stream configuration!",__FUNCTION__);
+        return;
+    }
+    mBufferFreedListener = listener;
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 56cb827..27ef86d 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -365,6 +365,11 @@
     void             removeBufferListener(
             const sp<Camera3StreamBufferListener>& listener);
 
+
+    // Setting listener will remove previous listener (if exists)
+    virtual void     setBufferFreedListener(
+            Camera3StreamBufferFreedListener* listener) override;
+
     /**
      * Return if the buffer queue of the stream is abandoned.
      */
@@ -408,6 +413,8 @@
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
             int setId);
 
+    Camera3StreamBufferFreedListener* mBufferFreedListener;
+
     /**
      * Interface to be implemented by derived classes
      */
diff --git a/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h b/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h
new file mode 100644
index 0000000..478a752
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA3_STREAMBUFFERFREEDLISTENER_H
+#define ANDROID_SERVERS_CAMERA3_STREAMBUFFERFREEDLISTENER_H
+
+#include <gui/Surface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3StreamBufferFreedListener {
+public:
+    // onBufferFreed is called when a buffer is no longer being managed
+    // by this stream. This will not be called in events when all
+    // buffers are freed due to stream disconnection.
+    //
+    // The input handle may be deleted after this callback ends, so attempting
+    // to dereference handle post this callback is illegal and might lead to
+    // crash.
+    //
+    // This callback will be called while holding Camera3Stream's lock, so
+    // calling into other Camera3Stream APIs within this callback will
+    // lead to deadlock.
+    virtual void onBufferFreed(int streamId, const native_handle_t* handle) = 0;
+
+    virtual ~Camera3StreamBufferFreedListener() {}
+};
+
+}; //namespace camera3
+}; //namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index f7b092f..37b7c36 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -19,6 +19,7 @@
 
 #include <utils/RefBase.h>
 #include "Camera3StreamBufferListener.h"
+#include "Camera3StreamBufferFreedListener.h"
 
 struct camera3_stream_buffer;
 
@@ -287,6 +288,15 @@
             wp<Camera3StreamBufferListener> listener) = 0;
     virtual void     removeBufferListener(
             const sp<Camera3StreamBufferListener>& listener) = 0;
+
+    /**
+     * Setting listner will remove previous listener (if exists)
+     * Only allow set listener during stream configuration because stream is guaranteed to be IDLE
+     * at this state, so setBufferFreedListener won't collide with onBufferFreed callbacks.
+     * Client is responsible to keep the listener object alive throughout the lifecycle of this
+     * Camera3Stream.
+     */
+    virtual void setBufferFreedListener(Camera3StreamBufferFreedListener* listener) = 0;
 };
 
 } // namespace camera3