Merge "BufferQueue: Increase max slots from 32 to 64"
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/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 6b41fd4..b70afe6 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "stagefright"
 #include <media/stagefright/foundation/ADebug.h>
 
-#include <sys/time.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
 #include "jpeg.h"
 #include "SineSource.h"
 
@@ -51,8 +51,6 @@
 
 #include <private/media/VideoFrame.h>
 
-#include <fcntl.h>
-
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
@@ -648,7 +646,7 @@
                 const CodecProfileLevel &profileLevel =
                      results[i].mProfileLevels[j];
 
-                printf("%s%ld/%ld", j > 0 ? ", " : "",
+                printf("%s%" PRIu32 "/%" PRIu32, j > 0 ? ", " : "",
                     profileLevel.mProfile, profileLevel.mLevel);
             }
 
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index 5400bdd..584c6a6 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -47,7 +47,7 @@
         return false;
     }
 
-    for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) {
+    for (size_t i = 0; i < mMimeTypeVector.size(); i++) {
         const String8 item = mMimeTypeVector.itemAt(i);
 
         if (!strcasecmp(item.string(), mimeType.string())) {
@@ -58,7 +58,7 @@
 }
 
 bool DrmSupportInfo::isSupportedFileSuffix(const String8& fileType) const {
-    for (unsigned int i = 0; i < mFileSuffixVector.size(); i++) {
+    for (size_t i = 0; i < mFileSuffixVector.size(); i++) {
         const String8 item = mFileSuffixVector.itemAt(i);
 
         if (!strcasecmp(item.string(), fileType.string())) {
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index dccd23d..d8aeb0c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -101,7 +101,7 @@
 status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
     mPlugInManager.loadPlugIns(plugInDirPath);
     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
-    for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+    for (size_t i = 0; i < plugInPathList.size(); ++i) {
         String8 plugInPath = plugInPathList[i];
         DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
         if (NULL != info) {
@@ -138,7 +138,7 @@
     Mutex::Autolock _l(mLock);
     if (!mSupportInfoToPlugInIdMap.isEmpty()) {
         Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
-        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+        for (size_t index = 0; index < plugInIdList.size(); index++) {
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
             rDrmEngine.initialize(uniqueId);
             rDrmEngine.setOnInfoListener(uniqueId, this);
@@ -149,7 +149,7 @@
 void DrmManager::removeClient(int uniqueId) {
     Mutex::Autolock _l(mLock);
     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
-    for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+    for (size_t index = 0; index < plugInIdList.size(); index++) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
         rDrmEngine.terminate(uniqueId);
     }
@@ -208,7 +208,7 @@
     bool result = false;
     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
 
-    for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+    for (size_t i = 0; i < plugInPathList.size(); ++i) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
         result = rDrmEngine.canHandle(uniqueId, path);
 
@@ -318,7 +318,7 @@
 status_t DrmManager::removeAllRights(int uniqueId) {
     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
     status_t result = DRM_ERROR_UNKNOWN;
-    for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+    for (size_t index = 0; index < plugInIdList.size(); index++) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
         result = rDrmEngine.removeAllRights(uniqueId);
         if (DRM_NO_ERROR != result) {
@@ -412,7 +412,7 @@
     if (NULL != handle) {
         handle->decryptId = mDecryptSessionId + 1;
 
-        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+        for (size_t index = 0; index < plugInIdList.size(); index++) {
             String8 plugInId = plugInIdList.itemAt(index);
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
             result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime);
@@ -440,7 +440,7 @@
     if (NULL != handle) {
         handle->decryptId = mDecryptSessionId + 1;
 
-        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+        for (size_t index = 0; index < plugInIdList.size(); index++) {
             String8 plugInId = plugInIdList.itemAt(index);
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
             result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime);
@@ -565,7 +565,7 @@
     String8 plugInId("");
 
     if (EMPTY_STRING != mimeType) {
-        for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+        for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
             const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
 
             if (drmSupportInfo.isSupportedMimeType(mimeType)) {
@@ -581,7 +581,7 @@
     String8 plugInId("");
     const String8 fileSuffix = path.getPathExtension();
 
-    for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+    for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
         const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
 
         if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
@@ -599,7 +599,7 @@
 
 void DrmManager::onInfo(const DrmInfoEvent& event) {
     Mutex::Autolock _l(mListenerLock);
-    for (unsigned int index = 0; index < mServiceListeners.size(); index++) {
+    for (size_t index = 0; index < mServiceListeners.size(); index++) {
         int uniqueId = mServiceListeners.keyAt(index);
 
         if (uniqueId == event.getUniqueId()) {
diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h
index 7bb143f..c1d019a 100644
--- a/drm/libdrmframework/include/PlugInManager.h
+++ b/drm/libdrmframework/include/PlugInManager.h
@@ -80,7 +80,7 @@
         Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);
 
         if (!plugInFileList.isEmpty()) {
-            for (unsigned int i = 0; i < plugInFileList.size(); ++i) {
+            for (size_t i = 0; i < plugInFileList.size(); ++i) {
                 loadPlugIn(plugInFileList[i]);
             }
         }
@@ -91,7 +91,7 @@
      *
      */
     void unloadPlugIns() {
-        for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) {
+        for (size_t i = 0; i < m_plugInIdList.size(); ++i) {
             unloadPlugIn(m_plugInIdList[i]);
         }
         m_plugInIdList.clear();
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..913696f 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;
 
@@ -30,6 +31,10 @@
 class CaptureRequest;
 class CameraMetadata;
 
+enum {
+    NO_IN_FLIGHT_REPEATING_FRAMES = -1,
+};
+
 class ICameraDeviceUser : public IInterface
 {
     /**
@@ -44,9 +49,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 +94,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/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 9838ed2..a981d1c 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -56,7 +56,7 @@
     sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
     int64_t mDrmBufOffset;
-    int64_t mDrmBufSize;
+    size_t mDrmBufSize;
     unsigned char *mDrmBuf;
 
     ssize_t readAtDRM(off64_t offset, void *data, size_t size);
diff --git a/libvideoeditor/lvpp/DummyVideoSource.cpp b/libvideoeditor/lvpp/DummyVideoSource.cpp
index b06f937..6dbcf2a 100755
--- a/libvideoeditor/lvpp/DummyVideoSource.cpp
+++ b/libvideoeditor/lvpp/DummyVideoSource.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DummyVideoSource"
+#include <inttypes.h>
 #include <stdlib.h>
 #include <utils/Log.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -146,7 +147,7 @@
     if (mIsFirstImageFrame) {
         M4OSA_clockGetTime(&mImagePlayStartTime, kTimeScale);
         mFrameTimeUs =  (mImageSeekTime + 1);
-        ALOGV("read: jpg 1st frame timeUs = %lld, begin cut time = %ld",
+        ALOGV("read: jpg 1st frame timeUs = %lld, begin cut time = %" PRIu32,
             mFrameTimeUs, mImageSeekTime);
 
         mIsFirstImageFrame = false;
diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
index e60030e..e1a81d8 100755
--- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
+++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #define LOG_NDEBUG 1
 #define LOG_TAG "VideoEditorAudioPlayer"
 #include <utils/Log.h>
@@ -372,7 +374,7 @@
 
         // Get the duration in time of the audio BT
         if ( result == M4NO_ERROR ) {
-         ALOGV("VEAP: channels = %d freq = %d",
+         ALOGV("VEAP: channels = %" PRIu32 " freq = %" PRIu32,
          mAudioMixSettings->uiNbChannels,  mAudioMixSettings->uiSamplingFrequency);
 
             // No trim
@@ -440,7 +442,7 @@
                 // do nothing
             }
 
-            ALOGV("VideoEditorAudioPlayer::startTime %d", startTime);
+            ALOGV("VideoEditorAudioPlayer::startTime %" PRIu32, startTime);
             seekTimeStamp = 0;
             if (startTime) {
                 if (startTime >= mBGAudioPCMFileDuration) {
diff --git a/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp b/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp
index e24fcf4..0c12aac 100755
--- a/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp
+++ b/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "VideoEditorBGAudioProcessing"
 #include <utils/Log.h>
@@ -50,8 +52,8 @@
         void *backgroundTrackBuffer,
         void *outBuffer) {
 
-    ALOGV("mixAndDuck: track buffers (primary: 0x%x and background: 0x%x) "
-            "and out buffer 0x%x",
+    ALOGV("mixAndDuck: track buffers (primary: %p and background: %p) "
+            "and out buffer %p",
             primaryTrackBuffer, backgroundTrackBuffer, outBuffer);
 
     M4AM_Buffer16* pPrimaryTrack   = (M4AM_Buffer16*)primaryTrackBuffer;
@@ -217,7 +219,7 @@
     mDoDucking            = 0;
     mDuckingFactor        = 1.0;
 
-    ALOGV("ducking enable 0x%x lowVolume %f threshold %d "
+    ALOGV("ducking enable 0x%x lowVolume %f threshold %" PRIu32 " "
             "fPTVolLevel %f BTVolLevel %f",
             mDucking_enable, mDucking_lowVolume, mDucking_threshold,
             mPTVolLevel, mPTVolLevel);
diff --git a/libvideoeditor/osal/inc/M4OSA_Types.h b/libvideoeditor/osal/inc/M4OSA_Types.h
index 92a68d8..ee258a0 100755
--- a/libvideoeditor/osal/inc/M4OSA_Types.h
+++ b/libvideoeditor/osal/inc/M4OSA_Types.h
@@ -36,13 +36,13 @@
 #endif
 
 
-typedef signed char     M4OSA_Bool;
-typedef unsigned char   M4OSA_UInt8;
-typedef signed char     M4OSA_Int8;
-typedef unsigned short  M4OSA_UInt16;
-typedef signed short    M4OSA_Int16;
-typedef unsigned long   M4OSA_UInt32;
-typedef signed long     M4OSA_Int32;
+typedef int8_t     M4OSA_Bool;
+typedef uint8_t    M4OSA_UInt8;
+typedef int8_t     M4OSA_Int8;
+typedef uint16_t   M4OSA_UInt16;
+typedef int16_t    M4OSA_Int16;
+typedef uint32_t   M4OSA_UInt32;
+typedef int32_t    M4OSA_Int32;
 
 typedef signed char     M4OSA_Char;
 typedef unsigned char   M4OSA_UChar;
diff --git a/libvideoeditor/osal/src/M4OSA_Thread.c b/libvideoeditor/osal/src/M4OSA_Thread.c
index db54245..3e82fb3 100755
--- a/libvideoeditor/osal/src/M4OSA_Thread.c
+++ b/libvideoeditor/osal/src/M4OSA_Thread.c
@@ -524,7 +524,7 @@
    M4OSA_TRACE2_2("M4OSA_SetThreadSyncPriority\t\tM4OSA_Context 0x%x\t"
                   "M4OSA_DataOption 0x%x", context, optionValue);
 
-   if((M4OSA_UInt32)optionValue>M4OSA_kThreadLowestPriority)
+   if((M4OSA_UInt32)(uintptr_t)optionValue>M4OSA_kThreadLowestPriority)
    {
       return M4ERR_PARAMETER;
    }
@@ -590,7 +590,7 @@
    M4OSA_TRACE2_2("M4OSA_SetThreadSyncStackSize\t\tM4OSA_Context 0x%x\t"
                   "M4OSA_DataOption 0x%x", context, optionValue);
 
-   threadContext->stackSize = (M4OSA_UInt32)optionValue;
+   threadContext->stackSize = (M4OSA_UInt32)(uintptr_t)optionValue;
 
    return M4NO_ERROR;
 }
diff --git a/libvideoeditor/osal/src/M4PSW_DebugTrace.c b/libvideoeditor/osal/src/M4PSW_DebugTrace.c
index 0fcba94..850ed91 100755
--- a/libvideoeditor/osal/src/M4PSW_DebugTrace.c
+++ b/libvideoeditor/osal/src/M4PSW_DebugTrace.c
@@ -25,6 +25,7 @@
 */
 
 
+#include <inttypes.h>
 #include <stdio.h> /*for printf */
 
 #include "M4OSA_Types.h"
@@ -65,9 +66,9 @@
     }
 
 #ifdef NO_FILE
-    printf("Error: %li, on %s: %s\n",err,cond,msg);
+    printf("Error: %" PRIu32 ", on %s: %s\n",err,cond,msg);
 #else /* NO_FILE     */
-    printf("Error: %li, on %s: %s Line %lu in: %s\n",err,cond,msg,line,file);
+    printf("Error: %" PRIu32 ", on %s: %s Line %" PRIu32 " in: %s\n",err,cond,msg,line,file);
 #endif /* NO_FILE     */
 
 }
diff --git a/libvideoeditor/vss/common/inc/marker.h b/libvideoeditor/vss/common/inc/marker.h
deleted file mode 100755
index 83cade0..0000000
--- a/libvideoeditor/vss/common/inc/marker.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 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 MARKER_H
-#define MARKER_H
-
-#define ADD_CODE_MARKER_FUN(m_condition)                    \
-    if ( !(m_condition) )                                   \
-    {                                                       \
-        __asm__ volatile (                                  \
-            ".word     0x21614062\n\t"      /* '!a@b' */    \
-            ".word     0x47712543\n\t"      /* 'Gq%C' */    \
-            ".word     0x5F5F5F43\n\t"      /* '___C' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x245F5F5F"          /* '$___' */    \
-        );                                                  \
-    }
-
-#define ADD_TEXT_MARKER_FUN(m_condition)                    \
-    if ( !(m_condition) )                                   \
-    {                                                       \
-        __asm__ volatile (                                  \
-            ".word     0x21614062\n\t"      /* '!a@b' */    \
-            ".word     0x47712543\n\t"      /* 'Gq%C' */    \
-            ".word     0x5F5F5F54\n\t"      /* '___T' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x5F5F5F5F\n\t"      /* '____' */    \
-            ".word     0x245F5F5F"          /* '$___' */    \
-        );                                                  \
-    }
-
-#endif
diff --git a/libvideoeditor/vss/src/M4PCMR_CoreReader.c b/libvideoeditor/vss/src/M4PCMR_CoreReader.c
index 3343254..19f07dd 100755
--- a/libvideoeditor/vss/src/M4PCMR_CoreReader.c
+++ b/libvideoeditor/vss/src/M4PCMR_CoreReader.c
@@ -690,7 +690,7 @@
     switch(optionID)
     {
         case M4PCMR_kPCMblockSize:
-            c->m_blockSize = (M4OSA_UInt32)Value;
+            c->m_blockSize = (M4OSA_UInt32)(uintptr_t)Value;
             break;
 
         default:
diff --git a/libvideoeditor/vss/src/M4READER_Amr.c b/libvideoeditor/vss/src/M4READER_Amr.c
index 0859157..71f0e28 100755
--- a/libvideoeditor/vss/src/M4READER_Amr.c
+++ b/libvideoeditor/vss/src/M4READER_Amr.c
@@ -303,7 +303,7 @@
     pStreamHandler->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize;
     pStreamHandler->m_streamId                = streamDesc.streamID;
     pStreamHandler->m_duration                = streamDesc.duration;
-    pStreamHandler->m_pUserData               = (void*)streamDesc.timeScale; /*trick to change*/
+    pStreamHandler->m_pUserData               = (void*)(intptr_t)streamDesc.timeScale; /*trick to change*/
 
     if (streamDesc.duration > pC->m_maxDuration)
     {
@@ -704,7 +704,7 @@
 
     if (err == M4NO_ERROR)
     {
-        timeScale = (M4OSA_Float)(M4OSA_Int32)(pStreamHandler->m_pUserData)/1000;
+        timeScale = (M4OSA_Float)(M4OSA_Int32)(intptr_t)(pStreamHandler->m_pUserData)/1000;
         pAccessUnit->m_dataAddress = (M4OSA_MemAddr8)pAu->dataAddress;
         pAccessUnit->m_size = pAu->size;
         pAccessUnit->m_CTS  = (M4_MediaTime)pAu->CTS/*/timeScale*/;
diff --git a/libvideoeditor/vss/src/M4READER_Pcm.c b/libvideoeditor/vss/src/M4READER_Pcm.c
index 833930b..392367f 100755
--- a/libvideoeditor/vss/src/M4READER_Pcm.c
+++ b/libvideoeditor/vss/src/M4READER_Pcm.c
@@ -386,7 +386,7 @@
     pC->m_pAudioStream->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize;
     pC->m_pAudioStream->m_streamId                = streamDesc.streamID;
     pC->m_pAudioStream->m_pUserData               =
-        (void*)streamDesc.timeScale; /*trick to change*/
+        (void*)(intptr_t)streamDesc.timeScale; /*trick to change*/
     pC->m_pAudioStream->m_averageBitRate          = streamDesc.averageBitrate;
     pC->m_pAudioStream->m_maxAUSize               =
          pAudioStreamHandler->m_byteFrameLength*pAudioStreamHandler->m_byteSampleSize\
diff --git a/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c b/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c
index cc67e72..fb83952 100755
--- a/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c
+++ b/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <inttypes.h>
+
 #include "utils/Log.h"
 #include "M4OSA_Types.h"
 #include "M4OSA_Debug.h"
@@ -505,7 +507,7 @@
     }
 
     constraintSet3 = (pDSI[index+2] & 0x10);
-    ALOGV("getAVCProfileAndLevel profile_byte %d, level_byte: %d constrain3flag",
+    ALOGV("getAVCProfileAndLevel profile_byte %d, level_byte: %d constrain3flag: %d",
           pDSI[index+1], pDSI[index+3], constraintSet3);
 
     switch (pDSI[index+1]) {
@@ -586,7 +588,8 @@
         default:
             *pLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
     }
-    ALOGV("getAVCProfileAndLevel profile %ld level %ld", *pProfile, *pLevel);
+    ALOGV("getAVCProfileAndLevel profile %" PRId32 " level %" PRId32,
+          *pProfile, *pLevel);
     return M4NO_ERROR;
 }
 
@@ -606,7 +609,7 @@
         *pLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
         return M4ERR_PARAMETER;
     }
-    ALOGV("getH263ProfileAndLevel profile_byte %d, level_byte",
+    ALOGV("getH263ProfileAndLevel profile_byte %d, level_byte %d",
           pDSI[6], pDSI[5]);
     /* get the H263 level */
     switch (pDSI[5]) {
@@ -670,7 +673,8 @@
         default:
            *pProfile = M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
     }
-    ALOGV("getH263ProfileAndLevel profile %ld level %ld", *pProfile, *pLevel);
+    ALOGV("getH263ProfileAndLevel profile %" PRId32 " level %" PRId32,
+          *pProfile, *pLevel);
     return M4NO_ERROR;
 }
 
@@ -693,6 +697,7 @@
             break;
         }
     }
-    ALOGV("getMPEG4ProfileAndLevel profile %ld level %ld", *pProfile, *pLevel);
+    ALOGV("getMPEG4ProfileAndLevel profile %" PRId32 " level %" PRId32,
+          *pProfile, *pLevel);
     return M4NO_ERROR;
 }
diff --git a/libvideoeditor/vss/src/M4xVSS_internal.c b/libvideoeditor/vss/src/M4xVSS_internal.c
index 64a6f40..84959ec 100755
--- a/libvideoeditor/vss/src/M4xVSS_internal.c
+++ b/libvideoeditor/vss/src/M4xVSS_internal.c
@@ -4156,12 +4156,12 @@
 
     M4VIFI_ImagePlane boxPlane[3];
 
-    if(M4xVSS_kVideoEffectType_ZoomOut == (M4OSA_UInt32)pFunctionContext)
+    if((M4OSA_Void *)M4xVSS_kVideoEffectType_ZoomOut == pFunctionContext)
     {
         //ratio = 16 - (15 * pProgress->uiProgress)/1000;
         ratio = 16 - pProgress->uiProgress / 66 ;
     }
-    else if(M4xVSS_kVideoEffectType_ZoomIn == (M4OSA_UInt32)pFunctionContext)
+    else if((M4OSA_Void *)M4xVSS_kVideoEffectType_ZoomIn == pFunctionContext)
     {
         //ratio = 1 + (15 * pProgress->uiProgress)/1000;
         ratio = 1 + pProgress->uiProgress / 66 ;
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c b/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c
index f4cfa7c..5a7b28e 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c
@@ -22,6 +22,8 @@
 #undef M4OSA_TRACE_LEVEL
 #define M4OSA_TRACE_LEVEL 1
 
+#include <inttypes.h>
+
 #include "VideoEditorBuffer.h"
 #include "utils/Log.h"
 
@@ -55,7 +57,7 @@
     VIDEOEDITOR_BUFFER_Pool* pool;
     M4OSA_UInt32 index;
 
-    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = 0x%x nbBuffers = %d ",
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = %p nbBuffers = %" PRIu32,
         ppool, nbBuffers);
 
     pool = M4OSA_NULL;
@@ -131,7 +133,7 @@
     M4OSA_ERR err;
     M4OSA_UInt32  j = 0;
 
-    ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = 0x%x", ppool);
+    ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = %p", ppool);
 
     err = M4NO_ERROR;
 
@@ -200,7 +202,7 @@
     /* case where a buffer has been found */
     *pNXPBuffer = &(ppool->pNXPBuffer[ibuf]);
 
-    ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %d", ibuf);
+    ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %" PRIu32, ibuf);
 
     return(err);
 }
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp
index 4787680..ca7db68 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp
@@ -857,7 +857,7 @@
         ALOGV("VideoEditorVideoEncoder_processOutputBuffer : buffer is empty");
         goto cleanUp;
     }
-    VIDEOEDITOR_CHECK(0 == ((M4OSA_UInt32)buffer->data())%4, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(0 == (((intptr_t)buffer->data())%4), M4ERR_PARAMETER);
     VIDEOEDITOR_CHECK(buffer->meta_data().get(), M4ERR_PARAMETER);
     if ( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ){
         {   // Display the DSI
diff --git a/media/common_time/utils.cpp b/media/common_time/utils.cpp
index 6539171..91cf2fd 100644
--- a/media/common_time/utils.cpp
+++ b/media/common_time/utils.cpp
@@ -59,7 +59,7 @@
 }
 
 void deserializeSockaddr(const Parcel* p, struct sockaddr_storage* addr) {
-    memset(addr, 0, sizeof(addr));
+    memset(addr, 0, sizeof(*addr));
 
     addr->ss_family = p->readInt32();
     switch(addr->ss_family) {
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index a39d837..1663d47 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -16,7 +16,8 @@
 
 #define LOG_TAG "EffectDownmix"
 //#define LOG_NDEBUG 0
-#include <cutils/log.h>
+#include <log/log.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
@@ -99,7 +100,7 @@
 // strictly for testing, logs the indices of the channels for a given mask,
 // uses the same code as Downmix_foldGeneric()
 void Downmix_testIndexComputation(uint32_t mask) {
-    ALOGI("Testing index computation for 0x%x:", mask);
+    ALOGI("Testing index computation for 0x%" PRIx32 ":", mask);
     // check against unsupported channels
     if (mask & kUnsupported) {
         ALOGE("Unsupported channels (top or front left/right of center)");
@@ -220,7 +221,7 @@
 
     *pHandle = (effect_handle_t) module;
 
-    ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t));
+    ALOGV("DownmixLib_Create() %p , size %zu", module, sizeof(downmix_module_t));
 
     return 0;
 }
@@ -254,7 +255,7 @@
         ALOGV("DownmixLib_GetDescriptor() i=%d", i);
         if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
             memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
-            ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x",
+            ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %" PRIx32,
                  i, gDescriptors[i]->uuid.timeLow);
             return 0;
         }
@@ -328,7 +329,7 @@
           // bypass the optimized downmix routines for the common formats
           if (!Downmix_foldGeneric(
                   downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
-              ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask);
+              ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported", downmixInputChannelMask);
               return -EINVAL;
           }
           break;
@@ -352,7 +353,7 @@
         default:
             if (!Downmix_foldGeneric(
                     downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
-                ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask);
+                ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported", downmixInputChannelMask);
                 return -EINVAL;
             }
             break;
@@ -380,7 +381,7 @@
 
     pDownmixer = (downmix_object_t*) &pDwmModule->context;
 
-    ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize);
+    ALOGV("Downmix_Command command %" PRIu32 " cmdSize %" PRIu32, cmdCode, cmdSize);
 
     switch (cmdCode) {
     case EFFECT_CMD_INIT:
@@ -404,7 +405,7 @@
         break;
 
     case EFFECT_CMD_GET_PARAM:
-        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",
+        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %" PRIu32 ", pReplyData: %p",
                 pCmdData, *replySize, pReplyData);
         if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
                 pReplyData == NULL ||
@@ -413,7 +414,7 @@
         }
         effect_param_t *rep = (effect_param_t *) pReplyData;
         memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
-        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",
+        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %" PRId32 ", replySize %" PRIu32,
                 *(int32_t *)rep->data, rep->vsize);
         rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize,
                 rep->data + sizeof(int32_t));
@@ -421,8 +422,8 @@
         break;
 
     case EFFECT_CMD_SET_PARAM:
-        ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, " \
-                "pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
+        ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %" PRIu32
+                ", pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
         if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
                 || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
             return -EINVAL;
@@ -471,7 +472,7 @@
             return -EINVAL;
         }
         // FIXME change type if playing on headset vs speaker
-        ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
+        ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08" PRIx32, *(uint32_t *)pCmdData);
         break;
 
     case EFFECT_CMD_SET_VOLUME: {
@@ -491,7 +492,7 @@
         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
             return -EINVAL;
         }
-        ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+        ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %" PRIu32, *(uint32_t *)pCmdData);
         break;
 
     case EFFECT_CMD_SET_CONFIG_REVERSE:
@@ -500,7 +501,7 @@
         break;
 
     default:
-        ALOGW("Downmix_Command invalid command %d",cmdCode);
+        ALOGW("Downmix_Command invalid command %" PRIu32, cmdCode);
         return -EINVAL;
     }
 
@@ -702,28 +703,28 @@
 int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue) {
 
     int16_t value16;
-    ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
+    ALOGV("Downmix_setParameter, context %p, param %" PRId32 ", value16 %" PRId16 ", value32 %" PRId32,
             pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue);
 
     switch (param) {
 
       case DOWNMIX_PARAM_TYPE:
         if (size != sizeof(downmix_type_t)) {
-            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %u, should be %zu",
+            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %" PRIu32 ", should be %zu",
                     size, sizeof(downmix_type_t));
             return -EINVAL;
         }
         value16 = *(int16_t *)pValue;
-        ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16);
+        ALOGV("set DOWNMIX_PARAM_TYPE, type %" PRId16, value16);
         if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 <= DOWNMIX_TYPE_LAST))) {
-            ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16);
+            ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %" PRId16, value16);
             return -EINVAL;
         } else {
             pDownmixer->type = (downmix_type_t) value16;
         break;
 
       default:
-        ALOGE("Downmix_setParameter unknown parameter %d", param);
+        ALOGE("Downmix_setParameter unknown parameter %" PRId32, param);
         return -EINVAL;
     }
 }
@@ -762,17 +763,17 @@
 
     case DOWNMIX_PARAM_TYPE:
       if (*pSize < sizeof(int16_t)) {
-          ALOGE("Downmix_getParameter invalid parameter size %zu for DOWNMIX_PARAM_TYPE", *pSize);
+          ALOGE("Downmix_getParameter invalid parameter size %" PRIu32 " for DOWNMIX_PARAM_TYPE", *pSize);
           return -EINVAL;
       }
       pValue16 = (int16_t *)pValue;
       *pValue16 = (int16_t) pDownmixer->type;
       *pSize = sizeof(int16_t);
-      ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16);
+      ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %" PRId16, *pValue16);
       break;
 
     default:
-      ALOGE("Downmix_getParameter unknown parameter %d", param);
+      ALOGE("Downmix_getParameter unknown parameter %" PRId16, param);
       return -EINVAL;
     }
 
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 5bdaa03..47cab62 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -16,8 +16,9 @@
 
 #define LOG_TAG "EffectVisualizer"
 //#define LOG_NDEBUG 0
-#include <cutils/log.h>
+#include <log/log.h>
 #include <assert.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <new>
@@ -226,8 +227,8 @@
 //
 
 int VisualizerLib_Create(const effect_uuid_t *uuid,
-                         int32_t sessionId,
-                         int32_t ioId,
+                         int32_t /*sessionId*/,
+                         int32_t /*ioId*/,
                          effect_handle_t *pHandle) {
     int ret;
     int i;
@@ -418,7 +419,7 @@
         return -EINVAL;
     }
 
-//    ALOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize);
+//    ALOGV("Visualizer_command command %" PRIu32 " cmdSize %" PRIu32, cmdCode, cmdSize);
 
     switch (cmdCode) {
     case EFFECT_CMD_INIT:
@@ -484,19 +485,19 @@
         }
         switch (*(uint32_t *)p->data) {
         case VISUALIZER_PARAM_CAPTURE_SIZE:
-            ALOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+            ALOGV("get mCaptureSize = %" PRIu32, pContext->mCaptureSize);
             *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
             p->vsize = sizeof(uint32_t);
             *replySize += sizeof(uint32_t);
             break;
         case VISUALIZER_PARAM_SCALING_MODE:
-            ALOGV("get mScalingMode = %d", pContext->mScalingMode);
+            ALOGV("get mScalingMode = %" PRIu32, pContext->mScalingMode);
             *((uint32_t *)p->data + 1) = pContext->mScalingMode;
             p->vsize = sizeof(uint32_t);
             *replySize += sizeof(uint32_t);
             break;
         case VISUALIZER_PARAM_MEASUREMENT_MODE:
-            ALOGV("get mMeasurementMode = %d", pContext->mMeasurementMode);
+            ALOGV("get mMeasurementMode = %" PRIu32, pContext->mMeasurementMode);
             *((uint32_t *)p->data + 1) = pContext->mMeasurementMode;
             p->vsize = sizeof(uint32_t);
             *replySize += sizeof(uint32_t);
@@ -520,19 +521,19 @@
         switch (*(uint32_t *)p->data) {
         case VISUALIZER_PARAM_CAPTURE_SIZE:
             pContext->mCaptureSize = *((uint32_t *)p->data + 1);
-            ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+            ALOGV("set mCaptureSize = %" PRIu32, pContext->mCaptureSize);
             break;
         case VISUALIZER_PARAM_SCALING_MODE:
             pContext->mScalingMode = *((uint32_t *)p->data + 1);
-            ALOGV("set mScalingMode = %d", pContext->mScalingMode);
+            ALOGV("set mScalingMode = %" PRIu32, pContext->mScalingMode);
             break;
         case VISUALIZER_PARAM_LATENCY:
             pContext->mLatency = *((uint32_t *)p->data + 1);
-            ALOGV("set mLatency = %d", pContext->mLatency);
+            ALOGV("set mLatency = %" PRIu32, pContext->mLatency);
             break;
         case VISUALIZER_PARAM_MEASUREMENT_MODE:
             pContext->mMeasurementMode = *((uint32_t *)p->data + 1);
-            ALOGV("set mMeasurementMode = %d", pContext->mMeasurementMode);
+            ALOGV("set mMeasurementMode = %" PRIu32, pContext->mMeasurementMode);
             break;
         default:
             *(int32_t *)pReplyData = -EINVAL;
@@ -545,9 +546,9 @@
 
 
     case VISUALIZER_CMD_CAPTURE: {
-        int32_t captureSize = pContext->mCaptureSize;
+        uint32_t captureSize = pContext->mCaptureSize;
         if (pReplyData == NULL || *replySize != captureSize) {
-            ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %d captureSize %d",
+            ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %" PRIu32 " captureSize %" PRIu32,
                     *replySize, captureSize);
             return -EINVAL;
         }
@@ -573,7 +574,7 @@
                 int32_t capturePoint = pContext->mCaptureIdx - captureSize - deltaSmpl;
 
                 if (capturePoint < 0) {
-                    int32_t size = -capturePoint;
+                    uint32_t size = -capturePoint;
                     if (size > captureSize) {
                         size = captureSize;
                     }
@@ -604,7 +605,7 @@
         // measurements aren't relevant anymore and shouldn't bias the new one)
         const int32_t delayMs = Visualizer_getDeltaTimeMsFromUpdatedTime(pContext);
         if (delayMs > DISCARD_MEASUREMENTS_TIME_MS) {
-            ALOGV("Discarding measurements, last measurement is %dms old", delayMs);
+            ALOGV("Discarding measurements, last measurement is %" PRId32 "ms old", delayMs);
             for (uint32_t i=0 ; i<pContext->mMeasurementWindowSizeInBuffers ; i++) {
                 pContext->mPastMeasurements[i].mIsValid = false;
                 pContext->mPastMeasurements[i].mPeakU16 = 0;
@@ -638,14 +639,14 @@
         } else {
             pIntReplyData[MEASUREMENT_IDX_PEAK] = (int32_t) (2000 * log10(peakU16 / 32767.0f));
         }
-        ALOGV("VISUALIZER_CMD_MEASURE peak=%d (%dmB), rms=%.1f (%dmB)",
+        ALOGV("VISUALIZER_CMD_MEASURE peak=%" PRIu16 " (%" PRId32 "mB), rms=%.1f (%" PRId32 "mB)",
                 peakU16, pIntReplyData[MEASUREMENT_IDX_PEAK],
                 rms, pIntReplyData[MEASUREMENT_IDX_RMS]);
         }
         break;
 
     default:
-        ALOGW("Visualizer_command invalid command %d",cmdCode);
+        ALOGW("Visualizer_command invalid command %" PRIu32, cmdCode);
         return -EINVAL;
     }
 
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 3f592ed..a6fb3d8 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -265,7 +265,7 @@
 
         mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6);
 
-        for (int i = 0; i< seekFrame - index * 50; i++) {
+        for (size_t i = 0; i< seekFrame - index * 50; i++) {
             status_t err;
             if ((err = getFrameSizeByOffset(mDataSource, mOffset,
                             mIsWide, &size)) != OK) {
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 60cdf66..15ba967 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -135,7 +135,7 @@
     }
 
     bool videoSizeSupported = false;
-    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
+    for (size_t i = 0; i < supportedSizes.size(); ++i) {
         int32_t pictureWidth = supportedSizes[i].width;
         int32_t pictureHeight = supportedSizes[i].height;
 
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 72ea32d..61cf0ad 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -648,7 +648,7 @@
     ssize_t lowwaterMarkKb, highwaterMarkKb;
     int keepAliveSecs;
 
-    if (sscanf(s, "%d/%d/%d",
+    if (sscanf(s, "%zd/%zd/%d",
                &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) {
         ALOGE("Failed to parse cache parameters from '%s'.", s);
         return;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1cfe6c0..a879656 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "OMXCodec"
 #include <utils/Log.h>
@@ -4251,9 +4253,9 @@
     CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
           || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
 
-    printf("  nBufferCountActual = %ld\n", def.nBufferCountActual);
-    printf("  nBufferCountMin = %ld\n", def.nBufferCountMin);
-    printf("  nBufferSize = %ld\n", def.nBufferSize);
+    printf("  nBufferCountActual = %" PRIu32 "\n", def.nBufferCountActual);
+    printf("  nBufferCountMin = %" PRIu32 "\n", def.nBufferCountMin);
+    printf("  nBufferSize = %" PRIu32 "\n", def.nBufferSize);
 
     switch (def.eDomain) {
         case OMX_PortDomainImage:
@@ -4262,9 +4264,9 @@
 
             printf("\n");
             printf("  // Image\n");
-            printf("  nFrameWidth = %ld\n", imageDef->nFrameWidth);
-            printf("  nFrameHeight = %ld\n", imageDef->nFrameHeight);
-            printf("  nStride = %ld\n", imageDef->nStride);
+            printf("  nFrameWidth = %" PRIu32 "\n", imageDef->nFrameWidth);
+            printf("  nFrameHeight = %" PRIu32 "\n", imageDef->nFrameHeight);
+            printf("  nStride = %" PRIu32 "\n", imageDef->nStride);
 
             printf("  eCompressionFormat = %s\n",
                    imageCompressionFormatString(imageDef->eCompressionFormat));
@@ -4281,9 +4283,9 @@
 
             printf("\n");
             printf("  // Video\n");
-            printf("  nFrameWidth = %ld\n", videoDef->nFrameWidth);
-            printf("  nFrameHeight = %ld\n", videoDef->nFrameHeight);
-            printf("  nStride = %ld\n", videoDef->nStride);
+            printf("  nFrameWidth = %" PRIu32 "\n", videoDef->nFrameWidth);
+            printf("  nFrameHeight = %" PRIu32 "\n", videoDef->nFrameHeight);
+            printf("  nStride = %" PRIu32 "\n", videoDef->nStride);
 
             printf("  eCompressionFormat = %s\n",
                    videoCompressionFormatString(videoDef->eCompressionFormat));
@@ -4312,10 +4314,10 @@
                         mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
                 CHECK_EQ(err, (status_t)OK);
 
-                printf("  nSamplingRate = %ld\n", params.nSamplingRate);
-                printf("  nChannels = %ld\n", params.nChannels);
+                printf("  nSamplingRate = %" PRIu32 "\n", params.nSamplingRate);
+                printf("  nChannels = %" PRIu32 "\n", params.nChannels);
                 printf("  bInterleaved = %d\n", params.bInterleaved);
-                printf("  nBitPerSample = %ld\n", params.nBitPerSample);
+                printf("  nBitPerSample = %" PRIu32 "\n", params.nBitPerSample);
 
                 printf("  eNumData = %s\n",
                        params.eNumData == OMX_NumericalDataSigned
@@ -4331,7 +4333,7 @@
                         mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
                 CHECK_EQ(err, (status_t)OK);
 
-                printf("  nChannels = %ld\n", amr.nChannels);
+                printf("  nChannels = %" PRIu32 "\n", amr.nChannels);
                 printf("  eAMRBandMode = %s\n",
                         amrBandModeString(amr.eAMRBandMode));
                 printf("  eAMRFrameFormat = %s\n",
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h
index 8b295a6..912cb0d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h
@@ -32,6 +32,7 @@
 #define _OMXTYPES_H_
 
 #include <limits.h> 
+#include <stdint.h>
 
 #define OMX_IN
 #define OMX_OUT
@@ -75,64 +76,22 @@
 
  
 /* OMX_U8 */
-#if UCHAR_MAX == 0xff
-typedef unsigned char OMX_U8;
-#elif USHRT_MAX == 0xff 
-typedef unsigned short int OMX_U8; 
-#else
-#error OMX_U8 undefined
-#endif 
-
+typedef uint8_t OMX_U8;
  
 /* OMX_S8 */
-#if SCHAR_MAX == 0x7f 
-typedef signed char OMX_S8;
-#elif SHRT_MAX == 0x7f 
-typedef signed short int OMX_S8; 
-#else
-#error OMX_S8 undefined
-#endif
- 
+typedef int8_t OMX_S8;
  
 /* OMX_U16 */
-#if USHRT_MAX == 0xffff
-typedef unsigned short int OMX_U16;
-#elif UINT_MAX == 0xffff
-typedef unsigned int OMX_U16; 
-#else
-#error OMX_U16 undefined
-#endif
-
+typedef uint16_t OMX_U16;
 
 /* OMX_S16 */
-#if SHRT_MAX == 0x7fff 
-typedef signed short int OMX_S16;
-#elif INT_MAX == 0x7fff 
-typedef signed int OMX_S16; 
-#else
-#error OMX_S16 undefined
-#endif
-
+typedef int16_t OMX_S16;
 
 /* OMX_U32 */
-#if UINT_MAX == 0xffffffff
-typedef unsigned int OMX_U32;
-#elif LONG_MAX == 0xffffffff
-typedef unsigned long int OMX_U32; 
-#else
-#error OMX_U32 undefined
-#endif
-
+typedef uint32_t OMX_U32;
 
 /* OMX_S32 */
-#if INT_MAX == 0x7fffffff
-typedef signed int OMX_S32;
-#elif LONG_MAX == 0x7fffffff
-typedef long signed int OMX_S32; 
-#else
-#error OMX_S32 undefined
-#endif
-
+typedef int32_t OMX_S32;
 
 /* OMX_U64 & OMX_S64 */
 #if defined( _WIN32 ) || defined ( _WIN64 )
@@ -143,15 +102,14 @@
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFi64)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFi64)
 #else
-    typedef long long OMX_S64; /** Signed 64-bit integer */
-    typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+    typedef int64_t OMX_S64; /** Signed 64-bit integer */
+    typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */
     #define OMX_MIN_S64			(0x8000000000000000LL)
     #define OMX_MIN_U64			(0x0000000000000000LL)
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFLL)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFLL)
 #endif
 
-
 /* OMX_SC8 */
 typedef struct
 {
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
index 8b295a6..912cb0d 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
@@ -32,6 +32,7 @@
 #define _OMXTYPES_H_
 
 #include <limits.h> 
+#include <stdint.h>
 
 #define OMX_IN
 #define OMX_OUT
@@ -75,64 +76,22 @@
 
  
 /* OMX_U8 */
-#if UCHAR_MAX == 0xff
-typedef unsigned char OMX_U8;
-#elif USHRT_MAX == 0xff 
-typedef unsigned short int OMX_U8; 
-#else
-#error OMX_U8 undefined
-#endif 
-
+typedef uint8_t OMX_U8;
  
 /* OMX_S8 */
-#if SCHAR_MAX == 0x7f 
-typedef signed char OMX_S8;
-#elif SHRT_MAX == 0x7f 
-typedef signed short int OMX_S8; 
-#else
-#error OMX_S8 undefined
-#endif
- 
+typedef int8_t OMX_S8;
  
 /* OMX_U16 */
-#if USHRT_MAX == 0xffff
-typedef unsigned short int OMX_U16;
-#elif UINT_MAX == 0xffff
-typedef unsigned int OMX_U16; 
-#else
-#error OMX_U16 undefined
-#endif
-
+typedef uint16_t OMX_U16;
 
 /* OMX_S16 */
-#if SHRT_MAX == 0x7fff 
-typedef signed short int OMX_S16;
-#elif INT_MAX == 0x7fff 
-typedef signed int OMX_S16; 
-#else
-#error OMX_S16 undefined
-#endif
-
+typedef int16_t OMX_S16;
 
 /* OMX_U32 */
-#if UINT_MAX == 0xffffffff
-typedef unsigned int OMX_U32;
-#elif LONG_MAX == 0xffffffff
-typedef unsigned long int OMX_U32; 
-#else
-#error OMX_U32 undefined
-#endif
-
+typedef uint32_t OMX_U32;
 
 /* OMX_S32 */
-#if INT_MAX == 0x7fffffff
-typedef signed int OMX_S32;
-#elif LONG_MAX == 0x7fffffff
-typedef long signed int OMX_S32; 
-#else
-#error OMX_S32 undefined
-#endif
-
+typedef int32_t OMX_S32;
 
 /* OMX_U64 & OMX_S64 */
 #if defined( _WIN32 ) || defined ( _WIN64 )
@@ -143,15 +102,14 @@
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFi64)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFi64)
 #else
-    typedef long long OMX_S64; /** Signed 64-bit integer */
-    typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+    typedef int64_t OMX_S64; /** Signed 64-bit integer */
+    typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */
     #define OMX_MIN_S64			(0x8000000000000000LL)
     #define OMX_MIN_U64			(0x0000000000000000LL)
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFLL)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFLL)
 #endif
 
-
 /* OMX_SC8 */
 typedef struct
 {
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h
index 8b295a6..912cb0d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h
@@ -32,6 +32,7 @@
 #define _OMXTYPES_H_
 
 #include <limits.h> 
+#include <stdint.h>
 
 #define OMX_IN
 #define OMX_OUT
@@ -75,64 +76,22 @@
 
  
 /* OMX_U8 */
-#if UCHAR_MAX == 0xff
-typedef unsigned char OMX_U8;
-#elif USHRT_MAX == 0xff 
-typedef unsigned short int OMX_U8; 
-#else
-#error OMX_U8 undefined
-#endif 
-
+typedef uint8_t OMX_U8;
  
 /* OMX_S8 */
-#if SCHAR_MAX == 0x7f 
-typedef signed char OMX_S8;
-#elif SHRT_MAX == 0x7f 
-typedef signed short int OMX_S8; 
-#else
-#error OMX_S8 undefined
-#endif
- 
+typedef int8_t OMX_S8;
  
 /* OMX_U16 */
-#if USHRT_MAX == 0xffff
-typedef unsigned short int OMX_U16;
-#elif UINT_MAX == 0xffff
-typedef unsigned int OMX_U16; 
-#else
-#error OMX_U16 undefined
-#endif
-
+typedef uint16_t OMX_U16;
 
 /* OMX_S16 */
-#if SHRT_MAX == 0x7fff 
-typedef signed short int OMX_S16;
-#elif INT_MAX == 0x7fff 
-typedef signed int OMX_S16; 
-#else
-#error OMX_S16 undefined
-#endif
-
+typedef int16_t OMX_S16;
 
 /* OMX_U32 */
-#if UINT_MAX == 0xffffffff
-typedef unsigned int OMX_U32;
-#elif LONG_MAX == 0xffffffff
-typedef unsigned long int OMX_U32; 
-#else
-#error OMX_U32 undefined
-#endif
-
+typedef uint32_t OMX_U32;
 
 /* OMX_S32 */
-#if INT_MAX == 0x7fffffff
-typedef signed int OMX_S32;
-#elif LONG_MAX == 0x7fffffff
-typedef long signed int OMX_S32; 
-#else
-#error OMX_S32 undefined
-#endif
-
+typedef int32_t OMX_S32;
 
 /* OMX_U64 & OMX_S64 */
 #if defined( _WIN32 ) || defined ( _WIN64 )
@@ -143,15 +102,14 @@
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFi64)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFi64)
 #else
-    typedef long long OMX_S64; /** Signed 64-bit integer */
-    typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+    typedef int64_t OMX_S64; /** Signed 64-bit integer */
+    typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */
     #define OMX_MIN_S64			(0x8000000000000000LL)
     #define OMX_MIN_U64			(0x0000000000000000LL)
     #define OMX_MAX_S64			(0x7FFFFFFFFFFFFFFFLL)
     #define OMX_MAX_U64			(0xFFFFFFFFFFFFFFFFLL)
 #endif
 
-
 /* OMX_SC8 */
 typedef struct
 {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 0b4a616..16f6c58 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #define LOG_TAG "GraphicBufferSource"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
@@ -207,7 +209,7 @@
         return;
     }
 
-    ALOGV("addCodecBuffer h=%p size=%lu p=%p",
+    ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
             header, header->nAllocLen, header->pBuffer);
     CodecBuffer codecBuffer;
     codecBuffer.mHeader = header;
@@ -228,7 +230,7 @@
         return;
     }
 
-    ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p",
+    ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
             header, header->nAllocLen, header->nFilledLen,
             header->pBuffer);
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index a608479..74076c6 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "OMX"
 #include <utils/Log.h>
@@ -425,7 +427,7 @@
         OMX_IN OMX_U32 nData1,
         OMX_IN OMX_U32 nData2,
         OMX_IN OMX_PTR /* pEventData */) {
-    ALOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2);
+    ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
 
     // Forward to OMXNodeInstance.
     findInstance(node)->onEvent(eEvent, nData1, nData2);
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 08a3d42..eb9fcf7 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftVideoDecoderOMXComponent"
 #include <utils/Log.h>
@@ -177,7 +179,7 @@
                   (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
 
             if (profileLevel->nPortIndex != kInputPortIndex) {
-                ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
+                ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex);
                 return OMX_ErrorUnsupportedIndex;
             }
 
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index d672dff..d6d5dd5 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -195,7 +195,7 @@
 
 MtpDevice::~MtpDevice() {
     close();
-    for (int i = 0; i < mDeviceProperties.size(); i++)
+    for (size_t i = 0; i < mDeviceProperties.size(); i++)
         delete mDeviceProperties[i];
     usb_request_free(mRequestIn1);
     usb_request_free(mRequestIn2);
@@ -253,7 +253,7 @@
             ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
             MtpObjectPropertyList* props = getObjectPropsSupported(format);
             if (props) {
-                for (int j = 0; j < props->size(); j++) {
+                for (size_t j = 0; j < props->size(); j++) {
                     MtpObjectProperty prop = (*props)[j];
                     MtpProperty* property = getObjectPropDesc(prop, format);
                     if (property) {
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index dadfb54..157f2ce 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -20,6 +20,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <errno.h>
 #include <sys/stat.h>
 #include <dirent.h>
@@ -125,7 +126,7 @@
 void MtpServer::removeStorage(MtpStorage* storage) {
     Mutex::Autolock autoLock(mMutex);
 
-    for (int i = 0; i < mStorages.size(); i++) {
+    for (size_t i = 0; i < mStorages.size(); i++) {
         if (mStorages[i] == storage) {
             mStorages.removeAt(i);
             sendStoreRemoved(storage->getStorageID());
@@ -137,7 +138,7 @@
 MtpStorage* MtpServer::getStorage(MtpStorageID id) {
     if (id == 0)
         return mStorages[0];
-    for (int i = 0; i < mStorages.size(); i++) {
+    for (size_t i = 0; i < mStorages.size(); i++) {
         MtpStorage* storage = mStorages[i];
         if (storage->getStorageID() == id)
             return storage;
@@ -1116,7 +1117,7 @@
     }
 
     const char* filePath = (const char *)edit->mPath;
-    ALOGV("receiving partial %s %lld %lld\n", filePath, offset, length);
+    ALOGV("receiving partial %s %lld %" PRIu32 "\n", filePath, offset, length);
 
     // read the header, and possibly some data
     int ret = mData.read(mFD);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bb8c15e..755d480 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -607,7 +607,7 @@
         }
 
         // Look for sync events awaiting for a session to be used.
-        for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) {
+        for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
             if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
                 if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
                     if (lStatus == NO_ERROR) {
@@ -912,7 +912,7 @@
 
     AutoMutex lock(mLock);
     mStreamTypes[stream].mute = muted;
-    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++)
         mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
 
     return NO_ERROR;
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index ca98f16..562c4ea 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -234,7 +234,16 @@
     case DYN_MED_QUALITY:
     case DYN_HIGH_QUALITY:
         ALOGV("Create dynamic Resampler = %d", quality);
-        resampler = new AudioResamplerDyn(bitDepth, inChannelCount, sampleRate, quality);
+        if (bitDepth == 32) { /* bitDepth == 32 signals float precision */
+            resampler = new AudioResamplerDyn<float, float, float>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        } else if (quality == DYN_HIGH_QUALITY) {
+            resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        } else {
+            resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        }
         break;
     }
 
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index 7e4ca0c..3abe8fd 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -25,6 +25,7 @@
 
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
+#include <utils/Debug.h>
 #include <utils/Log.h>
 
 #include "AudioResamplerFirOps.h" // USE_NEON and USE_INLINE_ASSEMBLY defined here
@@ -38,9 +39,9 @@
 namespace android {
 
 // generate a unique resample type compile-time constant (constexpr)
-#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE, COEFTYPE) \
-    ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 | (COEFTYPE)<<2 \
-    | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<3)
+#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE) \
+    ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 \
+    | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<2)
 
 /*
  * InBuffer is a type agnostic input buffer.
@@ -58,42 +59,46 @@
  * r = extra space for implementing the ring buffer
  */
 
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::InBuffer()
-    : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateSize(0) {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::InBuffer()
+    : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateCount(0)
+{
 }
 
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::~InBuffer() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::~InBuffer()
+{
     init();
 }
 
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::init()
+{
     free(mState);
     mState = NULL;
     mImpulse = NULL;
     mRingFull = NULL;
-    mStateSize = 0;
+    mStateCount = 0;
 }
 
 // resizes the state buffer to accommodate the appropriate filter length
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::resize(int CHANNELS, int halfNumCoefs) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::resize(int CHANNELS, int halfNumCoefs)
+{
     // calculate desired state size
-    int stateSize = halfNumCoefs * CHANNELS * 2
-            * kStateSizeMultipleOfFilterLength;
+    int stateCount = halfNumCoefs * CHANNELS * 2 * kStateSizeMultipleOfFilterLength;
 
     // check if buffer needs resizing
     if (mState
-            && stateSize == mStateSize
-            && mRingFull-mState == mStateSize-halfNumCoefs*CHANNELS) {
+            && stateCount == mStateCount
+            && mRingFull-mState == mStateCount-halfNumCoefs*CHANNELS) {
         return;
     }
 
     // create new buffer
-    TI* state = (int16_t*)memalign(32, stateSize*sizeof(*state));
-    memset(state, 0, stateSize*sizeof(*state));
+    TI* state;
+    (void)posix_memalign(reinterpret_cast<void**>(&state), 32, stateCount*sizeof(*state));
+    memset(state, 0, stateCount*sizeof(*state));
 
     // attempt to preserve state
     if (mState) {
@@ -105,8 +110,8 @@
             dst += mState-srcLo;
             srcLo = mState;
         }
-        if (srcHi > mState + mStateSize) {
-            srcHi = mState + mStateSize;
+        if (srcHi > mState + mStateCount) {
+            srcHi = mState + mStateCount;
         }
         memcpy(dst, srcLo, (srcHi - srcLo) * sizeof(*srcLo));
         free(mState);
@@ -114,27 +119,29 @@
 
     // set class member vars
     mState = state;
-    mStateSize = stateSize;
-    mImpulse = mState + halfNumCoefs*CHANNELS; // actually one sample greater than needed
-    mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS;
+    mStateCount = stateCount;
+    mImpulse = state + halfNumCoefs*CHANNELS; // actually one sample greater than needed
+    mRingFull = state + mStateCount - halfNumCoefs*CHANNELS;
 }
 
 // copy in the input data into the head (impulse+halfNumCoefs) of the buffer.
-template<typename TI>
+template<typename TC, typename TI, typename TO>
 template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAgain(TI*& impulse, const int halfNumCoefs,
-        const TI* const in, const size_t inputIndex) {
-    int16_t* head = impulse + halfNumCoefs*CHANNELS;
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAgain(TI*& impulse, const int halfNumCoefs,
+        const TI* const in, const size_t inputIndex)
+{
+    TI* head = impulse + halfNumCoefs*CHANNELS;
     for (size_t i=0 ; i<CHANNELS ; i++) {
         head[i] = in[inputIndex*CHANNELS + i];
     }
 }
 
 // advance the impulse pointer, and load in data into the head (impulse+halfNumCoefs)
-template<typename TI>
+template<typename TC, typename TI, typename TO>
 template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAdvance(TI*& impulse, const int halfNumCoefs,
-        const TI* const in, const size_t inputIndex) {
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAdvance(TI*& impulse, const int halfNumCoefs,
+        const TI* const in, const size_t inputIndex)
+{
     impulse += CHANNELS;
 
     if (CC_UNLIKELY(impulse >= mRingFull)) {
@@ -145,7 +152,8 @@
     readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
 }
 
-void AudioResamplerDyn::Constants::set(
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::Constants::set(
         int L, int halfNumCoefs, int inSampleRate, int outSampleRate)
 {
     int bits = 0;
@@ -158,10 +166,11 @@
     mHalfNumCoefs = halfNumCoefs;
 }
 
-AudioResamplerDyn::AudioResamplerDyn(int bitDepth,
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::AudioResamplerDyn(int bitDepth,
         int inChannelCount, int32_t sampleRate, src_quality quality)
     : AudioResampler(bitDepth, inChannelCount, sampleRate, quality),
-    mResampleType(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
+      mResampleFunc(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
     mCoefBuffer(NULL)
 {
     mVolumeSimd[0] = mVolumeSimd[1] = 0;
@@ -172,33 +181,48 @@
     mConstants.set(128, 8, mSampleRate, mSampleRate); // TODO: set better
 }
 
-AudioResamplerDyn::~AudioResamplerDyn() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::~AudioResamplerDyn()
+{
     free(mCoefBuffer);
 }
 
-void AudioResamplerDyn::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::init()
+{
     mFilterSampleRate = 0; // always trigger new filter generation
     mInBuffer.init();
 }
 
-void AudioResamplerDyn::setVolume(int16_t left, int16_t right) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setVolume(int16_t left, int16_t right)
+{
     AudioResampler::setVolume(left, right);
-    mVolumeSimd[0] = static_cast<int32_t>(left)<<16;
-    mVolumeSimd[1] = static_cast<int32_t>(right)<<16;
+    // volume is applied on the output type.
+    if (is_same<TO, float>::value || is_same<TO, double>::value) {
+        const TO scale = 1. / (1UL << 12);
+        mVolumeSimd[0] = static_cast<TO>(left) * scale;
+        mVolumeSimd[1] = static_cast<TO>(right) * scale;
+    } else {
+        mVolumeSimd[0] = static_cast<int32_t>(left) << 16;
+        mVolumeSimd[1] = static_cast<int32_t>(right) << 16;
+    }
 }
 
-template <typename T> T max(T a, T b) {return a > b ? a : b;}
+template<typename T> T max(T a, T b) {return a > b ? a : b;}
 
-template <typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
+template<typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
 
-template<typename T>
-void AudioResamplerDyn::createKaiserFir(Constants &c, double stopBandAtten,
-        int inSampleRate, int outSampleRate, double tbwCheat) {
-    T* buf = reinterpret_cast<T*>(memalign(32, (c.mL+1)*c.mHalfNumCoefs*sizeof(T)));
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::createKaiserFir(Constants &c,
+        double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat)
+{
+    TC* buf;
     static const double atten = 0.9998;   // to avoid ripple overflow
     double fcr;
     double tbw = firKaiserTbw(c.mHalfNumCoefs, stopBandAtten);
 
+    (void)posix_memalign(reinterpret_cast<void**>(&buf), 32, (c.mL+1)*c.mHalfNumCoefs*sizeof(TC));
     if (inSampleRate < outSampleRate) { // upsample
         fcr = max(0.5*tbwCheat - tbw/2, tbw/2);
     } else { // downsample
@@ -206,7 +230,7 @@
     }
     // create and set filter
     firKaiserGen(buf, c.mL, c.mHalfNumCoefs, stopBandAtten, fcr, atten);
-    c.setBuf(buf);
+    c.mFirCoefs = buf;
     if (mCoefBuffer) {
         free(mCoefBuffer);
     }
@@ -228,7 +252,8 @@
 }
 
 // recursive gcd. Using objdump, it appears the tail recursion is converted to a while loop.
-static int gcd(int n, int m) {
+static int gcd(int n, int m)
+{
     if (m == 0) {
         return n;
     }
@@ -236,7 +261,8 @@
 }
 
 static bool isClose(int32_t newSampleRate, int32_t prevSampleRate,
-        int32_t filterSampleRate, int32_t outSampleRate) {
+        int32_t filterSampleRate, int32_t outSampleRate)
+{
 
     // different upsampling ratios do not need a filter change.
     if (filterSampleRate != 0
@@ -253,7 +279,9 @@
     return pdiff < prevSampleRate>>4 && adiff < filterSampleRate>>3;
 }
 
-void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate)
+{
     if (mInSampleRate == inSampleRate) {
         return;
     }
@@ -357,13 +385,8 @@
 
         // create the filter
         mConstants.set(phases, halfLength, inSampleRate, mSampleRate);
-        if (useS32) {
-            createKaiserFir<int32_t>(mConstants, stopBandAtten,
-                    inSampleRate, mSampleRate, tbwCheat);
-        } else {
-            createKaiserFir<int16_t>(mConstants, stopBandAtten,
-                    inSampleRate, mSampleRate, tbwCheat);
-        }
+        createKaiserFir(mConstants, stopBandAtten,
+                inSampleRate, mSampleRate, tbwCheat);
     } // End Kaiser filter
 
     // update phase and state based on the new filter.
@@ -385,7 +408,7 @@
         mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase
     }
 
-    mResampleType = RESAMPLETYPE(mChannelCount, locked, stride, !!useS32);
+    setResampler(RESAMPLETYPE(mChannelCount, locked, stride));
 #ifdef DEBUG_RESAMPLER
     printf("channels:%d  %s  stride:%d  %s  coef:%d  shift:%d\n",
             mChannelCount, locked ? "locked" : "interpolated",
@@ -393,78 +416,45 @@
 #endif
 }
 
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount,
             AudioBufferProvider* provider)
 {
-    // TODO:
-    // 24 cases - this perhaps can be reduced later, as testing might take too long
-    switch (mResampleType) {
+    (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider);
+}
 
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setResampler(unsigned resampleType)
+{
     // stride 16 (falls back to stride 2 for machines that do not support NEON)
-    case RESAMPLETYPE(1, true, 16, 0):
-        return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 16, 0):
-        return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 16, 0):
-        return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 16, 0):
-        return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 16, 1):
-        return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 16, 1):
-        return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 16, 1):
-        return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 16, 1):
-        return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#if 0
-    // TODO: Remove these?
-    // stride 8
-    case RESAMPLETYPE(1, true, 8, 0):
-        return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 8, 0):
-        return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 8, 0):
-        return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 8, 0):
-        return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 8, 1):
-        return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 8, 1):
-        return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 8, 1):
-        return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 8, 1):
-        return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    // stride 2 (can handle any filter length)
-    case RESAMPLETYPE(1, true, 2, 0):
-        return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 2, 0):
-        return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 2, 0):
-        return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 2, 0):
-        return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 2, 1):
-        return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 2, 1):
-        return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 2, 1):
-        return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 2, 1):
-        return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#endif
+    switch (resampleType) {
+    case RESAMPLETYPE(1, true, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
+        return;
+    case RESAMPLETYPE(2, true, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
+        return;
+    case RESAMPLETYPE(1, false, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
+        return;
+    case RESAMPLETYPE(2, false, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
+        return;
     default:
-        ; // error
+        LOG_ALWAYS_FATAL("Invalid resampler type: %u", resampleType);
+        mResampleFunc = NULL;
+        return;
     }
 }
 
-template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
-        const TC* const coefs,  AudioBufferProvider* provider)
+template<typename TC, typename TI, typename TO>
+template<int CHANNELS, bool LOCKED, int STRIDE>
+void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
+        AudioBufferProvider* provider)
 {
     const Constants& c(mConstants);
-    int16_t* impulse = mInBuffer.getImpulse();
+    const TC* const coefs = mConstants.mFirCoefs;
+    TI* impulse = mInBuffer.getImpulse();
     size_t inputIndex = mInputIndex;
     uint32_t phaseFraction = mPhaseFraction;
     const uint32_t phaseIncrement = mPhaseIncrement;
@@ -490,8 +480,9 @@
                 goto resample_exit;
             }
             if (phaseFraction >= phaseWrapLimit) { // read in data
-                mInBuffer.readAdvance<CHANNELS>(
-                        impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+                mInBuffer.template readAdvance<CHANNELS>(
+                        impulse, c.mHalfNumCoefs,
+                        reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
                 phaseFraction -= phaseWrapLimit;
                 while (phaseFraction >= phaseWrapLimit) {
                     inputIndex++;
@@ -500,20 +491,21 @@
                         provider->releaseBuffer(&mBuffer);
                         break;
                     }
-                    mInBuffer.readAdvance<CHANNELS>(
-                            impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+                    mInBuffer.template readAdvance<CHANNELS>(
+                            impulse, c.mHalfNumCoefs,
+                            reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
                     phaseFraction -= phaseWrapLimit;
                 }
             }
         }
-        const int16_t* const in = mBuffer.i16;
+        const TI* const in = reinterpret_cast<const TI*>(mBuffer.raw);
         const size_t frameCount = mBuffer.frameCount;
         const int coefShift = c.mShift;
         const int halfNumCoefs = c.mHalfNumCoefs;
-        const int32_t* const volumeSimd = mVolumeSimd;
+        const TO* const volumeSimd = mVolumeSimd;
 
         // reread the last input in.
-        mInBuffer.readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+        mInBuffer.template readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
 
         // main processing loop
         while (CC_LIKELY(outputIndex < outputSampleCount)) {
@@ -536,7 +528,7 @@
                 if (inputIndex >= frameCount) {
                     goto done;  // need a new buffer
                 }
-                mInBuffer.readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+                mInBuffer.template readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
                 phaseFraction -= phaseWrapLimit;
             }
         }
@@ -555,5 +547,10 @@
     mPhaseFraction = phaseFraction;
 }
 
+/* instantiate templates used by AudioResampler::create */
+template class AudioResamplerDyn<float, float, float>;
+template class AudioResamplerDyn<int16_t, int16_t, int32_t>;
+template class AudioResamplerDyn<int32_t, int16_t, int32_t>;
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h
index df1fdbe..8c56319 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/services/audioflinger/AudioResamplerDyn.h
@@ -25,10 +25,24 @@
 
 namespace android {
 
+/* AudioResamplerDyn
+ *
+ * This class template is used for floating point and integer resamplers.
+ *
+ * Type variables:
+ * TC = filter coefficient type (one of int16_t, int32_t, or float)
+ * TI = input data type (one of int16_t or float)
+ * TO = output data type (one of int32_t or float)
+ *
+ * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
+ * For float input data types TI, the coefficient type TC is float.
+ */
+
+template<typename TC, typename TI, typename TO>
 class AudioResamplerDyn: public AudioResampler {
 public:
-    AudioResamplerDyn(int bitDepth, int inChannelCount, int32_t sampleRate,
-            src_quality quality);
+    AudioResamplerDyn(int bitDepth, int inChannelCount,
+            int32_t sampleRate, src_quality quality);
 
     virtual ~AudioResamplerDyn();
 
@@ -46,46 +60,38 @@
     class Constants { // stores the filter constants.
     public:
         Constants() :
-            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefsS16(NULL)
+            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
         {}
         void set(int L, int halfNumCoefs,
                 int inSampleRate, int outSampleRate);
-        inline void setBuf(int16_t* buf) {
-            mFirCoefsS16 = buf;
-        }
-        inline void setBuf(int32_t* buf) {
-            mFirCoefsS32 = buf;
-        }
 
-        int mL;       // interpolation phases in the filter.
-        int mShift;   // right shift to get polyphase index
+                 int mL;            // interpolation phases in the filter.
+                 int mShift;        // right shift to get polyphase index
         unsigned int mHalfNumCoefs; // filter half #coefs
-        union {       // polyphase filter bank
-            const int16_t* mFirCoefsS16;
-            const int32_t* mFirCoefsS32;
-        };
+           const TC* mFirCoefs;     // polyphase filter bank
     };
 
-    // Input buffer management for a given input type TI, now (int16_t)
-    // Is agnostic of the actual type, can work with int32_t and float.
-    template<typename TI>
-    class InBuffer {
+    class InBuffer { // buffer management for input type TI
     public:
         InBuffer();
         ~InBuffer();
         void init();
+
         void resize(int CHANNELS, int halfNumCoefs);
 
         // used for direct management of the mImpulse pointer
         inline TI* getImpulse() {
             return mImpulse;
         }
+
         inline void setImpulse(TI *impulse) {
             mImpulse = impulse;
         }
+
         template<int CHANNELS>
         inline void readAgain(TI*& impulse, const int halfNumCoefs,
                 const TI* const in, const size_t inputIndex);
+
         template<int CHANNELS>
         inline void readAdvance(TI*& impulse, const int halfNumCoefs,
                 const TI* const in, const size_t inputIndex);
@@ -94,31 +100,35 @@
         // tuning parameter guidelines: 2 <= multiple <= 8
         static const int kStateSizeMultipleOfFilterLength = 4;
 
-        TI* mState;    // base pointer for the input buffer storage
-        TI* mImpulse;  // current location of the impulse response (centered)
-        TI* mRingFull; // mState <= mImpulse < mRingFull
         // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
-        size_t mStateSize; // in units of TI.
+           TI* mState;      // base pointer for the input buffer storage
+           TI* mImpulse;    // current location of the impulse response (centered)
+           TI* mRingFull;   // mState <= mImpulse < mRingFull
+        size_t mStateCount; // size of state in units of TI.
     };
 
-    template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
-    void resample(int32_t* out, size_t outFrameCount,
-            const TC* const coefs, AudioBufferProvider* provider);
-
-    template<typename T>
     void createKaiserFir(Constants &c, double stopBandAtten,
             int inSampleRate, int outSampleRate, double tbwCheat);
 
-    InBuffer<int16_t> mInBuffer;
-    Constants mConstants;  // current set of coefficient parameters
-    int32_t __attribute__ ((aligned (8))) mVolumeSimd[2];
-    int32_t mResampleType; // contains the resample type.
-    int32_t mFilterSampleRate; // designed filter sample rate.
-    src_quality mFilterQuality; // designed filter quality.
-    void* mCoefBuffer; // if a filter is created, this is not null
+    void setResampler(unsigned resampleType);
+
+    template<int CHANNELS, bool LOCKED, int STRIDE>
+    void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
+
+    // declare a pointer to member function for resample
+    typedef void (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
+            size_t outFrameCount, AudioBufferProvider* provider);
+
+    // data - the contiguous storage and layout of these is important.
+           InBuffer mInBuffer;
+          Constants mConstants;        // current set of coefficient parameters
+    TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
+     resample_ABP_t mResampleFunc;     // called function for resampling
+            int32_t mFilterSampleRate; // designed filter sample rate.
+        src_quality mFilterQuality;    // designed filter quality.
+              void* mCoefBuffer;       // if a filter is created, this is not null
 };
 
-// ----------------------------------------------------------------------------
 }; // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/
diff --git a/services/audioflinger/AudioResamplerFirGen.h b/services/audioflinger/AudioResamplerFirGen.h
index 8833758..d024b2f 100644
--- a/services/audioflinger/AudioResamplerFirGen.h
+++ b/services/audioflinger/AudioResamplerFirGen.h
@@ -365,6 +365,28 @@
     }
 }
 
+/* A speed optimized version of the Modified Bessel I0() which incorporates
+ * the sqrt and numerator multiply and denominator divide into the computation.
+ * This speeds up filter computation by about 10-15%.
+ */
+static inline double I0SqrRat(double x2, double num, double den) {
+    if (x2 < (3.75 * 3.75)) {
+        return Poly7(I0Term<0>::value, I0Term<1>::value,
+                I0Term<2>::value, I0Term<3>::value,
+                I0Term<4>::value, I0Term<5>::value,
+                I0Term<6>::value, x2) * num / den; // e < 1.6e-7
+    }
+    num *= Poly9(-0.13544938430e9, -0.33153754512e8,
+            -0.19406631946e7, -0.48058318783e5,
+            -0.63269783360e3, -0.49520779070e1,
+            -0.24970910370e-1, -0.74741159550e-4,
+            -0.18257612460e-6, x2); // e < 10^(-7.13).
+    double y = x2 - 225.; // reflection around 15 (squared)
+    den *= Poly4(-0.34598737196e8, 0.23852643181e6,
+            -0.70699387620e3, 0.10000000000e1, y);
+    return num / den;
+}
+
 /*
  * calculates the transition bandwidth for a Kaiser filter
  *
@@ -645,6 +667,7 @@
     const double xstep = (2. * M_PI) * fcr / L;
     const double xfrac = 1. / N;
     const double yscale = atten * L / (I0(beta) * M_PI);
+    const double sqrbeta = sqr(beta);
 
     // We use sine generators, which computes sines on regular step intervals.
     // This speeds up overall computation about 40% from computing the sine directly.
@@ -663,7 +686,8 @@
                 double x = static_cast<double>(ix);
 
                 // sine generator: sg.valueAdvance() returns sin(ix*xstep);
-                y = I0(beta * sqrt(1.0 - sqr(x * xfrac))) * yscale * sg.valueAdvance() / x;
+                // y = I0(beta * sqrt(1.0 - sqr(x * xfrac))) * yscale * sg.valueAdvance() / x;
+                y = I0SqrRat(sqrbeta * (1.0 - sqr(x * xfrac)), yscale * sg.valueAdvance(), x);
             } else {
                 y = 2. * atten * fcr; // center of filter, sinc(0) = 1.
                 sg.advance();
diff --git a/services/audioflinger/AudioResamplerFirProcess.h b/services/audioflinger/AudioResamplerFirProcess.h
index 38e387c..76d2d66 100644
--- a/services/audioflinger/AudioResamplerFirProcess.h
+++ b/services/audioflinger/AudioResamplerFirProcess.h
@@ -21,47 +21,55 @@
 
 // depends on AudioResamplerFirOps.h
 
-template<int CHANNELS, typename TC>
+/* variant for input type TI = int16_t input samples */
+template<typename TC>
 static inline
-void mac(
-        int32_t& l, int32_t& r,
-        const TC coef,
-        const int16_t* samples)
+void mac(int32_t& l, int32_t& r, TC coef, const int16_t* samples)
 {
-    if (CHANNELS == 2) {
-        uint32_t rl = *reinterpret_cast<const uint32_t*>(samples);
-        l = mulAddRL(1, rl, coef, l);
-        r = mulAddRL(0, rl, coef, r);
-    } else {
-        r = l = mulAdd(samples[0], coef, l);
-    }
+    uint32_t rl = *reinterpret_cast<const uint32_t*>(samples);
+    l = mulAddRL(1, rl, coef, l);
+    r = mulAddRL(0, rl, coef, r);
 }
 
-template<int CHANNELS, typename TC>
+template<typename TC>
 static inline
-void interpolate(
-        int32_t& l, int32_t& r,
-        const TC coef_0, const TC coef_1,
-        const int16_t lerp, const int16_t* samples)
+void mac(int32_t& l, TC coef, const int16_t* samples)
 {
-    TC sinc;
+    l = mulAdd(samples[0], coef, l);
+}
 
-    if (is_same<TC, int16_t>::value) {
-        sinc = (lerp * ((coef_1-coef_0)<<1)>>16) + coef_0;
-    } else {
-        sinc = mulAdd(lerp, (coef_1-coef_0)<<1, coef_0);
-    }
-    if (CHANNELS == 2) {
-        uint32_t rl = *reinterpret_cast<const uint32_t*>(samples);
-        l = mulAddRL(1, rl, sinc, l);
-        r = mulAddRL(0, rl, sinc, r);
-    } else {
-        r = l = mulAdd(samples[0], sinc, l);
-    }
+/* variant for input type TI = float input samples */
+template<typename TC>
+static inline
+void mac(float& l, float& r, TC coef,  const float* samples)
+{
+    l += *samples++ * coef;
+    r += *samples++ * coef;
+}
+
+template<typename TC>
+static inline
+void mac(float& l, TC coef,  const float* samples)
+{
+    l += *samples++ * coef;
+}
+
+/* variant for output type TO = int32_t output samples */
+static inline
+int32_t volumeAdjust(int32_t value, int32_t volume)
+{
+    return 2 * mulRL(0, value, volume);  // Note: only use top 16b
+}
+
+/* variant for output type TO = float output samples */
+static inline
+float volumeAdjust(float value, float volume)
+{
+    return value * volume;
 }
 
 /*
- * Calculates a single output sample (two stereo frames).
+ * Calculates a single output frame (two samples).
  *
  * This function computes both the positive half FIR dot product and
  * the negative half FIR dot product, accumulates, and then applies the volume.
@@ -72,30 +80,43 @@
  * filter bank.
  */
 
-template <int CHANNELS, int STRIDE, typename TC>
+template <int CHANNELS, int STRIDE, typename TC, typename TI, typename TO>
 static inline
-void ProcessL(int32_t* const out,
+void ProcessL(TO* const out,
         int count,
         const TC* coefsP,
         const TC* coefsN,
-        const int16_t* sP,
-        const int16_t* sN,
-        const int32_t* const volumeLR)
+        const TI* sP,
+        const TI* sN,
+        const TO* const volumeLR)
 {
-    int32_t l = 0;
-    int32_t r = 0;
-    do {
-        mac<CHANNELS>(l, r, *coefsP++, sP);
-        sP -= CHANNELS;
-        mac<CHANNELS>(l, r, *coefsN++, sN);
-        sN += CHANNELS;
-    } while (--count > 0);
-    out[0] += 2 * mulRL(0, l, volumeLR[0]); // Note: only use top 16b
-    out[1] += 2 * mulRL(0, r, volumeLR[1]); // Note: only use top 16b
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS >= 1 && CHANNELS <= 2)
+    if (CHANNELS == 2) {
+        TO l = 0;
+        TO r = 0;
+        do {
+            mac(l, r, *coefsP++, sP);
+            sP -= CHANNELS;
+            mac(l, r, *coefsN++, sN);
+            sN += CHANNELS;
+        } while (--count > 0);
+        out[0] += volumeAdjust(l, volumeLR[0]);
+        out[1] += volumeAdjust(r, volumeLR[1]);
+    } else { /* CHANNELS == 1 */
+        TO l = 0;
+        do {
+            mac(l, *coefsP++, sP);
+            sP -= CHANNELS;
+            mac(l, *coefsN++, sN);
+            sN += CHANNELS;
+        } while (--count > 0);
+        out[0] += volumeAdjust(l, volumeLR[0]);
+        out[1] += volumeAdjust(l, volumeLR[1]);
+    }
 }
 
 /*
- * Calculates a single output sample (two stereo frames) interpolating phase.
+ * Calculates a single output frame (two samples) interpolating phase.
  *
  * This function computes both the positive half FIR dot product and
  * the negative half FIR dot product, accumulates, and then applies the volume.
@@ -106,47 +127,91 @@
  * filter bank.
  */
 
-template <int CHANNELS, int STRIDE, typename TC>
+template<typename TC, typename T>
+void adjustLerp(T& lerpP __unused)
+{
+}
+
+template<int32_t, typename T>
+void adjustLerp(T& lerpP)
+{
+    lerpP >>= 16;   // lerpP is 32bit for NEON int32_t, but always 16 bit for non-NEON path
+}
+
+template<typename TC, typename TINTERP>
 static inline
-void Process(int32_t* const out,
+TC interpolate(TC coef_0, TC coef_1, TINTERP lerp)
+{
+    return lerp * (coef_1 - coef_0) + coef_0;
+}
+
+template<int16_t, uint32_t>
+static inline
+int16_t interpolate(int16_t coef_0, int16_t coef_1, uint32_t lerp)
+{
+    return (static_cast<int16_t>(lerp) * ((coef_1-coef_0)<<1)>>16) + coef_0;
+}
+
+template<int32_t, uint32_t>
+static inline
+int32_t interpolate(int32_t coef_0, int32_t coef_1, uint32_t lerp)
+{
+    return mulAdd(static_cast<int16_t>(lerp), (coef_1-coef_0)<<1, coef_0);
+}
+
+template <int CHANNELS, int STRIDE, typename TC, typename TI, typename TO, typename TINTERP>
+static inline
+void Process(TO* const out,
         int count,
         const TC* coefsP,
         const TC* coefsN,
-        const TC* coefsP1,
-        const TC* coefsN1,
-        const int16_t* sP,
-        const int16_t* sN,
-        uint32_t lerpP,
-        const int32_t* const volumeLR)
+        const TC* coefsP1 __unused,
+        const TC* coefsN1 __unused,
+        const TI* sP,
+        const TI* sN,
+        TINTERP lerpP,
+        const TO* const volumeLR)
 {
-    (void) coefsP1; // suppress unused parameter warning
-    (void) coefsN1;
-    if (sizeof(*coefsP)==4) {
-        lerpP >>= 16;   // ensure lerpP is 16b
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS >= 1 && CHANNELS <= 2)
+    adjustLerp<TC, TINTERP>(lerpP); // coefficient type adjustment for interpolation
+
+    if (CHANNELS == 2) {
+        TO l = 0;
+        TO r = 0;
+        for (size_t i = 0; i < count; ++i) {
+            mac(l, r, interpolate(coefsP[0], coefsP[count], lerpP), sP);
+            coefsP++;
+            sP -= CHANNELS;
+            mac(l, r, interpolate(coefsN[count], coefsN[0], lerpP), sN);
+            coefsN++;
+            sN += CHANNELS;
+        }
+        out[0] += volumeAdjust(l, volumeLR[0]);
+        out[1] += volumeAdjust(r, volumeLR[1]);
+    } else { /* CHANNELS == 1 */
+        TO l = 0;
+        for (size_t i = 0; i < count; ++i) {
+            mac(l, interpolate(coefsP[0], coefsP[count], lerpP), sP);
+            coefsP++;
+            sP -= CHANNELS;
+            mac(l, interpolate(coefsN[count], coefsN[0], lerpP), sN);
+            coefsN++;
+            sN += CHANNELS;
+        }
+        out[0] += volumeAdjust(l, volumeLR[0]);
+        out[1] += volumeAdjust(l, volumeLR[1]);
     }
-    int32_t l = 0;
-    int32_t r = 0;
-    for (size_t i = 0; i < count; ++i) {
-        interpolate<CHANNELS>(l, r, coefsP[0], coefsP[count], lerpP, sP);
-        coefsP++;
-        sP -= CHANNELS;
-        interpolate<CHANNELS>(l, r, coefsN[count], coefsN[0], lerpP, sN);
-        coefsN++;
-        sN += CHANNELS;
-    }
-    out[0] += 2 * mulRL(0, l, volumeLR[0]); // Note: only use top 16b
-    out[1] += 2 * mulRL(0, r, volumeLR[1]); // Note: only use top 16b
 }
 
 /*
- * Calculates a single output sample (two stereo frames) from input sample pointer.
+ * Calculates a single output frame (two samples) from input sample pointer.
  *
  * This sets up the params for the accelerated Process() and ProcessL()
  * functions to do the appropriate dot products.
  *
- * @param out should point to the output buffer with at least enough space for 2 output frames.
+ * @param out should point to the output buffer with space for at least one output frame.
  *
- * @param phase is the fractional distance between input samples for interpolation:
+ * @param phase is the fractional distance between input frames for interpolation:
  * phase >= 0  && phase < phaseWrapLimit.  It can be thought of as a rational fraction
  * of phase/phaseWrapLimit.
  *
@@ -195,14 +260,17 @@
  * lerpP = phase << sizeof(phase)*8 - coefShift
  *              >> (sizeof(phase)-sizeof(*coefs))*8 + 1;
  *
+ * For floating point, lerpP is the fractional phase scaled to [0.0, 1.0):
+ *
+ * lerpP = (phase << 32 - coefShift) / (1 << 32); // floating point equivalent
  */
 
-template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
+template<int CHANNELS, bool LOCKED, int STRIDE, typename TC, typename TI, typename TO>
 static inline
-void fir(int32_t* const out,
+void fir(TO* const out,
         const uint32_t phase, const uint32_t phaseWrapLimit,
         const int coefShift, const int halfNumCoefs, const TC* const coefs,
-        const int16_t* const samples, const int32_t* const volumeLR)
+        const TI* const samples, const TO* const volumeLR)
 {
     // NOTE: be very careful when modifying the code here. register
     // pressure is very high and a small change might cause the compiler
@@ -216,8 +284,8 @@
         uint32_t indexN = (phaseWrapLimit - phase) >> coefShift;
         const TC* coefsP = coefs + indexP*halfNumCoefs;
         const TC* coefsN = coefs + indexN*halfNumCoefs;
-        const int16_t* sP = samples;
-        const int16_t* sN = samples + CHANNELS;
+        const TI* sP = samples;
+        const TI* sN = samples + CHANNELS;
 
         // dot product filter.
         ProcessL<CHANNELS, STRIDE>(out,
@@ -231,8 +299,8 @@
         const TC* coefsN = coefs + indexN*halfNumCoefs;
         const TC* coefsP1 = coefsP + halfNumCoefs;
         const TC* coefsN1 = coefsN + halfNumCoefs;
-        const int16_t* sP = samples;
-        const int16_t* sN = samples + CHANNELS;
+        const TI* sP = samples;
+        const TI* sN = samples + CHANNELS;
 
         // Interpolation fraction lerpP derived by shifting all the way up and down
         // to clear the appropriate bits and align to the appropriate level
@@ -242,12 +310,21 @@
         //
         // interpolated[P] = index[P]*lerpP + index[P+1]*(1-lerpP)
         // interpolated[N] = index[N+1]*lerpP + index[N]*(1-lerpP)
-        uint32_t lerpP = phase << (sizeof(phase)*8 - coefShift)
-                >> ((sizeof(phase)-sizeof(*coefs))*8 + 1);
 
         // on-the-fly interpolated dot product filter
-        Process<CHANNELS, STRIDE>(out,
-                halfNumCoefs, coefsP, coefsN, coefsP1, coefsN1, sP, sN, lerpP, volumeLR);
+        if (is_same<TC, float>::value || is_same<TC, double>::value) {
+            static const TC scale = 1. / (65536. * 65536.); // scale phase bits to [0.0, 1.0)
+            TC lerpP = TC(phase << (sizeof(phase)*8 - coefShift)) * scale;
+
+            Process<CHANNELS, STRIDE>(out,
+                    halfNumCoefs, coefsP, coefsN, coefsP1, coefsN1, sP, sN, lerpP, volumeLR);
+        } else {
+            uint32_t lerpP = phase << (sizeof(phase)*8 - coefShift)
+                    >> ((sizeof(phase)-sizeof(*coefs))*8 + 1);
+
+            Process<CHANNELS, STRIDE>(out,
+                    halfNumCoefs, coefsP, coefsN, coefsP1, coefsN1, sP, sN, lerpP, volumeLR);
+        }
     }
 }
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index feedd89..ae3dd8b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3951,6 +3951,16 @@
         AudioParameter param = AudioParameter(keyValuePair);
         int value;
 
+        if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            // forward device change to effects that have requested to be
+            // aware of attached audio device.
+            if (value != AUDIO_DEVICE_NONE) {
+                mOutDevice = value;
+                for (size_t i = 0; i < mEffectChains.size(); i++) {
+                    mEffectChains[i]->setDevice_l(mOutDevice);
+                }
+            }
+        }
         if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
             // do not accept frame count changes if tracks are open as the track buffer
             // size depends on frame count and correct behavior would not be garantied
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 2cf10e2..1064fd1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -930,7 +930,7 @@
 
 void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
 {
-    for (int i = 0; i < (int)mSyncEvents.size(); i++) {
+    for (size_t i = 0; i < mSyncEvents.size(); i++) {
         if (mSyncEvents[i]->type() == type) {
             mSyncEvents[i]->trigger();
             mSyncEvents.removeAt(i);
diff --git a/services/audioflinger/test-resample.cpp b/services/audioflinger/test-resample.cpp
index d1de95d..e14b4ae 100644
--- a/services/audioflinger/test-resample.cpp
+++ b/services/audioflinger/test-resample.cpp
@@ -36,16 +36,16 @@
 static bool gVerbose = false;
 
 static int usage(const char* name) {
-    fprintf(stderr,"Usage: %s [-p] [-f] [-F] [-h] [-v] [-s] [-q {dq|lq|mq|hq|vhq|dlq|dmq|dhq}]"
+    fprintf(stderr,"Usage: %s [-p] [-f] [-F] [-v] [-c channels]"
+                   " [-q {dq|lq|mq|hq|vhq|dlq|dmq|dhq}]"
                    " [-i input-sample-rate] [-o output-sample-rate]"
                    " [-O csv] [-P csv] [<input-file>]"
                    " <output-file>\n", name);
     fprintf(stderr,"    -p    enable profiling\n");
     fprintf(stderr,"    -f    enable filter profiling\n");
     fprintf(stderr,"    -F    enable floating point -q {dlq|dmq|dhq} only");
-    fprintf(stderr,"    -h    create wav file\n");
     fprintf(stderr,"    -v    verbose : log buffer provider calls\n");
-    fprintf(stderr,"    -s    stereo (ignored if input file is specified)\n");
+    fprintf(stderr,"    -c    # channels (1-2 for lq|mq|hq; 1-8 for dlq|dmq|dhq)\n");
     fprintf(stderr,"    -q    resampler quality\n");
     fprintf(stderr,"              dq  : default quality\n");
     fprintf(stderr,"              lq  : low quality\n");
@@ -102,11 +102,9 @@
 }
 
 int main(int argc, char* argv[]) {
-
     const char* const progname = argv[0];
     bool profileResample = false;
     bool profileFilter = false;
-    bool writeHeader = false;
     bool useFloat = false;
     int channels = 1;
     int input_freq = 0;
@@ -116,7 +114,7 @@
     Vector<int> Pvalues;
 
     int ch;
-    while ((ch = getopt(argc, argv, "pfFhvsq:i:o:O:P:")) != -1) {
+    while ((ch = getopt(argc, argv, "pfFvc:q:i:o:O:P:")) != -1) {
         switch (ch) {
         case 'p':
             profileResample = true;
@@ -127,14 +125,11 @@
         case 'F':
             useFloat = true;
             break;
-        case 'h':
-            writeHeader = true;
-            break;
         case 'v':
             gVerbose = true;
             break;
-        case 's':
-            channels = 2;
+        case 'c':
+            channels = atoi(optarg);
             break;
         case 'q':
             if (!strcmp(optarg, "dq"))
@@ -183,6 +178,11 @@
         }
     }
 
+    if (channels < 1
+            || channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
+        fprintf(stderr, "invalid number of audio channels %d\n", channels);
+        return -1;
+    }
     if (useFloat && quality < AudioResampler::DYN_LOW_QUALITY) {
         fprintf(stderr, "float processing is only possible for dynamic resamplers\n");
         return -1;
@@ -234,20 +234,20 @@
             double t = double(i) / input_freq;
             double y = sin(M_PI * k * t * t);
             int16_t yi = floor(y * 32767.0 + 0.5);
-            for (size_t j=0 ; j<(size_t)channels ; j++) {
-                in[i*channels + j] = yi / (1+j); // right ch. 1/2 left ch.
+            for (int j = 0; j < channels; j++) {
+                in[i*channels + j] = yi / (1 + j);
             }
         }
     }
-    size_t frame_size = channels * sizeof(int16_t);
-    size_t input_frames = input_size / frame_size;
+    size_t input_framesize = channels * sizeof(int16_t);
+    size_t input_frames = input_size / input_framesize;
 
     // For float processing, convert input int16_t to float array
     if (useFloat) {
         void *new_vaddr;
 
-        frame_size = channels * sizeof(float);
-        input_size = input_frames * frame_size;
+        input_framesize = channels * sizeof(float);
+        input_size = input_frames * input_framesize;
         new_vaddr = malloc(input_size);
         memcpy_to_float_from_i16(reinterpret_cast<float*>(new_vaddr),
                 reinterpret_cast<int16_t*>(input_vaddr), input_frames * channels);
@@ -323,15 +323,17 @@
         void reset() {
             mNextFrame = 0;
         }
-    } provider(input_vaddr, input_frames, frame_size, Pvalues);
+    } provider(input_vaddr, input_frames, input_framesize, Pvalues);
 
     if (gVerbose) {
         printf("%zu input frames\n", input_frames);
     }
 
     int bit_depth = useFloat ? 32 : 16;
-    size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq;
-    output_size &= ~7; // always stereo, 32-bits
+    int output_channels = channels > 2 ? channels : 2; // output is at least stereo samples
+    size_t output_framesize = output_channels * (useFloat ? sizeof(float) : sizeof(int32_t));
+    size_t output_frames = ((int64_t) input_frames * output_freq) / input_freq;
+    size_t output_size = output_frames * output_framesize;
 
     if (profileFilter) {
         // Check how fast sample rate changes are that require filter changes.
@@ -380,7 +382,7 @@
     void* output_vaddr = malloc(output_size);
     AudioResampler* resampler = AudioResampler::create(bit_depth, channels,
             output_freq, quality);
-    size_t out_frames = output_size/8;
+
 
     /* set volume precision to 12 bits, so the volume scale is 1<<12.
      * The output int32_t is represented as Q4.27, with 4 bits of guard
@@ -422,7 +424,7 @@
         for (int n = 0; n < trials; ++n) {
             clock_gettime(CLOCK_MONOTONIC, &start);
             for (int i = 0; i < looplimit; ++i) {
-                resampler->resample((int*) output_vaddr, out_frames, &provider);
+                resampler->resample((int*) output_vaddr, output_frames, &provider);
                 provider.reset(); //  during benchmarking reset only the provider
             }
             clock_gettime(CLOCK_MONOTONIC, &end);
@@ -435,26 +437,26 @@
         }
         // Mfrms/s is "Millions of output frames per second".
         printf("quality: %d  channels: %d  msec: %" PRId64 "  Mfrms/s: %.2lf\n",
-                quality, channels, time/1000000, out_frames * looplimit / (time / 1e9) / 1e6);
+                quality, channels, time/1000000, output_frames * looplimit / (time / 1e9) / 1e6);
         resampler->reset();
     }
 
     memset(output_vaddr, 0, output_size);
     if (gVerbose) {
-        printf("resample() %zu output frames\n", out_frames);
+        printf("resample() %zu output frames\n", output_frames);
     }
     if (Ovalues.isEmpty()) {
-        Ovalues.push(out_frames);
+        Ovalues.push(output_frames);
     }
-    for (size_t i = 0, j = 0; i < out_frames; ) {
+    for (size_t i = 0, j = 0; i < output_frames; ) {
         size_t thisFrames = Ovalues[j++];
         if (j >= Ovalues.size()) {
             j = 0;
         }
-        if (thisFrames == 0 || thisFrames > out_frames - i) {
-            thisFrames = out_frames - i;
+        if (thisFrames == 0 || thisFrames > output_frames - i) {
+            thisFrames = output_frames - i;
         }
-        resampler->resample((int*) output_vaddr + 2*i, thisFrames, &provider);
+        resampler->resample((int*) output_vaddr + output_channels*i, thisFrames, &provider);
         i += thisFrames;
     }
     if (gVerbose) {
@@ -471,20 +473,20 @@
     // which is then converted to int16_t for final storage.
     if (useFloat) {
         memcpy_to_q4_27_from_float(reinterpret_cast<int32_t*>(output_vaddr),
-                reinterpret_cast<float*>(output_vaddr), out_frames * 2); // stereo samples
+                reinterpret_cast<float*>(output_vaddr), output_frames * output_channels);
     }
 
-    // mono takes left channel only
-    // stereo right channel is half amplitude of stereo left channel (due to input creation)
+    // mono takes left channel only (out of stereo output pair)
+    // stereo and multichannel preserve all channels.
     int32_t* out = (int32_t*) output_vaddr;
-    int16_t* convert = (int16_t*) malloc(out_frames * channels * sizeof(int16_t));
+    int16_t* convert = (int16_t*) malloc(output_frames * channels * sizeof(int16_t));
 
     // round to half towards zero and saturate at int16 (non-dithered)
     const int roundVal = (1<<(volumePrecision-1)) - 1; // volumePrecision > 0
 
-    for (size_t i = 0; i < out_frames; i++) {
+    for (size_t i = 0; i < output_frames; i++) {
         for (int j = 0; j < channels; j++) {
-            int32_t s = out[i * 2 + j] + roundVal; // add offset here
+            int32_t s = out[i * output_channels + j] + roundVal; // add offset here
             if (s < 0) {
                 s = (s + 1) >> volumePrecision; // round to 0
                 if (s < -32768) {
@@ -501,29 +503,18 @@
     }
 
     // write output to disk
-    if (writeHeader) {
-        SF_INFO info;
-        info.frames = 0;
-        info.samplerate = output_freq;
-        info.channels = channels;
-        info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
-        SNDFILE *sf = sf_open(file_out, SFM_WRITE, &info);
-        if (sf == NULL) {
-            perror(file_out);
-            return EXIT_FAILURE;
-        }
-        (void) sf_writef_short(sf, convert, out_frames);
-        sf_close(sf);
-    } else {
-        int output_fd = open(file_out, O_WRONLY | O_CREAT | O_TRUNC,
-                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-        if (output_fd < 0) {
-            perror(file_out);
-            return EXIT_FAILURE;
-        }
-        write(output_fd, convert, out_frames * channels * sizeof(int16_t));
-        close(output_fd);
+    SF_INFO info;
+    info.frames = 0;
+    info.samplerate = output_freq;
+    info.channels = channels;
+    info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    SNDFILE *sf = sf_open(file_out, SFM_WRITE, &info);
+    if (sf == NULL) {
+        perror(file_out);
+        return EXIT_FAILURE;
     }
+    (void) sf_writef_short(sf, convert, output_frames);
+    sf_close(sf);
 
     return EXIT_SUCCESS;
 }
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..8268f65 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();
@@ -585,12 +584,15 @@
         entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP);
         if (entry.count == 0) {
             ALOGE("No timestamp field in capture frame!");
-        }
-        if (entry.data.i64[0] != mCaptureTimestamp) {
-            ALOGW("Mismatched capture timestamps: Metadata frame %" PRId64 ","
-                    " captured buffer %" PRId64,
-                    entry.data.i64[0],
-                    mCaptureTimestamp);
+        } else if (entry.count == 1) {
+            if (entry.data.i64[0] != mCaptureTimestamp) {
+                ALOGW("Mismatched capture timestamps: Metadata frame %" PRId64 ","
+                        " captured buffer %" PRId64,
+                        entry.data.i64[0],
+                        mCaptureTimestamp);
+            }
+        } else {
+            ALOGE("Timestamp metadata is malformed!");
         }
         client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
 
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..f965136 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,60 +407,39 @@
             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);
+
+        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);
-    Mutex::Autolock l(mLock);
 
-    // TODO: take ownership of the request
-
-    switch (mStatus) {
-        case STATUS_ERROR:
-            CLOGE("Device has encountered a serious error");
-            return INVALID_OPERATION;
-        case STATUS_UNINITIALIZED:
-            CLOGE("Device not initialized");
-            return INVALID_OPERATION;
-        case STATUS_UNCONFIGURED:
-            // May be lazily configuring streams, will check during setup
-        case STATUS_CONFIGURED:
-        case STATUS_ACTIVE:
-            // OK
-            break;
-        default:
-            SET_ERR_L("Unexpected status: %d", mStatus);
-            return INVALID_OPERATION;
-    }
-
-    sp<CaptureRequest> newRequest = setUpRequestLocked(request);
-    if (newRequest == NULL) {
-        CLOGE("Can't create capture request");
-        return BAD_VALUE;
-    }
-
-    res = mRequestThread->queueRequest(newRequest);
-    if (res == OK) {
-        waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
-        if (res != OK) {
-            SET_ERR_L("Can't transition to active in %f seconds!",
-                    kActiveTimeout/1e9);
-        }
-        ALOGV("Camera %d: Capture request enqueued", mId);
-    } else {
-        CLOGE("Cannot queue request. Impossible."); // queueRequest always returns OK.
-        return BAD_VALUE;
-    }
-    return res;
+    List<const CameraMetadata> requests;
+    requests.push_back(request);
+    return captureList(requests, /*lastFrameNumber*/NULL);
 }
 
 status_t Camera3Device::submitRequestsHelper(
-        const List<const CameraMetadata> &requests, bool repeating) {
+        const List<const CameraMetadata> &requests, bool repeating,
+        /*out*/
+        int64_t *lastFrameNumber) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
@@ -479,9 +459,9 @@
     }
 
     if (repeating) {
-        res = mRequestThread->setRepeatingRequests(requestList);
+        res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
     } else {
-        res = mRequestThread->queueRequestList(requestList);
+        res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
     }
 
     if (res == OK) {
@@ -490,7 +470,8 @@
             SET_ERR_L("Can't transition to active in %f seconds!",
                     kActiveTimeout/1e9);
         }
-        ALOGV("Camera %d: Capture request enqueued", mId);
+        ALOGV("Camera %d: Capture request %" PRId32 " enqueued", mId,
+              (*(requestList.begin()))->mResultExtras.requestId);
     } else {
         CLOGE("Cannot queue request. Impossible.");
         return BAD_VALUE;
@@ -499,61 +480,27 @@
     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);
-    Mutex::Autolock l(mLock);
 
-    switch (mStatus) {
-        case STATUS_ERROR:
-            CLOGE("Device has encountered a serious error");
-            return INVALID_OPERATION;
-        case STATUS_UNINITIALIZED:
-            CLOGE("Device not initialized");
-            return INVALID_OPERATION;
-        case STATUS_UNCONFIGURED:
-            // May be lazily configuring streams, will check during setup
-        case STATUS_CONFIGURED:
-        case STATUS_ACTIVE:
-            // OK
-            break;
-        default:
-            SET_ERR_L("Unexpected status: %d", mStatus);
-            return INVALID_OPERATION;
-    }
-
-    sp<CaptureRequest> newRepeatingRequest = setUpRequestLocked(request);
-    if (newRepeatingRequest == NULL) {
-        CLOGE("Can't create repeating request");
-        return BAD_VALUE;
-    }
-
-    RequestList newRepeatingRequests;
-    newRepeatingRequests.push_back(newRepeatingRequest);
-
-    res = mRequestThread->setRepeatingRequests(newRepeatingRequests);
-    if (res == OK) {
-        waitUntilStateThenRelock(/*active*/ true, kActiveTimeout);
-        if (res != OK) {
-            SET_ERR_L("Can't transition to active in %f seconds!",
-                    kActiveTimeout/1e9);
-        }
-        ALOGV("Camera %d: Repeating request set", mId);
-    }
-    return res;
+    List<const CameraMetadata> requests;
+    requests.push_back(request);
+    return setStreamingRequestList(requests, /*lastFrameNumber*/NULL);
 }
 
-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 +523,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,7 +545,8 @@
             return INVALID_OPERATION;
     }
     ALOGV("Camera %d: Clearing repeating request", mId);
-    return mRequestThread->clearRepeatingRequests();
+
+    return mRequestThread->clearRepeatingRequests(lastFrameNumber);
 }
 
 status_t Camera3Device::waitUntilRequestReceived(int32_t requestId, nsecs_t timeout) {
@@ -1115,7 +1063,7 @@
     return OK;
 }
 
