Merge "Update test-resample to handle multichannel"
diff --git a/camera/Android.mk b/camera/Android.mk
index 369d0c5..5774b6f 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -22,6 +22,7 @@
 	Camera.cpp \
 	CameraMetadata.cpp \
 	CameraParameters.cpp \
+	CaptureResult.cpp \
 	ICamera.cpp \
 	ICameraClient.cpp \
 	ICameraService.cpp \
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
new file mode 100644
index 0000000..c016e52
--- /dev/null
+++ b/camera/CaptureResult.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define LOG_TAG "Camera-CaptureResult"
+#include <utils/Log.h>
+
+#include <camera/CaptureResult.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+bool CaptureResultExtras::isValid() {
+    return requestId >= 0;
+}
+
+status_t CaptureResultExtras::readFromParcel(Parcel *parcel) {
+    if (parcel == NULL) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    parcel->readInt32(&requestId);
+    parcel->readInt32(&burstId);
+    parcel->readInt32(&afTriggerId);
+    parcel->readInt32(&precaptureTriggerId);
+    parcel->readInt64(&frameNumber);
+
+    return OK;
+}
+
+status_t CaptureResultExtras::writeToParcel(Parcel *parcel) const {
+    if (parcel == NULL) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    parcel->writeInt32(requestId);
+    parcel->writeInt32(burstId);
+    parcel->writeInt32(afTriggerId);
+    parcel->writeInt32(precaptureTriggerId);
+    parcel->writeInt64(frameNumber);
+
+    return OK;
+}
+
+CaptureResult::CaptureResult() :
+        mMetadata(), mResultExtras() {
+}
+
+CaptureResult::CaptureResult(const CaptureResult &otherResult) {
+    mResultExtras = otherResult.mResultExtras;
+    mMetadata = otherResult.mMetadata;
+}
+
+status_t CaptureResult::readFromParcel(Parcel *parcel) {
+
+    ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
+
+    if (parcel == NULL) {
+        ALOGE("%s: parcel is null", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    mMetadata.clear();
+
+    status_t res = OK;
+    res = mMetadata.readFromParcel(parcel);
+    if (res != OK) {
+        ALOGE("%s: Failed to read metadata from parcel.",
+              __FUNCTION__);
+        return res;
+    }
+    ALOGV("%s: Read metadata from parcel", __FUNCTION__);
+
+    res = mResultExtras.readFromParcel(parcel);
+    if (res != OK) {
+        ALOGE("%s: Failed to read result extras from parcel.",
+                __FUNCTION__);
+        return res;
+    }
+    ALOGV("%s: Read result extras from parcel", __FUNCTION__);
+
+    return OK;
+}
+
+status_t CaptureResult::writeToParcel(Parcel *parcel) const {
+
+    ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
+
+    if (parcel == NULL) {
+        ALOGE("%s: parcel is null", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    status_t res;
+
+    res = mMetadata.writeToParcel(parcel);
+    if (res != OK) {
+        ALOGE("%s: Failed to write metadata to parcel", __FUNCTION__);
+        return res;
+    }
+    ALOGV("%s: Wrote metadata to parcel", __FUNCTION__);
+
+    res = mResultExtras.writeToParcel(parcel);
+    if (res != OK) {
+        ALOGE("%s: Failed to write result extras to parcel", __FUNCTION__);
+        return res;
+    }
+    ALOGV("%s: Wrote result extras to parcel", __FUNCTION__);
+
+    return OK;
+}
+
+}
diff --git a/camera/camera2/ICameraDeviceCallbacks.cpp b/camera/camera2/ICameraDeviceCallbacks.cpp
index 613358a..4cc7b5d 100644
--- a/camera/camera2/ICameraDeviceCallbacks.cpp
+++ b/camera/camera2/ICameraDeviceCallbacks.cpp
@@ -28,6 +28,7 @@
 
 #include <camera/camera2/ICameraDeviceCallbacks.h>
 #include "camera/CameraMetadata.h"
+#include "camera/CaptureResult.h"
 
 namespace android {
 
@@ -46,12 +47,14 @@
     {
     }
 
-    void onDeviceError(CameraErrorCode errorCode)
+    void onDeviceError(CameraErrorCode errorCode, const CaptureResultExtras& resultExtras)
     {
         ALOGV("onDeviceError");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
         data.writeInt32(static_cast<int32_t>(errorCode));
+        data.writeInt32(1); // to mark presence of CaptureResultExtras object
+        resultExtras.writeToParcel(&data);
         remote()->transact(CAMERA_ERROR, data, &reply, IBinder::FLAG_ONEWAY);
         data.writeNoException();
     }
@@ -65,25 +68,28 @@
         data.writeNoException();
     }
 
-    void onCaptureStarted(int32_t requestId, int64_t timestamp)
+    void onCaptureStarted(const CaptureResultExtras& result, int64_t timestamp)
     {
         ALOGV("onCaptureStarted");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(requestId);
+        data.writeInt32(1); // to mark presence of CaptureResultExtras object
+        result.writeToParcel(&data);
         data.writeInt64(timestamp);
         remote()->transact(CAPTURE_STARTED, data, &reply, IBinder::FLAG_ONEWAY);
         data.writeNoException();
     }
 
 
-    void onResultReceived(int32_t requestId, const CameraMetadata& result) {
+    void onResultReceived(const CameraMetadata& metadata,
+            const CaptureResultExtras& resultExtras) {
         ALOGV("onResultReceived");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(requestId);
         data.writeInt32(1); // to mark presence of metadata object
-        result.writeToParcel(&data);
+        metadata.writeToParcel(&data);
+        data.writeInt32(1); // to mark presence of CaptureResult object
+        resultExtras.writeToParcel(&data);
         remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
         data.writeNoException();
     }
@@ -104,7 +110,13 @@
             CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
             CameraErrorCode errorCode =
                     static_cast<CameraErrorCode>(data.readInt32());
-            onDeviceError(errorCode);
+            CaptureResultExtras resultExtras;
+            if (data.readInt32() != 0) {
+                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
+            } else {
+                ALOGE("No CaptureResultExtras object is present!");
+            }
+            onDeviceError(errorCode, resultExtras);
             data.readExceptionCode();
             return NO_ERROR;
         } break;
@@ -118,23 +130,33 @@
         case CAPTURE_STARTED: {
             ALOGV("onCaptureStarted");
             CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            int32_t requestId = data.readInt32();
+            CaptureResultExtras result;
+            if (data.readInt32() != 0) {
+                result.readFromParcel(const_cast<Parcel*>(&data));
+            } else {
+                ALOGE("No CaptureResultExtras object is present in result!");
+            }
             int64_t timestamp = data.readInt64();
-            onCaptureStarted(requestId, timestamp);
+            onCaptureStarted(result, timestamp);
             data.readExceptionCode();
             return NO_ERROR;
         } break;
         case RESULT_RECEIVED: {
             ALOGV("onResultReceived");
             CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            int32_t requestId = data.readInt32();
-            CameraMetadata result;
+            CameraMetadata metadata;
             if (data.readInt32() != 0) {
-                result.readFromParcel(const_cast<Parcel*>(&data));
+                metadata.readFromParcel(const_cast<Parcel*>(&data));
             } else {
                 ALOGW("No metadata object is present in result");
             }
-            onResultReceived(requestId, result);
+            CaptureResultExtras resultExtras;
+            if (data.readInt32() != 0) {
+                resultExtras.readFromParcel(const_cast<Parcel*>(&data));
+            } else {
+                ALOGW("No capture result extras object is present in result");
+            }
+            onResultReceived(metadata, resultExtras);
             data.readExceptionCode();
             return NO_ERROR;
         } break;
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 1e5822f..ad65955 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -35,6 +35,7 @@
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     SUBMIT_REQUEST,
+    SUBMIT_REQUEST_LIST,
     CANCEL_REQUEST,
     DELETE_STREAM,
     CREATE_STREAM,
@@ -75,7 +76,8 @@
         reply.readExceptionCode();
     }
 
-    virtual int submitRequest(sp<CaptureRequest> request, bool streaming)
+    virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
+                              int64_t *lastFrameNumber)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
@@ -89,15 +91,67 @@
         }
 
         // arg1 = streaming (bool)
-        data.writeInt32(streaming);
+        data.writeInt32(repeating);
 
         remote()->transact(SUBMIT_REQUEST, data, &reply);
 
         reply.readExceptionCode();
-        return reply.readInt32();
+        status_t res = reply.readInt32();
+
+        status_t resFrameNumber = BAD_VALUE;
+        if (reply.readInt32() != 0) {
+            if (lastFrameNumber != NULL) {
+                resFrameNumber = reply.readInt64(lastFrameNumber);
+            }
+        }
+
+	if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+            res = FAILED_TRANSACTION;
+        }
+        return res;
     }
 
-    virtual status_t cancelRequest(int requestId)
+    virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
+                                  int64_t *lastFrameNumber)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+
+        data.writeInt32(requestList.size());
+
+        for (List<sp<CaptureRequest> >::iterator it = requestList.begin();
+                it != requestList.end(); ++it) {
+            sp<CaptureRequest> request = *it;
+            if (request != 0) {
+                data.writeInt32(1);
+                if (request->writeToParcel(&data) != OK) {
+                    return BAD_VALUE;
+                }
+            } else {
+                data.writeInt32(0);
+            }
+        }
+
+        data.writeInt32(repeating);
+
+        remote()->transact(SUBMIT_REQUEST_LIST, data, &reply);
+
+        reply.readExceptionCode();
+        status_t res = reply.readInt32();
+
+        status_t resFrameNumber = BAD_VALUE;
+        if (reply.readInt32() != 0) {
+            if (lastFrameNumber != NULL) {
+                resFrameNumber = reply.readInt64(lastFrameNumber);
+            }
+        }
+        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+            res = FAILED_TRANSACTION;
+        }
+        return res;
+    }
+
+    virtual status_t cancelRequest(int requestId, int64_t *lastFrameNumber)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
@@ -106,7 +160,18 @@
         remote()->transact(CANCEL_REQUEST, data, &reply);
 
         reply.readExceptionCode();