-status_t Camera3Device::getNextFrame(CameraMetadata *frame) {
+status_t Camera3Device::getNextResult(CaptureResult *frame) {
     ATRACE_CALL();
     Mutex::Autolock l(mOutputLock);
 
@@ -1123,8 +1071,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,13 +1156,13 @@
     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);
 
-    mRequestThread->clear();
+    mRequestThread->clear(/*out*/frameNumber);
     status_t res;
     if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) {
         res = mHal3Device->ops->flush(mHal3Device);
@@ -1484,13 +1438,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 +1456,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
@@ -1552,7 +1506,7 @@
     ALOGVV("%s: Camera %d: Frame %d, Request ID %d: AF mode %d, AWB mode %d, "
         "AF state %d, AE state %d, AWB state %d, "
         "AF trigger %d, AE precapture trigger %d",
-        __FUNCTION__, mId, frameNumber, requestId,
+        __FUNCTION__, mId, frameNumber, resultExtras.requestId,
         afMode, awbMode,
         afState, aeState, awbState,
         afTriggerId, aeTriggerId);
@@ -1567,58 +1521,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 +1589,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 +1614,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 +1641,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 +1657,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 +1682,15 @@
                 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;
+
         /**
          * One of the following must happen before it's legal to call process_capture_result,
          * unless partial metadata is being provided:
@@ -1791,11 +1757,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 +1773,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 +1795,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 +1827,6 @@
 
 }
 
-
-
 void Camera3Device::notify(const camera3_notify_msg *msg) {
     ATRACE_CALL();
     NotificationListener *listener;
@@ -1884,18 +1853,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 +1898,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 +1908,7 @@
                 if (idx >= 0) {
                     InFlightRequest &r = mInFlightMap.editValueAt(idx);
                     r.captureTimestamp = timestamp;
-                    requestId = r.requestId;
+                    resultExtras = r.resultExtras;
                 }
             }
             if (idx < 0) {
@@ -1934,10 +1917,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 +1942,7 @@
     return retVal;
 }
 
+
 /**
  * RequestThread inner class methods
  */
@@ -1975,7 +1959,8 @@
         mDoPause(false),
         mPaused(true),
         mFrameNumber(0),
-        mLatestRequestId(NAME_NOT_FOUND) {
+        mLatestRequestId(NAME_NOT_FOUND),
+        mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
     mStatusId = statusTracker->addComponent();
 }
 
@@ -1984,24 +1969,23 @@
     mReconfigured = true;
 }
 
-status_t Camera3Device::RequestThread::queueRequest(
-         sp<CaptureRequest> request) {
-    Mutex::Autolock l(mRequestLock);
-    mRequestQueue.push_back(request);
-
-    unpauseForNewRequests();
-
-    return OK;
-}
-
 status_t Camera3Device::RequestThread::queueRequestList(
-        List<sp<CaptureRequest> > &requests) {
+        List<sp<CaptureRequest> > &requests,
+        /*out*/
+        int64_t *lastFrameNumber) {
     Mutex::Autolock l(mRequestLock);
     for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
             ++it) {
         mRequestQueue.push_back(*it);
     }
 
+    if (lastFrameNumber != NULL) {
+        *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
+        ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
+              __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
+              *lastFrameNumber);
+    }
+
     unpauseForNewRequests();
 
     return OK;
@@ -2064,28 +2048,43 @@
 }
 
 status_t Camera3Device::RequestThread::setRepeatingRequests(
-        const RequestList &requests) {
+        const RequestList &requests,
+        /*out*/
+        int64_t *lastFrameNumber) {
     Mutex::Autolock l(mRequestLock);
+    if (lastFrameNumber != NULL) {
+        *lastFrameNumber = mRepeatingLastFrameNumber;
+    }
     mRepeatingRequests.clear();
     mRepeatingRequests.insert(mRepeatingRequests.begin(),
             requests.begin(), requests.end());
 
     unpauseForNewRequests();
 
+    mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
     return OK;
 }
 