-        return reply.readInt32();
+        status_t res = reply.readInt32();
+
+        status_t resFrameNumber = BAD_VALUE;
+        if (reply.readInt32() != 0) {
+            if (lastFrameNumber != NULL) {
+                res = reply.readInt64(lastFrameNumber);
+            }
+        }
+        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+            res = FAILED_TRANSACTION;
+        }
+        return res;
     }
 
     virtual status_t deleteStream(int streamId)
@@ -197,14 +262,25 @@
         return reply.readInt32();
     }
 
-    virtual status_t flush()
+    virtual status_t flush(int64_t *lastFrameNumber)
     {
         ALOGV("flush");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
         remote()->transact(FLUSH, data, &reply);
         reply.readExceptionCode();
-        return reply.readInt32();
+        status_t res = reply.readInt32();
+
+        status_t resFrameNumber = BAD_VALUE;
+        if (reply.readInt32() != 0) {
+            if (lastFrameNumber != NULL) {
+                res = reply.readInt64(lastFrameNumber);
+            }
+        }
+        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+            res = FAILED_TRANSACTION;
+        }
+        return res;
     }
 
 private:
@@ -239,11 +315,43 @@
             }
 
             // arg1 = streaming (bool)
-            bool streaming = data.readInt32();
+            bool repeating = data.readInt32();
 
             // return code: requestId (int32)
             reply->writeNoException();
-            reply->writeInt32(submitRequest(request, streaming));
+            int64_t lastFrameNumber = -1;
+            reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
+            reply->writeInt32(1);
+            reply->writeInt64(lastFrameNumber);
+
+            return NO_ERROR;
+        } break;
+        case SUBMIT_REQUEST_LIST: {
+            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+
+            List<sp<CaptureRequest> > requestList;
+            int requestListSize = data.readInt32();
+            for (int i = 0; i < requestListSize; i++) {
+                if (data.readInt32() != 0) {
+                    sp<CaptureRequest> request = new CaptureRequest();
+                    if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
+                        return BAD_VALUE;
+                    }
+                    requestList.push_back(request);
+                } else {
+                    sp<CaptureRequest> request = 0;
+                    requestList.push_back(request);
+                    ALOGE("A request is missing. Sending in null request.");
+                }
+            }
+
+            bool repeating = data.readInt32();
+
+            reply->writeNoException();
+            int64_t lastFrameNumber = -1;
+            reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
+            reply->writeInt32(1);
+            reply->writeInt64(lastFrameNumber);
 
             return NO_ERROR;
         } break;
@@ -251,7 +359,10 @@
             CHECK_INTERFACE(ICameraDeviceUser, data, reply);
             int requestId = data.readInt32();
             reply->writeNoException();
-            reply->writeInt32(cancelRequest(requestId));
+            int64_t lastFrameNumber = -1;
+            reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
+            reply->writeInt32(1);
+            reply->writeInt64(lastFrameNumber);
             return NO_ERROR;
         } break;
         case DELETE_STREAM: {
@@ -339,7 +450,10 @@
         case FLUSH: {
             CHECK_INTERFACE(ICameraDeviceUser, data, reply);
             reply->writeNoException();
-            reply->writeInt32(flush());
+            int64_t lastFrameNumber = -1;
+            reply->writeInt32(flush(&lastFrameNumber));
+            reply->writeInt32(1);
+            reply->writeInt64(lastFrameNumber);
             return NO_ERROR;
         }
         default:
diff --git a/include/camera/CaptureResult.h b/include/camera/CaptureResult.h
new file mode 100644
index 0000000..6e47a16
--- /dev/null
+++ b/include/camera/CaptureResult.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 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_HARDWARE_CAPTURERESULT_H
+#define ANDROID_HARDWARE_CAPTURERESULT_H
+
+#include <utils/RefBase.h>
+#include <camera/CameraMetadata.h>
+
+namespace android {
+
+/**
+ * CaptureResultExtras is a structure to encapsulate various indices for a capture result.
+ * These indices are framework-internal and not sent to the HAL.
+ */
+struct CaptureResultExtras {
+    /**
+     * An integer to index the request sequence that this result belongs to.
+     */
+    int32_t requestId;
+
+    /**
+     * An integer to index this result inside a request sequence, starting from 0.
+     */
+    int32_t burstId;
+
+    /**
+     * TODO: Add documentation for this field.
+     */
+    int32_t afTriggerId;
+
+    /**
+     * TODO: Add documentation for this field.
+     */
+    int32_t precaptureTriggerId;
+
+    /**
+     * A 64bit integer to index the frame number associated with this result.
+     */
+    int64_t frameNumber;
+
+    /**
+     * Constructor initializes object as invalid by setting requestId to be -1.
+     */
+    CaptureResultExtras()
+        : requestId(-1),
+          burstId(0),
+          afTriggerId(0),
+          precaptureTriggerId(0),
+          frameNumber(0) {
+    }
+
+    /**
+     * This function returns true if it's a valid CaptureResultExtras object.
+     * Otherwise, returns false. It is valid only when requestId is non-negative.
+     */
+    bool isValid();
+
+    status_t                readFromParcel(Parcel* parcel);
+    status_t                writeToParcel(Parcel* parcel) const;
+};
+
+struct CaptureResult : public virtual LightRefBase<CaptureResult> {
+    CameraMetadata          mMetadata;
+    CaptureResultExtras     mResultExtras;
+
+    CaptureResult();
+
+    CaptureResult(const CaptureResult& otherResult);
+
+    status_t                readFromParcel(Parcel* parcel);
+    status_t                writeToParcel(Parcel* parcel) const;
+};
+
+}
+
+#endif /* ANDROID_HARDWARE_CAPTURERESULT_H */
diff --git a/include/camera/camera2/ICameraDeviceCallbacks.h b/include/camera/camera2/ICameraDeviceCallbacks.h
index 8dac4f2..f059b3d 100644
--- a/include/camera/camera2/ICameraDeviceCallbacks.h
+++ b/include/camera/camera2/ICameraDeviceCallbacks.h
@@ -24,9 +24,12 @@
 #include <utils/Timers.h>
 #include <system/camera.h>
 
+#include <camera/CaptureResult.h>
+
 namespace android {
 class CameraMetadata;
 
+
 class ICameraDeviceCallbacks : public IInterface
 {
     /**
@@ -45,18 +48,19 @@
     };
 
     // One way
-    virtual void            onDeviceError(CameraErrorCode errorCode) = 0;
+    virtual void            onDeviceError(CameraErrorCode errorCode,
+                                          const CaptureResultExtras& resultExtras) = 0;
 
     // One way
     virtual void            onDeviceIdle() = 0;
 
     // One way
-    virtual void            onCaptureStarted(int32_t requestId,
+    virtual void            onCaptureStarted(const CaptureResultExtras& resultExtras,
                                              int64_t timestamp) = 0;
 
     // One way
-    virtual void            onResultReceived(int32_t requestId,
-                                             const CameraMetadata& result) = 0;
+    virtual void            onResultReceived(const CameraMetadata& metadata,
+                                             const CaptureResultExtras& resultExtras) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index f71f302..49daf69 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -19,6 +19,7 @@
 
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
+#include <utils/List.h>
 
 struct camera_metadata;
 
@@ -44,9 +45,34 @@
      * Request Handling
      **/
 
+    /**
+     * For streaming requests, output lastFrameNumber is the last frame number
+     * of the previous repeating request.
+     * For non-streaming requests, output lastFrameNumber is the expected last
+     * frame number of the current request.
+     */
     virtual int             submitRequest(sp<CaptureRequest> request,
-                                          bool streaming = false) = 0;
-    virtual status_t        cancelRequest(int requestId) = 0;
+                                          bool streaming = false,
+                                          /*out*/
+                                          int64_t* lastFrameNumber = NULL) = 0;
+
+    /**
+     * For streaming requests, output lastFrameNumber is the last frame number
+     * of the previous repeating request.
+     * For non-streaming requests, output lastFrameNumber is the expected last
+     * frame number of the current request.
+     */
+    virtual int             submitRequestList(List<sp<CaptureRequest> > requestList,
+                                              bool streaming = false,
+                                              /*out*/
+                                              int64_t* lastFrameNumber = NULL) = 0;
+
+    /**
+     * Output lastFrameNumber is the last frame number of the previous repeating request.
+     */
+    virtual status_t        cancelRequest(int requestId,
+                                          /*out*/
+                                          int64_t* lastFrameNumber = NULL) = 0;
 
     virtual status_t        deleteStream(int streamId) = 0;
     virtual status_t        createStream(
@@ -64,8 +90,12 @@
     // 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;
+    /**
+     * Flush all pending and in-progress work as quickly as possible.
+     * Output lastFrameNumber is the last frame number of the previous repeating request.
+     */
+    virtual status_t        flush(/*out*/
+                                  int64_t* lastFrameNumber = NULL) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 446ff8c..2d8c1e1 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -8,7 +8,7 @@
         $(TOP)/external/libvpx/libwebm \
         $(TOP)/frameworks/native/include/media/openmax \
 
-LOCAL_CFLAGS += -Wno-multichar -Werror
+LOCAL_CFLAGS += -Wno-multichar
 
 LOCAL_MODULE:= libstagefright_matroska
 
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index 6a8b9fc..c4cfa17 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -9,7 +9,7 @@
         TimedTextSRTSource.cpp    \
         TimedTextPlayer.cpp
 
-LOCAL_CFLAGS += -Wno-multichar -Werror
+LOCAL_CFLAGS += -Wno-multichar
 
 LOCAL_C_INCLUDES:= \
         $(TOP)/frameworks/av/include/media/stagefright/timedtext \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 5c6f653..02bca1f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1116,7 +1116,8 @@
         // Reset the client PID to allow server-initiated disconnect,
         // and to prevent further calls by client.
         mClientPid = getCallingPid();
-        notifyError();
+        CaptureResultExtras resultExtras; // a dummy result (invalid)
+        notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE, resultExtras);
         disconnect();
     }
 }
@@ -1145,7 +1146,8 @@
     return client;
 }
 
-void CameraService::Client::notifyError() {
+void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+        const CaptureResultExtras& resultExtras) {
     mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
 }
 
@@ -1199,7 +1201,8 @@
 CameraService::ProClient::~ProClient() {
 }
 
-void CameraService::ProClient::notifyError() {
+void CameraService::ProClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+        const CaptureResultExtras& resultExtras) {
     mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
 }
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8853e48..76ea7be 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -31,6 +31,7 @@
 #include <camera/camera2/ICameraDeviceUser.h>
 #include <camera/camera2/ICameraDeviceCallbacks.h>
 #include <camera/VendorTagDescriptor.h>
+#include <camera/CaptureResult.h>
 
 #include <camera/ICameraServiceListener.h>
 
@@ -182,7 +183,9 @@
         status_t                        finishCameraOps();
 
         // Notify client about a fatal error
-        virtual void                    notifyError() = 0;
+        virtual void                    notifyError(
+                ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                const CaptureResultExtras& resultExtras) = 0;
     private:
         AppOpsManager                   mAppOpsManager;
 
@@ -259,7 +262,8 @@
         // convert client from cookie. Client lock should be acquired before getting Client.
         static Client*       getClientFromCookie(void* user);
 
-        virtual void         notifyError();
+        virtual void         notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                                         const CaptureResultExtras& resultExtras);
 
         // Initialized in constructor
 
@@ -307,7 +311,8 @@
         virtual void          onExclusiveLockStolen() = 0;
 
     protected:
-        virtual void          notifyError();
+        virtual void          notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                                          const CaptureResultExtras& resultExtras);
 
         sp<IProCameraCallbacks> mRemoteCallback;
     }; // class ProClient
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index f5c28ed..e5f5064 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -106,13 +106,12 @@
     }
 }
 
-void CaptureSequencer::onFrameAvailable(int32_t requestId,
-        const CameraMetadata &frame) {
-    ALOGV("%s: Listener found new frame", __FUNCTION__);
+void CaptureSequencer::onResultAvailable(const CaptureResult &result) {
     ATRACE_CALL();
+    ALOGV("%s: New result available.", __FUNCTION__);
     Mutex::Autolock l(mInputMutex);
-    mNewFrameId = requestId;
-    mNewFrame = frame;
+    mNewFrameId = result.mResultExtras.requestId;
+    mNewFrame = result.mMetadata;
     if (!mNewFrameReceived) {
         mNewFrameReceived = true;
         mNewFrameSignal.signal();
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
index 9fb4ee7..d42ab13 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
@@ -24,6 +24,7 @@
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
 #include "camera/CameraMetadata.h"
+#include "camera/CaptureResult.h"
 #include "Parameters.h"
 #include "FrameProcessor.h"
 
@@ -61,8 +62,8 @@
     // Notifications about AE state changes
     void notifyAutoExposure(uint8_t newState, int triggerId);
 
-    // Notifications from the frame processor
-    virtual void onFrameAvailable(int32_t requestId, const CameraMetadata &frame);
+    // Notification from the frame processor
+    virtual void onResultAvailable(const CaptureResult &result);
 
     // Notifications from the JPEG processor
     void onCaptureAvailable(nsecs_t timestamp, sp<MemoryBase> captureBuffer);
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index dd5b27c..69bea24 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -55,7 +55,7 @@
 FrameProcessor::~FrameProcessor() {
 }
 
-bool FrameProcessor::processSingleFrame(CameraMetadata &frame,
+bool FrameProcessor::processSingleFrame(CaptureResult &frame,
                                         const sp<CameraDeviceBase> &device) {
 
     sp<Camera2Client> client = mClient.promote();
@@ -66,19 +66,19 @@
     bool partialResult = false;
     if (mUsePartialQuirk) {
         camera_metadata_entry_t entry;
-        entry = frame.find(ANDROID_QUIRKS_PARTIAL_RESULT);
+        entry = frame.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT);
         if (entry.count > 0 &&
                 entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
             partialResult = true;
         }
     }
 
-    if (!partialResult && processFaceDetect(frame, client) != OK) {
+    if (!partialResult && processFaceDetect(frame.mMetadata, client) != OK) {
         return false;
     }
 
     if (mSynthesize3ANotify) {
-        process3aState(frame, client);
+        process3aState(frame.mMetadata, client);
     }
 
     return FrameProcessorBase::processSingleFrame(frame, device);
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.h b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
index 856ad32..514bd1a 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
@@ -51,7 +51,7 @@
 
     void processNewFrames(const sp<Camera2Client> &client);
 
-    virtual bool processSingleFrame(CameraMetadata &frame,
+    virtual bool processSingleFrame(CaptureResult &frame,
                                     const sp<CameraDeviceBase> &device);
 
     status_t processFaceDetect(const CameraMetadata &frame,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 6ab9e1a..2a2a5af 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -73,18 +73,19 @@
     }
 }
 
-void ZslProcessor::onFrameAvailable(int32_t /*requestId*/,
-        const CameraMetadata &frame) {
+void ZslProcessor::onResultAvailable(const CaptureResult &result) {
+    ATRACE_CALL();
+    ALOGV("%s:", __FUNCTION__);
     Mutex::Autolock l(mInputMutex);
     camera_metadata_ro_entry_t entry;
-    entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
+    entry = result.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
     nsecs_t timestamp = entry.data.i64[0];
     (void)timestamp;
     ALOGVV("Got preview frame for timestamp %" PRId64, timestamp);
 
     if (mState != RUNNING) return;
 
-    mFrameList.editItemAt(mFrameListHead) = frame;
+    mFrameList.editItemAt(mFrameListHead) = result.mMetadata;
     mFrameListHead = (mFrameListHead + 1) % kFrameListDepth;
 
     findMatchesLocked();
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index 6d3cb85..f4cf0c8 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -24,6 +24,7 @@
 #include <utils/Condition.h>
 #include <gui/BufferItemConsumer.h>
 #include <camera/CameraMetadata.h>
+#include <camera/CaptureResult.h>
 
 #include "common/CameraDeviceBase.h"
 #include "api1/client2/ZslProcessorInterface.h"
@@ -54,7 +55,7 @@
     // From mZslConsumer
     virtual void onFrameAvailable();
     // From FrameProcessor
-    virtual void onFrameAvailable(int32_t requestId, const CameraMetadata &frame);
+    virtual void onResultAvailable(const CaptureResult &result);
 
     virtual void onBufferReleased(buffer_handle_t *handle);
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
index 3949b90..1dcb718 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
@@ -63,18 +63,19 @@
     deleteStream();
 }
 
-void ZslProcessor3::onFrameAvailable(int32_t /*requestId*/,
-                                     const CameraMetadata &frame) {
+void ZslProcessor3::onResultAvailable(const CaptureResult &result) {
+    ATRACE_CALL();
+    ALOGV("%s:", __FUNCTION__);
     Mutex::Autolock l(mInputMutex);
     camera_metadata_ro_entry_t entry;
-    entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
+    entry = result.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
     nsecs_t timestamp = entry.data.i64[0];
     (void)timestamp;
     ALOGVV("Got preview metadata for timestamp %" PRId64, timestamp);
 
     if (mState != RUNNING) return;
 
-    mFrameList.editItemAt(mFrameListHead) = frame;
+    mFrameList.editItemAt(mFrameListHead) = result.mMetadata;
     mFrameListHead = (mFrameListHead + 1) % kFrameListDepth;
 }
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
index d2f8322..4c52a64 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
@@ -50,8 +50,8 @@
     ZslProcessor3(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
     ~ZslProcessor3();
 
-    // From FrameProcessor
-    virtual void onFrameAvailable(int32_t requestId, const CameraMetadata &frame);
+    // From FrameProcessor::FilteredListener
+    virtual void onResultAvailable(const CaptureResult &result);
 
     /**
      ****************************************
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1c9a342..3d85e90 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "CameraDeviceClient"
 #define ATRACE_TAG ATRACE_TAG_CAMERA
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <cutils/properties.h>
 #include <utils/Log.h>
@@ -91,105 +91,18 @@
 }
 
 status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request,
-                                         bool streaming) {
-    ATRACE_CALL();
-    ALOGV("%s", __FUNCTION__);
-
-    status_t res;
-
-    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
-
-    Mutex::Autolock icl(mBinderSerializationLock);
-
-    if (!mDevice.get()) return DEAD_OBJECT;
-
-    if (request == 0) {
-        ALOGE("%s: Camera %d: Sent null request. Rejecting 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.size() == 0) {
-        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 (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
-        sp<Surface> surface = request->mSurfaceList[i];
-
-        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());
-
-    int32_t requestId = mRequestIdCounter++;
-    metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
-    ALOGV("%s: Camera %d: Creating request with ID %d",
-          __FUNCTION__, mCameraId, requestId);
-
-    if (streaming) {
-        res = mDevice->setStreamingRequest(metadata);
-        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->capture(metadata);
-        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;
+                                         bool streaming,
+                                         /*out*/
+                                         int64_t* lastFrameNumber) {
+    List<sp<CaptureRequest> > requestList;
+    requestList.push_back(request);
+    return submitRequestList(requestList, streaming, lastFrameNumber);
 }
 
 status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests,
-                                               bool streaming) {
+                                               bool streaming, int64_t* lastFrameNumber) {
     ATRACE_CALL();
-    ALOGV("%s-start of function", __FUNCTION__);
+    ALOGV("%s-start of function. Request list size %d", __FUNCTION__, requests.size());
 
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -238,9 +151,8 @@
          */
         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;
+        for (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
+            sp<Surface> surface = request->mSurfaceList[i];
             if (surface == 0) continue;
 
             sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
@@ -273,7 +185,7 @@
     mRequestIdCounter++;
 
     if (streaming) {
-        res = mDevice->setStreamingRequestList(metadataRequestList);
+        res = mDevice->setStreamingRequestList(metadataRequestList, lastFrameNumber);
         if (res != OK) {
             ALOGE("%s: Camera %d:  Got error %d after trying to set streaming "
                   "request", __FUNCTION__, mCameraId, res);
@@ -281,11 +193,12 @@
             mStreamingRequestList.push_back(requestId);
         }
     } else {
-        res = mDevice->captureList(metadataRequestList);
+        res = mDevice->captureList(metadataRequestList, lastFrameNumber);
         if (res != OK) {
             ALOGE("%s: Camera %d: Got error %d after trying to set capture",
                 __FUNCTION__, mCameraId, res);
         }
+        ALOGV("%s: requestId = %d ", __FUNCTION__, requestId);
     }
 
     ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId);
@@ -296,7 +209,7 @@
     return res;
 }
 
-status_t CameraDeviceClient::cancelRequest(int requestId) {
+status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumber) {
     ATRACE_CALL();
     ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
 
@@ -322,7 +235,7 @@
         return BAD_VALUE;
     }
 
-    res = mDevice->clearStreamingRequest();
+    res = mDevice->clearStreamingRequest(lastFrameNumber);
 
     if (res == OK) {
         ALOGV("%s: Camera %d: Successfully cleared streaming request",
@@ -369,8 +282,6 @@
     } else if (res == OK) {
         mStreamMap.removeItemsAt(index);
 
-        ALOGV("%s: Camera %d: Successfully deleted stream ID (%d)",
-              __FUNCTION__, mCameraId, streamId);
     }
 
     return res;
@@ -575,7 +486,7 @@
     return res;
 }
 
-status_t CameraDeviceClient::flush() {
+status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
     ATRACE_CALL();
     ALOGV("%s", __FUNCTION__);
 
@@ -586,7 +497,7 @@
 
     if (!mDevice.get()) return DEAD_OBJECT;
 
-    return mDevice->flush();
+    return mDevice->flush(lastFrameNumber);
 }
 
 status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
@@ -603,13 +514,13 @@
     return dumpDevice(fd, args);
 }
 
-
-void CameraDeviceClient::notifyError() {
+void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                                     const CaptureResultExtras& resultExtras) {
     // Thread safe. Don't bother locking.
     sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
 
     if (remoteCb != 0) {
-        remoteCb->onDeviceError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE);
+        remoteCb->onDeviceError(errorCode, resultExtras);
     }
 }
 
@@ -622,12 +533,12 @@
     }
 }
 
-void CameraDeviceClient::notifyShutter(int requestId,
+void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
         nsecs_t timestamp) {
     // Thread safe. Don't bother locking.
     sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
     if (remoteCb != 0) {
-        remoteCb->onCaptureStarted(requestId, timestamp);
+        remoteCb->onCaptureStarted(resultExtras, timestamp);
     }
 }
 
@@ -662,16 +573,14 @@
 }
 
 /** Device-related methods */
-void CameraDeviceClient::onFrameAvailable(int32_t requestId,
-        const CameraMetadata& frame) {
+void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
     ATRACE_CALL();
     ALOGV("%s", __FUNCTION__);
 
     // Thread-safe. No lock necessary.
     sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
     if (remoteCb != NULL) {
-        ALOGV("%s: frame = %p ", __FUNCTION__, &frame);
-        remoteCb->onResultReceived(requestId, frame);
+        remoteCb->onResultReceived(result.mMetadata, result.mResultExtras);
     }
 }
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index e96e1ae..0b37784 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -64,11 +64,17 @@
 
     // Note that the callee gets a copy of the metadata.
     virtual status_t           submitRequest(sp<CaptureRequest> request,
-                                             bool streaming = false);
+                                             bool streaming = false,
+                                             /*out*/
+                                             int64_t* lastFrameNumber = NULL);
     // List of requests are copied.
     virtual status_t           submitRequestList(List<sp<CaptureRequest> > requests,
-                                                 bool streaming = false);
-    virtual status_t      cancelRequest(int requestId);
+                                                 bool streaming = false,
+                                                 /*out*/
+                                                 int64_t* lastFrameNumber = NULL);
+    virtual status_t      cancelRequest(int requestId,
+                                        /*out*/
+                                        int64_t* lastFrameNumber = NULL);
 
     // Returns -EBUSY if device is not idle
     virtual status_t      deleteStream(int streamId);