-status_t Camera3Device::RequestThread::clearRepeatingRequests() {
+status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
     Mutex::Autolock l(mRequestLock);
     mRepeatingRequests.clear();
+    if (lastFrameNumber != NULL) {
+        *lastFrameNumber = mRepeatingLastFrameNumber;
+    }
+    mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
     return OK;
 }
 
-status_t Camera3Device::RequestThread::clear() {
+status_t Camera3Device::RequestThread::clear(/*out*/int64_t *lastFrameNumber) {
     Mutex::Autolock l(mRequestLock);
+    ALOGV("RequestThread::%s:", __FUNCTION__);
     mRepeatingRequests.clear();
     mRequestQueue.clear();
     mTriggerMap.clear();
+    if (lastFrameNumber != NULL) {
+        *lastFrameNumber = mRepeatingLastFrameNumber;
+    }
+    mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;
     return OK;
 }
 
@@ -2137,6 +2136,7 @@
 
     // Create request to HAL
     camera3_capture_request_t request = camera3_capture_request_t();
+    request.frame_number = nextRequest->mResultExtras.frameNumber;
     Vector<camera3_stream_buffer_t> outputBuffers;
 
     // Get the request ID, if any
@@ -2157,7 +2157,7 @@
     if (res < 0) {
         SET_ERR("RequestThread: Unable to insert triggers "
                 "(capture request %d, HAL device: %s (%d)",
-                (mFrameNumber+1), strerror(-res), res);
+                request.frame_number, strerror(-res), res);
         cleanUpFailedRequest(request, nextRequest, outputBuffers);
         return false;
     }