@@ -92,7 +98,8 @@
     virtual status_t      waitUntilIdle();
 
     // Flush all active and pending requests as fast as possible
-    virtual status_t      flush();
+    virtual status_t      flush(/*out*/
+                                int64_t* lastFrameNumber = NULL);
 
     /**
      * Interface used by CameraService
@@ -117,16 +124,16 @@
      */
 
     virtual void notifyIdle();
-    virtual void notifyError();
-    virtual void notifyShutter(int requestId, nsecs_t timestamp);
+    virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                             const CaptureResultExtras& resultExtras);
+    virtual void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp);
 
     /**
      * Interface used by independent components of CameraDeviceClient.
      */
 protected:
     /** FilteredListener implementation **/
-    virtual void          onFrameAvailable(int32_t requestId,
-                                           const CameraMetadata& frame);
+    virtual void          onResultAvailable(const CaptureResult& result);
     virtual void          detachDevice();
 
     // Calculate the ANativeWindow transform from android.sensor.orientation
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 1a7a7a7..0f6d278 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -373,9 +373,7 @@
     Camera2ClientBase::detachDevice();
 }
 
-/** Device-related methods */
-void ProCamera2Client::onFrameAvailable(int32_t requestId,
-                                        const CameraMetadata& frame) {
+void ProCamera2Client::onResultAvailable(const CaptureResult& result) {
     ATRACE_CALL();
     ALOGV("%s", __FUNCTION__);
 
@@ -383,13 +381,12 @@
     SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
 
     if (mRemoteCallback != NULL) {
-        CameraMetadata tmp(frame);
+        CameraMetadata tmp(result.mMetadata);
         camera_metadata_t* meta = tmp.release();
         ALOGV("%s: meta = %p ", __FUNCTION__, meta);
-        mRemoteCallback->onResultReceived(requestId, meta);
+        mRemoteCallback->onResultReceived(result.mResultExtras.requestId, meta);
         tmp.acquire(meta);
     }
-
 }
 
 bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
index 8a0f547..9d83122 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
@@ -21,6 +21,7 @@
 #include "common/FrameProcessorBase.h"
 #include "common/Camera2ClientBase.h"
 #include "device2/Camera2Device.h"
+#include "camera/CaptureResult.h"
 
 namespace android {
 
@@ -97,8 +98,8 @@
 
 protected:
     /** FilteredListener implementation **/
-    virtual void          onFrameAvailable(int32_t requestId,
-                                           const CameraMetadata& frame);
+    virtual void onResultAvailable(const CaptureResult& result);
+
     virtual void          detachDevice();
 
 private:
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 6a88c87..19efd30 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -221,10 +221,11 @@
 /** Device-related methods */
 
 template <typename TClientBase>
-void Camera2ClientBase<TClientBase>::notifyError(int errorCode, int arg1,
-                                                 int arg2) {
-    ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
-          arg1, arg2);
+void Camera2ClientBase<TClientBase>::notifyError(
+        ICameraDeviceCallbacks::CameraErrorCode errorCode,
+        const CaptureResultExtras& resultExtras) {
+    ALOGE("Error condition %d reported by HAL, requestId %" PRId32, errorCode,
+          resultExtras.requestId);
 }
 
 template <typename TClientBase>
@@ -233,13 +234,13 @@
 }
 
 template <typename TClientBase>
-void Camera2ClientBase<TClientBase>::notifyShutter(int requestId,
+void Camera2ClientBase<TClientBase>::notifyShutter(const CaptureResultExtras& resultExtras,
                                                    nsecs_t timestamp) {
-    (void)requestId;
+    (void)resultExtras;
     (void)timestamp;
 
-    ALOGV("%s: Shutter notification for request id %d at time %" PRId64,
-            __FUNCTION__, requestId, timestamp);
+    ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
+            __FUNCTION__, resultExtras.requestId, timestamp);
 }
 
 template <typename TClientBase>
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 61e44f0..9feca93 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
 
 #include "common/CameraDeviceBase.h"
+#include "camera/CaptureResult.h"
 
 namespace android {
 
@@ -61,9 +62,11 @@
      * CameraDeviceBase::NotificationListener implementation
      */
 
-    virtual void          notifyError(int errorCode, int arg1, int arg2);
+    virtual void          notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                                      const CaptureResultExtras& resultExtras);
     virtual void          notifyIdle();
-    virtual void          notifyShutter(int requestId, nsecs_t timestamp);
+    virtual void          notifyShutter(const CaptureResultExtras& resultExtras,
+                                        nsecs_t timestamp);
     virtual void          notifyAutoFocus(uint8_t newState, int triggerId);
     virtual void          notifyAutoExposure(uint8_t newState, int triggerId);
     virtual void          notifyAutoWhitebalance(uint8_t newState,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index a4ae179..7597b10 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -24,8 +24,10 @@
 #include <utils/Timers.h>
 #include <utils/List.h>
 
+#include <camera/camera2/ICameraDeviceCallbacks.h>
 #include "hardware/camera2.h"
 #include "camera/CameraMetadata.h"
+#include "camera/CaptureResult.h"
 
 namespace android {
 
@@ -45,7 +47,7 @@
     virtual status_t initialize(camera_module_t *module) = 0;
     virtual status_t disconnect() = 0;
 
-    virtual status_t dump(int fd, const Vector<String16>& args) = 0;
+    virtual status_t dump(int fd, const Vector<String16> &args) = 0;
 
     /**
      * The device's static characteristics metadata buffer
@@ -55,29 +57,37 @@
     /**
      * Submit request for capture. The CameraDevice takes ownership of the
      * passed-in buffer.
+     * Output lastFrameNumber is the expected frame number of this request.
      */
-    virtual status_t capture(CameraMetadata &request) = 0;
+    virtual status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL) = 0;
 
     /**
      * Submit a list of requests.
+     * Output lastFrameNumber is the expected last frame number of the list of requests.
      */
-    virtual status_t captureList(const List<const CameraMetadata> &requests) = 0;
+    virtual status_t captureList(const List<const CameraMetadata> &requests,
+                                 int64_t *lastFrameNumber = NULL) = 0;
 
     /**
      * Submit request for streaming. The CameraDevice makes a copy of the
      * passed-in buffer and the caller retains ownership.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
      */
-    virtual status_t setStreamingRequest(const CameraMetadata &request) = 0;
+    virtual status_t setStreamingRequest(const CameraMetadata &request,
+                                         int64_t *lastFrameNumber = NULL) = 0;
 
     /**
      * Submit a list of requests for streaming.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
      */
-    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests) = 0;
+    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+                                             int64_t *lastFrameNumber = NULL) = 0;
 
     /**
      * Clear the streaming request slot.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
      */