@@ -2175,7 +2175,7 @@
         if (res != OK) {
             SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
                     "(capture request %d, HAL device: %s (%d)",
-                    (mFrameNumber+1), strerror(-res), res);
+                    request.frame_number, strerror(-res), res);
             cleanUpFailedRequest(request, nextRequest, outputBuffers);
             return false;
         }
@@ -2199,7 +2199,7 @@
             if (e.count > 0) {
                 ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
                       __FUNCTION__,
-                      mFrameNumber+1,
+                      request.frame_number,
                       e.data.u8[0]);
             }
         }
@@ -2241,8 +2241,6 @@
         request.num_output_buffers++;
     }
 
-    request.frame_number = mFrameNumber++;
-
     // Log request in the in-flight queue
     sp<Camera3Device> parent = mParent.promote();
     if (parent == NULL) {
@@ -2251,8 +2249,13 @@
         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 = %" PRId32 ", frameNumber = %" PRId64
+           ", burstId = %" PRId32 ".",
+            __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 +2332,7 @@
     return mLatestRequest;
 }
 
+
 void Camera3Device::RequestThread::cleanUpFailedRequest(
         camera3_capture_request_t &request,
         sp<CaptureRequest> &nextRequest,
@@ -2370,6 +2374,9 @@
                     ++firstRequest,
                     requests.end());
             // No need to wait any longer