-    virtual status_t clearStreamingRequest() = 0;
+    virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL) = 0;
 
     /**
      * Wait until a request with the given ID has been dequeued by the
@@ -153,11 +163,12 @@
         // API1 and API2.
 
         // Required for API 1 and 2
-        virtual void notifyError(int errorCode, int arg1, int arg2) = 0;
+        virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                                 const CaptureResultExtras &resultExtras) = 0;
 
         // Required only for API2
         virtual void notifyIdle() = 0;
-        virtual void notifyShutter(int requestId,
+        virtual void notifyShutter(const CaptureResultExtras &resultExtras,
                 nsecs_t timestamp) = 0;
 
         // Required only for API1
@@ -190,11 +201,12 @@
     virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
 
     /**
-     * Get next metadata frame from the frame queue. Returns NULL if the queue
-     * is empty; caller takes ownership of the metadata buffer.
-     * May be called concurrently to most methods, except for waitForNextFrame
+     * Get next capture result frame from the result queue. Returns NOT_ENOUGH_DATA
+     * if the queue is empty; caller takes ownership of the metadata buffer inside
+     * the capture result object's metadata field.
+     * May be called concurrently to most methods, except for waitForNextFrame.
      */
-    virtual status_t getNextFrame(CameraMetadata *frame) = 0;
+    virtual status_t getNextResult(CaptureResult *frame) = 0;
 
     /**
      * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel
@@ -235,8 +247,9 @@
     /**
      * Flush all pending and in-flight requests. Blocks until flush is
      * complete.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
      */
-    virtual status_t flush() = 0;
+    virtual status_t flush(int64_t *lastFrameNumber = NULL) = 0;
 
 };
 
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index 4d31667..f6a971a 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -99,15 +99,17 @@
 void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
     status_t res;
     ATRACE_CALL();
-    CameraMetadata frame;
+    CaptureResult result;
 
     ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId());
 