+
+            mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
+
             break;
         }
 
@@ -2421,6 +2428,9 @@
         mReconfigured = false;
     }
 
+    if (nextRequest != NULL) {
+        nextRequest->mResultExtras.frameNumber = mFrameNumber++;
+    }
     return nextRequest;
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ed58246..3ef39f3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -24,6 +24,8 @@
 #include <utils/Thread.h>
 #include <utils/KeyedVector.h>
 #include <hardware/camera3.h>
+#include <camera/CaptureResult.h>
+#include <camera/camera2/ICameraDeviceUser.h>
 
 #include "common/CameraDeviceBase.h"
 #include "device3/StatusTracker.h"
@@ -78,11 +80,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 +123,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 +132,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 +205,7 @@
         sp<camera3::Camera3Stream>          mInputStream;
         Vector<sp<camera3::Camera3OutputStreamInterface> >
                                             mOutputStreams;
+        CaptureResultExtras                 mResultExtras;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -207,9 +213,11 @@
 
     status_t convertMetadataListToRequestListLocked(
             const List<const CameraMetadata> &metadataList,
-            /*out*/RequestList *requestList);
+            /*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.
@@ -324,17 +332,21 @@
          * on either. Use waitUntilPaused to wait until request queue
          * has emptied out.
          */
-        status_t setRepeatingRequests(const RequestList& requests);
-        status_t clearRepeatingRequests();
+        status_t setRepeatingRequests(const RequestList& requests,
+                                      /*out*/
+                                      int64_t *lastFrameNumber = NULL);
+        status_t clearRepeatingRequests(/*out*/
+                                        int64_t *lastFrameNumber = NULL);
 