-    while ( (res = device->getNextFrame(&frame)) == OK) {
+    while ( (res = device->getNextResult(&result)) == OK) {
 
+        // TODO: instead of getting frame number from metadata, we should read
+        // this from result.mResultExtras when CameraDeviceBase interface is fixed.
         camera_metadata_entry_t entry;
 
-        entry = frame.find(ANDROID_REQUEST_FRAME_COUNT);
+        entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
         if (entry.count == 0) {
             ALOGE("%s: Camera %d: Error reading frame number",
                     __FUNCTION__, device->getId());
@@ -115,13 +117,13 @@
         }
         ATRACE_INT("cam2_frame", entry.data.i32[0]);
 
-        if (!processSingleFrame(frame, device)) {
+        if (!processSingleFrame(result, device)) {
             break;
         }
 
-        if (!frame.isEmpty()) {
+        if (!result.mMetadata.isEmpty()) {
             Mutex::Autolock al(mLastFrameMutex);
-            mLastFrame.acquire(frame);
+            mLastFrame.acquire(result.mMetadata);
         }
     }
     if (res != NOT_ENOUGH_DATA) {
@@ -133,21 +135,22 @@
     return;
 }
 
-bool FrameProcessorBase::processSingleFrame(CameraMetadata &frame,
-                                           const sp<CameraDeviceBase> &device) {
+bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
+                                            const sp<CameraDeviceBase> &device) {
     ALOGV("%s: Camera %d: Process single frame (is empty? %d)",
-          __FUNCTION__, device->getId(), frame.isEmpty());
-    return processListeners(frame, device) == OK;
+          __FUNCTION__, device->getId(), result.mMetadata.isEmpty());
+    return processListeners(result, device) == OK;
 }
 
-status_t FrameProcessorBase::processListeners(const CameraMetadata &frame,
+status_t FrameProcessorBase::processListeners(const CaptureResult &result,
         const sp<CameraDeviceBase> &device) {
     ATRACE_CALL();
+
     camera_metadata_ro_entry_t entry;
 
     // Quirks: Don't deliver partial results to listeners that don't want them
     bool quirkIsPartial = false;
-    entry = frame.find(ANDROID_QUIRKS_PARTIAL_RESULT);
+    entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT);
     if (entry.count != 0 &&
             entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
         ALOGV("%s: Camera %d: Not forwarding partial result to listeners",
@@ -155,10 +158,13 @@
         quirkIsPartial = true;
     }
 
-    entry = frame.find(ANDROID_REQUEST_ID);
+    // TODO: instead of getting requestID from CameraMetadata, we should get it
+    // from CaptureResultExtras. This will require changing Camera2Device.
+    // Currently Camera2Device uses MetadataQueue to store results, which does not
+    // include CaptureResultExtras.
+    entry = result.mMetadata.find(ANDROID_REQUEST_ID);
     if (entry.count == 0) {
-        ALOGE("%s: Camera %d: Error reading frame id",
-                __FUNCTION__, device->getId());
+        ALOGE("%s: Camera %d: Error reading frame id", __FUNCTION__, device->getId());
         return BAD_VALUE;
     }
     int32_t requestId = entry.data.i32[0];
@@ -169,9 +175,8 @@
 
         List<RangeListener>::iterator item = mRangeListeners.begin();
         while (item != mRangeListeners.end()) {
-            if (requestId >= item->minId &&
-                    requestId < item->maxId &&
-                    (!quirkIsPartial || item->quirkSendPartials) ) {
+            if (requestId >= item->minId && requestId < item->maxId &&
+                    (!quirkIsPartial || item->quirkSendPartials)) {
                 sp<FilteredListener> listener = item->listener.promote();
                 if (listener == 0) {
                     item = mRangeListeners.erase(item);
@@ -183,10 +188,12 @@
             item++;
         }
     }
-    ALOGV("Got %zu range listeners out of %zu", listeners.size(), mRangeListeners.size());
+    ALOGV("%s: Camera %d: Got %zu range listeners out of %zu", __FUNCTION__,
+          device->getId(), listeners.size(), mRangeListeners.size());
+
     List<sp<FilteredListener> >::iterator item = listeners.begin();
     for (; item != listeners.end(); item++) {
-        (*item)->onFrameAvailable(requestId, frame);
+        (*item)->onResultAvailable(result);
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h
index 89b608a..15a014e 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.h
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.h
@@ -23,6 +23,7 @@
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
 #include <camera/CameraMetadata.h>
+#include <camera/CaptureResult.h>
 
 namespace android {
 
@@ -39,8 +40,7 @@
     virtual ~FrameProcessorBase();
 
     struct FilteredListener: virtual public RefBase {
-        virtual void onFrameAvailable(int32_t requestId,
-                                      const CameraMetadata &frame) = 0;
+        virtual void onResultAvailable(const CaptureResult &result) = 0;
     };
 
     // Register a listener for a range of IDs [minId, maxId). Multiple listeners
@@ -72,10 +72,10 @@
 
     void processNewFrames(const sp<CameraDeviceBase> &device);
 
-    virtual bool processSingleFrame(CameraMetadata &frame,
+    virtual bool processSingleFrame(CaptureResult &result,
                                     const sp<CameraDeviceBase> &device);
 
-    status_t processListeners(const CameraMetadata &frame,
+    status_t processListeners(const CaptureResult &result,
                               const sp<CameraDeviceBase> &device);
 
     CameraMetadata mLastFrame;
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 0cc3a04..c33c166 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -199,7 +199,7 @@
     return mDeviceInfo;
 }
 
-status_t Camera2Device::capture(CameraMetadata &request) {
+status_t Camera2Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     ALOGV("%s: E", __FUNCTION__);
 
@@ -207,27 +207,29 @@
     return OK;
 }
 
-status_t Camera2Device::captureList(const List<const CameraMetadata> &requests) {
+status_t Camera2Device::captureList(const List<const CameraMetadata> &requests,
+                                    int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     ALOGE("%s: Camera2Device burst capture not implemented", __FUNCTION__);
     return INVALID_OPERATION;
 }
 
-
-status_t Camera2Device::setStreamingRequest(const CameraMetadata &request) {
+status_t Camera2Device::setStreamingRequest(const CameraMetadata &request,
+                                            int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     ALOGV("%s: E", __FUNCTION__);
     CameraMetadata streamRequest(request);
     return mRequestQueue.setStreamSlot(streamRequest.release());
 }
 
-status_t Camera2Device::setStreamingRequestList(const List<const CameraMetadata> &requests) {
+status_t Camera2Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
+                                                int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     ALOGE("%s, Camera2Device streaming burst not implemented", __FUNCTION__);
     return INVALID_OPERATION;
 }
 
-status_t Camera2Device::clearStreamingRequest() {
+status_t Camera2Device::clearStreamingRequest(int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     return mRequestQueue.setStreamSlot(NULL);
 }
@@ -460,7 +462,13 @@
     if (listener != NULL) {
         switch (msg_type) {
             case CAMERA2_MSG_ERROR:
-                listener->notifyError(ext1, ext2, ext3);
+                // TODO: This needs to be fixed. ext2 and ext3 need to be considered.
+                listener->notifyError(
+                        ((ext1 == CAMERA2_MSG_ERROR_DEVICE)
+                        || (ext1 == CAMERA2_MSG_ERROR_HARDWARE)) ?
+                                ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE :
+                                ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE,
+                        CaptureResultExtras());
                 break;
             case CAMERA2_MSG_SHUTTER: {
                 // TODO: Only needed for camera2 API, which is unsupported
@@ -489,16 +497,22 @@
     return mFrameQueue.waitForBuffer(timeout);
 }
 
-status_t Camera2Device::getNextFrame(CameraMetadata *frame) {
+status_t Camera2Device::getNextResult(CaptureResult *result) {
     ATRACE_CALL();
+    ALOGV("%s: get CaptureResult", __FUNCTION__);
+    if (result == NULL) {
+        ALOGE("%s: result pointer is NULL", __FUNCTION__);
+        return BAD_VALUE;
+    }
     status_t res;
     camera_metadata_t *rawFrame;
     res = mFrameQueue.dequeue(&rawFrame);
-    if (rawFrame  == NULL) {
+    if (rawFrame == NULL) {
         return NOT_ENOUGH_DATA;
     } else if (res == OK) {
-        frame->acquire(rawFrame);
+        result->mMetadata.acquire(rawFrame);
     }
+
     return res;
 }
 
@@ -568,7 +582,7 @@
     return res;
 }
 
-status_t Camera2Device::flush() {
+status_t Camera2Device::flush(int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
 
     mRequestQueue.clear();
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 61bfd1a..22a13ac 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -47,11 +47,14 @@
     virtual status_t disconnect();
     virtual status_t dump(int fd, const Vector<String16>& args);
     virtual const CameraMetadata& info() const;
-    virtual status_t capture(CameraMetadata &request);
-    virtual status_t captureList(const List<const CameraMetadata> &requests);
-    virtual status_t setStreamingRequest(const CameraMetadata &request);
-    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests);
-    virtual status_t clearStreamingRequest();
+    virtual status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL);
+    virtual status_t captureList(const List<const CameraMetadata> &requests,
+                                 int64_t *lastFrameNumber = NULL);
+    virtual status_t setStreamingRequest(const CameraMetadata &request,
+                                         int64_t *lastFrameNumber = NULL);
+    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+                                             int64_t *lastFrameNumber = NULL);
+    virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
     virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
     virtual status_t createStream(sp<ANativeWindow> consumer,
             uint32_t width, uint32_t height, int format, size_t size,
@@ -67,14 +70,14 @@
     virtual status_t setNotifyCallback(NotificationListener *listener);
     virtual bool     willNotify3A();
     virtual status_t waitForNextFrame(nsecs_t timeout);
-    virtual status_t getNextFrame(CameraMetadata *frame);
+    virtual status_t getNextResult(CaptureResult *frame);
     virtual status_t triggerAutofocus(uint32_t id);
     virtual status_t triggerCancelAutofocus(uint32_t id);
     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();
+    virtual status_t flush(int64_t *lastFrameNumber = NULL);
   private:
     const int mId;
     camera2_device_t *mHal2Device;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f586e75..a64917d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -399,6 +399,7 @@
         return BAD_VALUE;
     }
 
+    int32_t burstId = 0;
     for (List<const CameraMetadata>::const_iterator it = metadataList.begin();
             it != metadataList.end(); ++it) {
         sp<CaptureRequest> newRequest = setUpRequestLocked(*it);
@@ -406,12 +407,29 @@
             CLOGE("Can't create capture request");
             return BAD_VALUE;
         }
+
+        // Setup burst Id and request Id
+        newRequest->mResultExtras.burstId = burstId++;
+        if (it->exists(ANDROID_REQUEST_ID)) {
+            if (it->find(ANDROID_REQUEST_ID).count == 0) {
+                CLOGE("RequestID entry exists; but must not be empty in metadata");
+                return BAD_VALUE;
+            }
+            newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0];
+        } else {
+            CLOGE("RequestID does not exist in metadata");
+            return BAD_VALUE;
+        }
+
         requestList->push_back(newRequest);
+        if (newRequest->mResultExtras.requestId > 0) {
+            ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
+        }
     }
     return OK;
 }
 
-status_t Camera3Device::capture(CameraMetadata &request) {
+status_t Camera3Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     status_t res;
     Mutex::Autolock il(mInterfaceLock);
@@ -459,7 +477,7 @@
 }
 
 status_t Camera3Device::submitRequestsHelper(
-        const List<const CameraMetadata> &requests, bool repeating) {
+        const List<const CameraMetadata> &requests, bool repeating, int64_t *lastFrameNumber) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
@@ -479,9 +497,15 @@
     }
 
     if (repeating) {
+        if (lastFrameNumber != NULL) {
+            *lastFrameNumber = mRequestThread->getLastFrameNumber();
+        }
         res = mRequestThread->setRepeatingRequests(requestList);
     } else {
         res = mRequestThread->queueRequestList(requestList);
+        if (lastFrameNumber != NULL) {
+            *lastFrameNumber = mRequestThread->getLastFrameNumber();
+        }
     }
 
     if (res == OK) {
@@ -499,13 +523,15 @@
     return res;
 }
 
-status_t Camera3Device::captureList(const List<const CameraMetadata> &requests) {
+status_t Camera3Device::captureList(const List<const CameraMetadata> &requests,
+                                    int64_t *lastFrameNumber) {
     ATRACE_CALL();
 
-    return submitRequestsHelper(requests, /*repeating*/false);
+    return submitRequestsHelper(requests, /*repeating*/false, lastFrameNumber);
 }
 
-status_t Camera3Device::setStreamingRequest(const CameraMetadata &request) {
+status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
+                                            int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
     status_t res;
     Mutex::Autolock il(mInterfaceLock);
@@ -550,10 +576,11 @@
     return res;
 }
 
-status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests) {
+status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
+                                                int64_t *lastFrameNumber) {
     ATRACE_CALL();
 
-    return submitRequestsHelper(requests, /*repeating*/true);
+    return submitRequestsHelper(requests, /*repeating*/true, lastFrameNumber);
 }
 
 sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
@@ -576,7 +603,7 @@
     return newRequest;
 }
 
-status_t Camera3Device::clearStreamingRequest() {
+status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
@@ -598,6 +625,13 @@
             return INVALID_OPERATION;
     }
     ALOGV("Camera %d: Clearing repeating request", mId);
+
+    if (lastFrameNumber != NULL) {
+        *lastFrameNumber = mRequestThread->getLastFrameNumber();
+        ALOGV("%s: lastFrameNumber address %p, value %" PRId64, __FUNCTION__, lastFrameNumber,
+              *lastFrameNumber);
+    }
+
     return mRequestThread->clearRepeatingRequests();
 }
 
@@ -1115,7 +1149,7 @@
     return OK;
 }
 
-status_t Camera3Device::getNextFrame(CameraMetadata *frame) {
+status_t Camera3Device::getNextResult(CaptureResult *frame) {
     ATRACE_CALL();
     Mutex::Autolock l(mOutputLock);
 
@@ -1123,8 +1157,14 @@
         return NOT_ENOUGH_DATA;
     }
 
-    CameraMetadata &result = *(mResultQueue.begin());
-    frame->acquire(result);
+    if (frame == NULL) {
+        ALOGE("%s: argument cannot be NULL", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    CaptureResult &result = *(mResultQueue.begin());
+    frame->mResultExtras = result.mResultExtras;
+    frame->mMetadata.acquire(result.mMetadata);
     mResultQueue.erase(mResultQueue.begin());
 
     return OK;
@@ -1202,12 +1242,16 @@
     return INVALID_OPERATION;
 }
 
-status_t Camera3Device::flush() {
+status_t Camera3Device::flush(int64_t *frameNumber) {
     ATRACE_CALL();
     ALOGV("%s: Camera %d: Flushing all requests", __FUNCTION__, mId);
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
+    if (frameNumber != NULL) {
+        *frameNumber = mRequestThread->getLastFrameNumber();
+    }
+
     mRequestThread->clear();
     status_t res;
     if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) {
@@ -1484,13 +1528,13 @@
  * In-flight request management
  */
 
-status_t Camera3Device::registerInFlight(int32_t frameNumber,
-        int32_t requestId, int32_t numBuffers) {
+status_t Camera3Device::registerInFlight(uint32_t frameNumber,
+        int32_t numBuffers, CaptureResultExtras resultExtras) {
     ATRACE_CALL();
     Mutex::Autolock l(mInFlightLock);
 
     ssize_t res;
-    res = mInFlightMap.add(frameNumber, InFlightRequest(requestId, numBuffers));
+    res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras));
     if (res < 0) return res;
 
     return OK;
@@ -1502,8 +1546,8 @@
  * to the output frame queue
  */
 bool Camera3Device::processPartial3AQuirk(
-        int32_t frameNumber, int32_t requestId,
-        const CameraMetadata& partial) {
+        uint32_t frameNumber,
+        const CameraMetadata& partial, const CaptureResultExtras& resultExtras) {
 
     // Check if all 3A states are present
     // The full list of fields is
@@ -1567,58 +1611,63 @@
 
     Mutex::Autolock l(mOutputLock);
 
-    CameraMetadata& min3AResult =
-            *mResultQueue.insert(
-                mResultQueue.end(),
-                CameraMetadata(kMinimal3AResultEntries, /*dataCapacity*/ 0));
+    CaptureResult captureResult;
+    captureResult.mResultExtras = resultExtras;
+    captureResult.mMetadata = CameraMetadata(kMinimal3AResultEntries, /*dataCapacity*/ 0);
+    // TODO: change this to sp<CaptureResult>. This will need other changes, including,
+    // but not limited to CameraDeviceBase::getNextResult
+    CaptureResult& min3AResult =
+            *mResultQueue.insert(mResultQueue.end(), captureResult);
 
-    if (!insert3AResult(min3AResult, ANDROID_REQUEST_FRAME_COUNT,
-            &frameNumber, frameNumber)) {
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_FRAME_COUNT,
+            // TODO: This is problematic casting. Need to fix CameraMetadata.
+            reinterpret_cast<int32_t*>(&frameNumber), frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_REQUEST_ID,
+    int32_t requestId = resultExtras.requestId;
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_REQUEST_ID,
             &requestId, frameNumber)) {
         return false;
     }
 
     static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL;
-    if (!insert3AResult(min3AResult, ANDROID_QUIRKS_PARTIAL_RESULT,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_QUIRKS_PARTIAL_RESULT,
             &partialResult, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_MODE,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_MODE,
             &afMode, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AWB_MODE,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_MODE,
             &awbMode, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AE_STATE,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_STATE,
             &aeState, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_STATE,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_STATE,
             &afState, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AWB_STATE,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AWB_STATE,
             &awbState, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AF_TRIGGER_ID,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AF_TRIGGER_ID,
             &afTriggerId, frameNumber)) {
         return false;
     }
 
-    if (!insert3AResult(min3AResult, ANDROID_CONTROL_AE_PRECAPTURE_ID,
+    if (!insert3AResult(min3AResult.mMetadata, ANDROID_CONTROL_AE_PRECAPTURE_ID,
             &aeTriggerId, frameNumber)) {
         return false;
     }
@@ -1630,7 +1679,7 @@
 
 template<typename T>
 bool Camera3Device::get3AResult(const CameraMetadata& result, int32_t tag,
-        T* value, int32_t frameNumber) {
+        T* value, uint32_t frameNumber) {
     (void) frameNumber;
 
     camera_metadata_ro_entry_t entry;
@@ -1655,7 +1704,7 @@
 
 template<typename T>
 bool Camera3Device::insert3AResult(CameraMetadata& result, int32_t tag,
-        const T* value, int32_t frameNumber) {
+        const T* value, uint32_t frameNumber) {
     if (result.update(tag, value, 1) != NO_ERROR) {
         mResultQueue.erase(--mResultQueue.end(), mResultQueue.end());
         SET_ERR("Frame %d: Failed to set %s in partial metadata",
@@ -1682,11 +1731,12 @@
     }
     bool partialResultQuirk = false;
     CameraMetadata collectedQuirkResult;
+    CaptureResultExtras resultExtras;
 
-    // Get capture timestamp from list of in-flight requests, where it was added
-    // by the shutter notification for this frame. Then update the in-flight
-    // status and remove the in-flight entry if all result data has been
-    // received.
+    // Get capture timestamp and resultExtras from list of in-flight requests,
+    // where it was added by the shutter notification for this frame.
+    // Then update the in-flight status and remove the in-flight entry if
+    // all result data has been received.
     nsecs_t timestamp = 0;
     {
         Mutex::Autolock l(mInFlightLock);
@@ -1697,6 +1747,10 @@
             return;
         }
         InFlightRequest &request = mInFlightMap.editValueAt(idx);
+        ALOGVV("%s: got InFlightRequest requestId = %" PRId32 ", frameNumber = %" PRId64
+                ", burstId = %" PRId32,
+                __FUNCTION__, request.resultExtras.requestId, request.resultExtras.frameNumber,
+                request.resultExtras.burstId);
 
         // Check if this result carries only partial metadata
         if (mUsePartialResultQuirk && result->result != NULL) {
@@ -1718,13 +1772,17 @@
                 if (!request.partialResultQuirk.haveSent3A) {
                     request.partialResultQuirk.haveSent3A =
                             processPartial3AQuirk(frameNumber,
-                                    request.requestId,
-                                    request.partialResultQuirk.collectedResult);
+                                    request.partialResultQuirk.collectedResult,
+                                    request.resultExtras);
                 }
             }
         }
 
         timestamp = request.captureTimestamp;
+        resultExtras = request.resultExtras;
+        ALOGVV("%s: after checking partial burstId = %d, frameNumber %lld", __FUNCTION__,
+                request.resultExtras.burstId, request.resultExtras.frameNumber);
+
         /**
          * One of the following must happen before it's legal to call process_capture_result,
          * unless partial metadata is being provided:
@@ -1791,11 +1849,12 @@
         }
         mNextResultFrameNumber++;
 
-        CameraMetadata captureResult;
-        captureResult = result->result;
+        CaptureResult captureResult;
+        captureResult.mResultExtras = resultExtras;
+        captureResult.mMetadata = result->result;
 
-        if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
-                        (int32_t*)&frameNumber, 1) != OK) {
+        if (captureResult.mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
+                (int32_t*)&frameNumber, 1) != OK) {
             SET_ERR("Failed to set frame# in metadata (%d)",
                     frameNumber);
             gotResult = false;
@@ -1806,15 +1865,15 @@
 
         // Append any previous partials to form a complete result
         if (mUsePartialResultQuirk && !collectedQuirkResult.isEmpty()) {
-            captureResult.append(collectedQuirkResult);
+            captureResult.mMetadata.append(collectedQuirkResult);
         }
 
-        captureResult.sort();
+        captureResult.mMetadata.sort();
 
         // Check that there's a timestamp in the result metadata
 
         camera_metadata_entry entry =
-                captureResult.find(ANDROID_SENSOR_TIMESTAMP);
+                captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
         if (entry.count == 0) {
             SET_ERR("No timestamp provided by HAL for frame %d!",
                     frameNumber);
@@ -1828,9 +1887,13 @@
 
         if (gotResult) {
             // Valid result, insert into queue
-            CameraMetadata& queuedResult =
-                *mResultQueue.insert(mResultQueue.end(), CameraMetadata());
-            queuedResult.swap(captureResult);
+            List<CaptureResult>::iterator queuedResult =
+                    mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
+            ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+                   ", burstId = %" PRId32, __FUNCTION__,
+                   queuedResult->mResultExtras.requestId,
+                   queuedResult->mResultExtras.frameNumber,
+                   queuedResult->mResultExtras.burstId);
         }
     } // scope for mOutputLock
 
@@ -1856,8 +1919,6 @@
 
 }
 
-
-
 void Camera3Device::notify(const camera3_notify_msg *msg) {
     ATRACE_CALL();
     NotificationListener *listener;
@@ -1884,18 +1945,32 @@
                     mId, __FUNCTION__, msg->message.error.frame_number,
                     streamId, msg->message.error.error_code);
 
+            CaptureResultExtras resultExtras;
             // Set request error status for the request in the in-flight tracking
             {
                 Mutex::Autolock l(mInFlightLock);
                 ssize_t idx = mInFlightMap.indexOfKey(msg->message.error.frame_number);
                 if (idx >= 0) {
-                    mInFlightMap.editValueAt(idx).requestStatus = msg->message.error.error_code;
+                    InFlightRequest &r = mInFlightMap.editValueAt(idx);
+                    r.requestStatus = msg->message.error.error_code;
+                    resultExtras = r.resultExtras;
+                } else {
+                    resultExtras.frameNumber = msg->message.error.frame_number;
+                    ALOGE("Camera %d: %s: cannot find in-flight request on frame %" PRId64
+                          " error", mId, __FUNCTION__, resultExtras.frameNumber);
                 }
             }
 
             if (listener != NULL) {
-                listener->notifyError(msg->message.error.error_code,
-                        msg->message.error.frame_number, streamId);
+                if (msg->message.error.error_code == CAMERA3_MSG_ERROR_DEVICE) {
+                    listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                                          resultExtras);
+                } else {
+                    listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE,
+                                          resultExtras);
+                }
+            } else {
+                ALOGE("Camera %d: %s: no listener available", mId, __FUNCTION__);
             }
             break;
         }
@@ -1915,7 +1990,7 @@
                 mNextShutterFrameNumber++;
             }
 
-            int32_t requestId = -1;
+            CaptureResultExtras resultExtras;
 
             // Set timestamp for the request in the in-flight tracking
             // and get the request ID to send upstream
@@ -1925,7 +2000,7 @@
                 if (idx >= 0) {
                     InFlightRequest &r = mInFlightMap.editValueAt(idx);
                     r.captureTimestamp = timestamp;
-                    requestId = r.requestId;
+                    resultExtras = r.resultExtras;
                 }
             }
             if (idx < 0) {
@@ -1934,10 +2009,10 @@
                 break;
             }
             ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64,
-                    mId, __FUNCTION__, frameNumber, requestId, timestamp);
+                    mId, __FUNCTION__, frameNumber, resultExtras.requestId, timestamp);
             // Call listener, if any
             if (listener != NULL) {
-                listener->notifyShutter(requestId, timestamp);
+                listener->notifyShutter(resultExtras, timestamp);
             }
             break;
         }
@@ -1959,6 +2034,7 @@
     return retVal;
 }
 
+
 /**
  * RequestThread inner class methods
  */
@@ -1975,7 +2051,8 @@
         mDoPause(false),
         mPaused(true),
         mFrameNumber(0),
-        mLatestRequestId(NAME_NOT_FOUND) {
+        mLatestRequestId(NAME_NOT_FOUND),
+        mLastFrameNumber(-1) {
     mStatusId = statusTracker->addComponent();
 }
 
@@ -1989,6 +2066,8 @@
     Mutex::Autolock l(mRequestLock);
     mRequestQueue.push_back(request);
 
+    mLastFrameNumber++;
+
     unpauseForNewRequests();
 
     return OK;
@@ -2002,6 +2081,8 @@
         mRequestQueue.push_back(*it);
     }
 
+    mLastFrameNumber += requests.size();
+
     unpauseForNewRequests();
 
     return OK;
@@ -2086,6 +2167,7 @@
     mRepeatingRequests.clear();
     mRequestQueue.clear();
     mTriggerMap.clear();
+    // Question: no need to reset frame number?
     return OK;
 }
 
@@ -2242,6 +2324,8 @@
     }
 
     request.frame_number = mFrameNumber++;
+    // Update frameNumber of CaptureResultExtras
+    nextRequest->mResultExtras.frameNumber = request.frame_number;
 
     // Log request in the in-flight queue
     sp<Camera3Device> parent = mParent.promote();
@@ -2251,8 +2335,12 @@
         return false;
     }
 
-    res = parent->registerInFlight(request.frame_number, requestId,
-            request.num_output_buffers);
+    res = parent->registerInFlight(request.frame_number,
+            request.num_output_buffers, nextRequest->mResultExtras);
+    ALOGVV("%s: registered in flight requestId = %d, frameNumber = %lld, burstId = %d ",
+            __FUNCTION__,
+            nextRequest->mResultExtras.requestId, nextRequest->mResultExtras.frameNumber,
+            nextRequest->mResultExtras.burstId);
     if (res != OK) {
         SET_ERR("RequestThread: Unable to register new in-flight request:"
                 " %s (%d)", strerror(-res), res);
@@ -2329,6 +2417,14 @@
     return mLatestRequest;
 }
 
+int64_t Camera3Device::RequestThread::getLastFrameNumber() {
+    Mutex::Autolock al(mRequestLock);
+
+    ALOGV("RequestThread::%s", __FUNCTION__);
+
+    return mLastFrameNumber;
+}
+
 void Camera3Device::RequestThread::cleanUpFailedRequest(
         camera3_capture_request_t &request,
         sp<CaptureRequest> &nextRequest,
@@ -2370,6 +2466,9 @@
                     ++firstRequest,
                     requests.end());
             // No need to wait any longer
+
+            mLastFrameNumber += requests.size();
+
             break;
         }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ed58246..b1ea5ed 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -24,6 +24,7 @@
 #include <utils/Thread.h>
 #include <utils/KeyedVector.h>
 #include <hardware/camera3.h>
+#include <camera/CaptureResult.h>
 
 #include "common/CameraDeviceBase.h"
 #include "device3/StatusTracker.h"
@@ -78,11 +79,14 @@
 
     // Capture and setStreamingRequest will configure streams if currently in
     // idle state
-    virtual status_t capture(CameraMetadata &request);
-    virtual status_t captureList(const List<const CameraMetadata> &requests);
-    virtual status_t setStreamingRequest(const CameraMetadata &request);
-    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests);
-    virtual status_t clearStreamingRequest();
+    virtual status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL);
+    virtual status_t captureList(const List<const CameraMetadata> &requests,
+                                 int64_t *lastFrameNumber = NULL);
+    virtual status_t setStreamingRequest(const CameraMetadata &request,
+                                         int64_t *lastFrameNumber = NULL);
+    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+                                             int64_t *lastFrameNumber = NULL);
+    virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
 
     virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
 
@@ -118,7 +122,7 @@
     virtual status_t setNotifyCallback(NotificationListener *listener);
     virtual bool     willNotify3A();
     virtual status_t waitForNextFrame(nsecs_t timeout);
-    virtual status_t getNextFrame(CameraMetadata *frame);
+    virtual status_t getNextResult(CaptureResult *frame);
 
     virtual status_t triggerAutofocus(uint32_t id);
     virtual status_t triggerCancelAutofocus(uint32_t id);
@@ -127,7 +131,7 @@
     virtual status_t pushReprocessBuffer(int reprocessStreamId,
             buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
 
-    virtual status_t flush();
+    virtual status_t flush(int64_t *lastFrameNumber = NULL);
 
     // Methods called by subclasses
     void             notifyStatus(bool idle); // updates from StatusTracker
@@ -200,6 +204,7 @@
         sp<camera3::Camera3Stream>          mInputStream;
         Vector<sp<camera3::Camera3OutputStreamInterface> >
                                             mOutputStreams;
+        CaptureResultExtras                 mResultExtras;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -209,7 +214,8 @@
             const List<const CameraMetadata> &metadataList,
             /*out*/RequestList *requestList);
 
-    status_t submitRequestsHelper(const List<const CameraMetadata> &requests, bool repeating);
+    status_t submitRequestsHelper(const List<const CameraMetadata> &requests, bool repeating,
+                                  int64_t *lastFrameNumber = NULL);
 
     /**
      * Get the last request submitted to the hal by the request thread.
@@ -371,6 +377,8 @@
          */
         CameraMetadata getLatestRequest() const;
 
+        int64_t getLastFrameNumber();
+
       protected:
 
         virtual bool threadLoop();
@@ -447,6 +455,8 @@
         TriggerMap         mTriggerMap;
         TriggerMap         mTriggerRemovedMap;
         TriggerMap         mTriggerReplacedMap;
+
+        int64_t            mLastFrameNumber;
     };
     sp<RequestThread> mRequestThread;
 
@@ -455,8 +465,6 @@
      */
 
     struct InFlightRequest {
-        // android.request.id for the request
-        int     requestId;
         // Set by notify() SHUTTER call.
         nsecs_t captureTimestamp;
         int     requestStatus;
@@ -465,6 +473,7 @@
         // Decremented by calls to process_capture_result with valid output
         // buffers
         int     numBuffersLeft;
+        CaptureResultExtras resultExtras;
 
         // Fields used by the partial result quirk only
         struct PartialResultQuirkInFlight {
@@ -480,20 +489,26 @@
 
         // Default constructor needed by KeyedVector
         InFlightRequest() :
-                requestId(0),
                 captureTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(0) {
         }
 
-        InFlightRequest(int id, int numBuffers) :
-                requestId(id),
+        InFlightRequest(int numBuffers) :
                 captureTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(numBuffers) {
         }
+
+        InFlightRequest(int numBuffers, CaptureResultExtras extras) :
+                captureTimestamp(0),
+                requestStatus(OK),
+                haveResultMetadata(false),
+                numBuffersLeft(numBuffers),
+                resultExtras(extras) {
+        }
     };
     // Map from frame number to the in-flight request state
     typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
@@ -501,25 +516,25 @@
     Mutex                  mInFlightLock; // Protects mInFlightMap
     InFlightMap            mInFlightMap;
 
-    status_t registerInFlight(int32_t frameNumber, int32_t requestId,
-            int32_t numBuffers);
+    status_t registerInFlight(uint32_t frameNumber,
+            int32_t numBuffers, CaptureResultExtras resultExtras);
 
     /**
      * For the partial result quirk, check if all 3A state fields are available
      * and if so, queue up 3A-only result to the client. Returns true if 3A
      * is sent.
      */
-    bool processPartial3AQuirk(int32_t frameNumber, int32_t requestId,
-            const CameraMetadata& partial);
+    bool processPartial3AQuirk(uint32_t frameNumber,
+            const CameraMetadata& partial, const CaptureResultExtras& resultExtras);
 
     // Helpers for reading and writing 3A metadata into to/from partial results
     template<typename T>
     bool get3AResult(const CameraMetadata& result, int32_t tag,
-            T* value, int32_t frameNumber);
+            T* value, uint32_t frameNumber);
 
     template<typename T>
     bool insert3AResult(CameraMetadata &result, int32_t tag, const T* value,
-            int32_t frameNumber);
+            uint32_t frameNumber);
     /**
      * Tracking for idle detection
      */
@@ -536,7 +551,7 @@
 
     uint32_t               mNextResultFrameNumber;
     uint32_t               mNextShutterFrameNumber;
-    List<CameraMetadata>   mResultQueue;
+    List<CaptureResult>   mResultQueue;
     Condition              mResultSignal;
     NotificationListener  *mListener;
 
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index d662cc2..2257682 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -146,6 +146,13 @@
     // Inform tracker about becoming busy
     if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
             mState != STATE_IN_RECONFIG) {
+        /**
+         * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
+         * before/after register_stream_buffers during initial configuration
+         * or re-configuration.
+         *
+         * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2
+         */
         sp<StatusTracker> statusTracker = mStatusTracker.promote();
         if (statusTracker != 0) {
             statusTracker->markComponentActive(mStatusId);
@@ -224,6 +231,13 @@
     mDequeuedBufferCount--;
     if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
             mState != STATE_IN_RECONFIG) {
+        /**
+         * Avoid a spurious IDLE->ACTIVE->IDLE transition when using buffers
+         * before/after register_stream_buffers during initial configuration
+         * or re-configuration.
+         *
+         * TODO: IN_CONFIG and IN_RECONFIG checks only make sense for <HAL3.2
+         */
         ALOGV("%s: Stream %d: All buffers returned; now idle", __FUNCTION__,
                 mId);
         sp<StatusTracker> statusTracker = mStatusTracker.promote();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 70406f1..646f286 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -23,6 +23,8 @@
 #include "device3/Camera3Stream.h"
 #include "device3/StatusTracker.h"
 
+#include <cutils/properties.h>
+
 namespace android {
 
 namespace camera3 {
@@ -137,6 +139,7 @@
     if (mState == STATE_CONSTRUCTED) {
         mState = STATE_IN_CONFIG;
     } else { // mState == STATE_CONFIGURED
+        LOG_ALWAYS_FATAL_IF(mState != STATE_CONFIGURED, "Invalid state: 0x%x", mState);
         mState = STATE_IN_RECONFIG;
     }
 
@@ -223,6 +226,14 @@
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
 
+    /**
+     * TODO: Check that the state is valid first.
+     *
+     * <HAL3.2 IN_CONFIG and IN_RECONFIG in addition to CONFIGURED.
+     * >= HAL3.2 CONFIGURED only
+     *
+     * Do this for getBuffer as well.
+     */
     status_t res = returnBufferLocked(buffer, timestamp);
     if (res == OK) {
         fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
@@ -314,12 +325,46 @@
 
 status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) {
     ATRACE_CALL();
+
+    /**
+     * >= CAMERA_DEVICE_API_VERSION_3_2:
+     *
+     * camera3_device_t->ops->register_stream_buffers() is not called and must
+     * be NULL.
+     */
+    if (hal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_2) {
+        ALOGV("%s: register_stream_buffers unused as of HAL3.2", __FUNCTION__);
+
+        /**
+         * Skip the NULL check if camera.dev.register_stream is 1.
+         *
+         * For development-validation purposes only.
+         *
+         * TODO: Remove the property check before shipping L (b/13914251).
+         */
+        char value[PROPERTY_VALUE_MAX] = { '\0', };
+        property_get("camera.dev.register_stream", value, "0");
+        int propInt = atoi(value);
+
+        if (propInt == 0 && hal3Device->ops->register_stream_buffers != NULL) {
+            ALOGE("%s: register_stream_buffers is deprecated in HAL3.2; "
+                    "must be set to NULL in camera3_device::ops", __FUNCTION__);
+            return INVALID_OPERATION;
+        } else {
+            ALOGD("%s: Skipping NULL check for deprecated register_stream_buffers");
+        }
+
+        return OK;
+    } else {
+        ALOGV("%s: register_stream_buffers using deprecated code path", __FUNCTION__);
+    }
+
     status_t res;
 
     size_t bufferCount = getBufferCountLocked();
 
     Vector<buffer_handle_t*> buffers;
-    buffers.insertAt(NULL, 0, bufferCount);
+    buffers.insertAt(/*prototype_item*/NULL, /*index*/0, bufferCount);
 
     camera3_stream_buffer_set bufferSet = camera3_stream_buffer_set();
     bufferSet.stream = this;
@@ -327,7 +372,7 @@
     bufferSet.buffers = buffers.editArray();
 
     Vector<camera3_stream_buffer_t> streamBuffers;
-    streamBuffers.insertAt(camera3_stream_buffer_t(), 0, bufferCount);
+    streamBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
 
     // Register all buffers with the HAL. This means getting all the buffers
     // from the stream, providing them to the HAL with the
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 6eeb721..766b772 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -82,6 +82,23 @@
  *    STATE_CONFIGURED     => STATE_CONSTRUCTED:
  *        When disconnect() is called after making sure stream is idle with
  *        waitUntilIdle().
+ *
+ * Status Tracking:
+ *    Each stream is tracked by StatusTracker as a separate component,
+ *    depending on the handed out buffer count. The state must be STATE_CONFIGURED
+ *    in order for the component to be marked.
+ *
+ *    It's marked in one of two ways:
+ *
+ *    - ACTIVE: One or more buffers have been handed out (with #getBuffer).
+ *    - IDLE: All buffers have been returned (with #returnBuffer), and their
+ *          respective release_fence(s) have been signaled.
+ *
+ *    A typical use case is output streams. When the HAL has any buffers
+ *    dequeued, the stream is marked ACTIVE. When the HAL returns all buffers
+ *    (e.g. if no capture requests are active), the stream is marked IDLE.
+ *    In this use case, the app consumer does not affect the component status.
+ *
  */
 class Camera3Stream :
         protected camera3_stream,