-        status_t queueRequest(sp<CaptureRequest> request);
-
-        status_t queueRequestList(List<sp<CaptureRequest> > &requests);
+        status_t queueRequestList(List<sp<CaptureRequest> > &requests,
+                                  /*out*/
+                                  int64_t *lastFrameNumber = NULL);
 
         /**
          * Remove all queued and repeating requests, and pending triggers
          */
-        status_t clear();
+        status_t clear(/*out*/
+                       int64_t *lastFrameNumber = NULL);
 
         /**
          * Queue a trigger to be dispatched with the next outgoing
@@ -447,6 +459,8 @@
         TriggerMap         mTriggerMap;
         TriggerMap         mTriggerRemovedMap;
         TriggerMap         mTriggerReplacedMap;
+
+        int64_t            mRepeatingLastFrameNumber;
     };
     sp<RequestThread> mRequestThread;
 
@@ -455,8 +469,6 @@
      */
 
     struct InFlightRequest {
-        // android.request.id for the request
-        int     requestId;
         // Set by notify() SHUTTER call.
         nsecs_t captureTimestamp;
         int     requestStatus;
@@ -465,6 +477,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 +493,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 +520,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 +555,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..50a2c10 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -34,7 +34,8 @@
         Camera3Stream(id, type,
                 width, height, maxSize, format),
         mTotalBufferCount(0),
-        mDequeuedBufferCount(0),
+        mHandoutTotalBufferCount(0),
+        mHandoutOutputBufferCount(0),
         mFrameCount(0),
         mLastTimestamp(0) {
 
@@ -55,8 +56,8 @@
     nsecs_t signalTime = mCombinedFence->getSignalTime();
     ALOGV("%s: Stream %d: Has %zu outstanding buffers,"
             " buffer signal time is %" PRId64,
-            __FUNCTION__, mId, mDequeuedBufferCount, signalTime);
-    if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) {
+            __FUNCTION__, mId, mHandoutTotalBufferCount, signalTime);
+    if (mHandoutTotalBufferCount > 0 || signalTime == INT64_MAX) {
         return true;
     }
     return false;
@@ -75,7 +76,7 @@
     lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
             mFrameCount, mLastTimestamp);
     lines.appendFormat("      Total buffers: %zu, currently dequeued: %zu\n",
-            mTotalBufferCount, mDequeuedBufferCount);
+            mTotalBufferCount, mHandoutTotalBufferCount);
     write(fd, lines.string(), lines.size());
 }
 
@@ -104,6 +105,14 @@
     return mTotalBufferCount;
 }
 
+size_t Camera3IOStreamBase::getHandoutOutputBufferCountLocked() {
+    return mHandoutOutputBufferCount;
+}
+
+size_t Camera3IOStreamBase::getHandoutInputBufferCountLocked() {
+    return (mHandoutTotalBufferCount - mHandoutOutputBufferCount);
+}
+
 status_t Camera3IOStreamBase::disconnectLocked() {
     switch (mState) {
         case STATE_IN_RECONFIG:
@@ -117,9 +126,9 @@
             return -ENOTCONN;
     }
 
-    if (mDequeuedBufferCount > 0) {
+    if (mHandoutTotalBufferCount > 0) {
         ALOGE("%s: Can't disconnect with %zu buffers still dequeued!",
-                __FUNCTION__, mDequeuedBufferCount);
+                __FUNCTION__, mHandoutTotalBufferCount);
         return INVALID_OPERATION;
     }
 
@@ -130,7 +139,8 @@
                                               buffer_handle_t *handle,
                                               int acquireFence,
                                               int releaseFence,
-                                              camera3_buffer_status_t status) {
+                                              camera3_buffer_status_t status,
+                                              bool output) {
     /**
      * Note that all fences are now owned by HAL.
      */
@@ -144,14 +154,25 @@
     buffer.status = status;
 
     // Inform tracker about becoming busy
-    if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
+    if (mHandoutTotalBufferCount == 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);
         }
     }
-    mDequeuedBufferCount++;
+    mHandoutTotalBufferCount++;
+
+    if (output) {
+        mHandoutOutputBufferCount++;
+    }
 }
 
 status_t Camera3IOStreamBase::getBufferPreconditionCheckLocked() const {
@@ -165,7 +186,7 @@
 
     // Only limit dequeue amount when fully configured
     if (mState == STATE_CONFIGURED &&
-            mDequeuedBufferCount == camera3_stream::max_buffers) {
+            mHandoutTotalBufferCount == camera3_stream::max_buffers) {
         ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
                 " buffers (%d)", __FUNCTION__, mId,
                 camera3_stream::max_buffers);
@@ -183,7 +204,7 @@
                 __FUNCTION__, mId, mState);
         return INVALID_OPERATION;
     }
-    if (mDequeuedBufferCount == 0) {
+    if (mHandoutTotalBufferCount == 0) {
         ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
                 mId);
         return INVALID_OPERATION;
@@ -221,9 +242,20 @@
         mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
     }
 
-    mDequeuedBufferCount--;
-    if (mDequeuedBufferCount == 0 && mState != STATE_IN_CONFIG &&
+    if (output) {
+        mHandoutOutputBufferCount--;
+    }
+
+    mHandoutTotalBufferCount--;
+    if (mHandoutTotalBufferCount == 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/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index fcb9d04..a35c290 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -48,7 +48,10 @@
   protected:
     size_t            mTotalBufferCount;
     // sum of input and output buffers that are currently acquired by HAL
-    size_t            mDequeuedBufferCount;
+    size_t            mHandoutTotalBufferCount;
+    // number of output buffers that are currently acquired by HAL. This will be
+    // Redundant when camera3 streams are no longer bidirectional streams.
+    size_t            mHandoutOutputBufferCount;
     Condition         mBufferReturnedSignal;
     uint32_t          mFrameCount;
     // Last received output buffer's timestamp
@@ -76,6 +79,10 @@
 
     virtual size_t   getBufferCountLocked();
 
+    virtual size_t   getHandoutOutputBufferCountLocked();
+
+    virtual size_t   getHandoutInputBufferCountLocked();
+
     virtual status_t getEndpointUsage(uint32_t *usage) = 0;
 
     status_t getBufferPreconditionCheckLocked() const;
@@ -92,7 +99,8 @@
                              buffer_handle_t *handle,
                              int acquire_fence,
                              int release_fence,
-                             camera3_buffer_status_t status);
+                             camera3_buffer_status_t status,
+                             bool output);
 
 }; // class Camera3IOStreamBase
 
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index dd7fb6c..319be1d 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -81,7 +81,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
     mBuffersInFlight.push_back(bufferItem);
 
     return OK;
@@ -199,7 +199,7 @@
     assert(mMaxSize == 0);
     assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB);
 
-    mDequeuedBufferCount = 0;
+    mHandoutTotalBufferCount = 0;
     mFrameCount = 0;
 
     if (mConsumer.get() == 0) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 682755d..7ec649b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -119,7 +119,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+                        /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
 
     return OK;
 }
@@ -324,7 +324,7 @@
     }
 
     mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
-    mDequeuedBufferCount = 0;
+    mHandoutTotalBufferCount = 0;
     mFrameCount = 0;
     mLastTimestamp = 0;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 70406f1..abfb602 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;
     }
 
@@ -209,8 +212,30 @@
 status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
+    status_t res = OK;
 
-    status_t res = getBufferLocked(buffer);
+    // This function should be only called when the stream is configured already.
+    if (mState != STATE_CONFIGURED) {
+        ALOGE("%s: Stream %d: Can't get buffers if stream is not in CONFIGURED state %d",
+                __FUNCTION__, mId, mState);
+        return INVALID_OPERATION;
+    }
+
+    // Wait for new buffer returned back if we are running into the limit.
+    if (getHandoutOutputBufferCountLocked() == camera3_stream::max_buffers) {
+        ALOGV("%s: Already dequeued max output buffers (%d), wait for next returned one.",
+                __FUNCTION__, camera3_stream::max_buffers);
+        res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
+        if (res != OK) {
+            if (res == TIMED_OUT) {
+                ALOGE("%s: wait for output buffer return timed out after %lldms", __FUNCTION__,
+                        kWaitForBufferDuration / 1000000LL);
+            }
+            return res;
+        }
+    }
+
+    res = getBufferLocked(buffer);
     if (res == OK) {
         fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
     }
@@ -223,9 +248,18 @@
     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);
+        mOutputBufferReturnedSignal.signal();
     }
 
     return res;
@@ -234,8 +268,30 @@
 status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer) {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
+    status_t res = OK;
 
-    status_t res = getInputBufferLocked(buffer);
+    // This function should be only called when the stream is configured already.
+    if (mState != STATE_CONFIGURED) {
+        ALOGE("%s: Stream %d: Can't get input buffers if stream is not in CONFIGURED state %d",
+                __FUNCTION__, mId, mState);
+        return INVALID_OPERATION;
+    }
+
+    // Wait for new buffer returned back if we are running into the limit.
+    if (getHandoutInputBufferCountLocked() == camera3_stream::max_buffers) {
+        ALOGV("%s: Already dequeued max input buffers (%d), wait for next returned one.",
+                __FUNCTION__, camera3_stream::max_buffers);
+        res = mInputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
+        if (res != OK) {
+            if (res == TIMED_OUT) {
+                ALOGE("%s: wait for input buffer return timed out after %lldms", __FUNCTION__,
+                        kWaitForBufferDuration / 1000000LL);
+            }
+            return res;
+        }
+    }
+
+    res = getInputBufferLocked(buffer);
     if (res == OK) {
         fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
     }
@@ -250,6 +306,7 @@
     status_t res = returnInputBufferLocked(buffer);
     if (res == OK) {
         fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false);
+        mInputBufferReturnedSignal.signal();
     }
     return res;
 }
@@ -314,12 +371,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 +418,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..14f5387 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,
@@ -262,6 +279,12 @@
     // Get the total number of buffers in the queue
     virtual size_t   getBufferCountLocked() = 0;
 
+    // Get handout output buffer count.
+    virtual size_t   getHandoutOutputBufferCountLocked() = 0;
+
+    // Get handout input buffer count.
+    virtual size_t   getHandoutInputBufferCountLocked() = 0;
+
     // Get the usage flags for the other endpoint, or return
     // INVALID_OPERATION if they cannot be obtained.
     virtual status_t getEndpointUsage(uint32_t *usage) = 0;
@@ -274,6 +297,9 @@
   private:
     uint32_t oldUsage;
     uint32_t oldMaxBuffers;
+    Condition mOutputBufferReturnedSignal;
+    Condition mInputBufferReturnedSignal;
+    static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms
 
     // Gets all buffers from endpoint and registers them with the HAL.
     status_t registerBuffersLocked(camera3_device *hal3Device);
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
index 09e14c5..05b3d1f 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
@@ -176,7 +176,7 @@
      * in which case we reassign it to acquire_fence
      */
     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
-                         /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK);
+                         /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/false);
 
     mBuffersInFlight.push_back(bufferItem);