Merge "NuPlayer: disable pre-start preview for audio only sources" into mnc-dev
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 7bb24ee..7c9720f 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -285,6 +285,7 @@
         }
 
         Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
 
         data.writeInt32(cameraId);
         remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply);
@@ -304,6 +305,7 @@
     virtual status_t supportsCameraApi(int cameraId, int apiVersion) {
         Parcel data, reply;
 
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeInt32(cameraId);
         data.writeInt32(apiVersion);
         remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply);
@@ -315,6 +317,7 @@
 
     virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
         Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeInt32(eventId);
         data.writeInt32Array(len, args);
         remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index 90a8bc2..0010325 100644
--- a/camera/ICameraServiceListener.cpp
+++ b/camera/ICameraServiceListener.cpp
@@ -45,8 +45,7 @@
     virtual void onStatusChanged(Status status, int32_t cameraId)
     {
         Parcel data, reply;
-        data.writeInterfaceToken(
-                              ICameraServiceListener::getInterfaceDescriptor());
+        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
 
         data.writeInt32(static_cast<int32_t>(status));
         data.writeInt32(cameraId);
@@ -60,8 +59,7 @@
     virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
     {
         Parcel data, reply;
-        data.writeInterfaceToken(
-                              ICameraServiceListener::getInterfaceDescriptor());
+        data.writeInterfaceToken(ICameraServiceListener::getInterfaceDescriptor());
 
         data.writeInt32(static_cast<int32_t>(status));
         data.writeString16(cameraId);
@@ -73,14 +71,12 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(CameraServiceListener,
-                         "android.hardware.ICameraServiceListener");
+IMPLEMENT_META_INTERFACE(CameraServiceListener, "android.hardware.ICameraServiceListener");
 
 // ----------------------------------------------------------------------
 
-status_t BnCameraServiceListener::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
+status_t BnCameraServiceListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags) {
     switch(code) {
         case STATUS_CHANGED: {
             CHECK_INTERFACE(ICameraServiceListener, data, reply);
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index a7549f2..ffe974b 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -82,7 +82,7 @@
         reply.readExceptionCode();
     }
 
-    virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
+    virtual int submitRequest(sp<CaptureRequest> request, bool repeating,
                               int64_t *lastFrameNumber)
     {
         Parcel data, reply;
@@ -111,13 +111,13 @@
             }
         }
 
-	if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+        if (res < 0 || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
     }
 
-    virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
+    virtual int submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
                                   int64_t *lastFrameNumber)
     {
         Parcel data, reply;
@@ -151,7 +151,7 @@
                 resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
-        if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+        if (res < 0 || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 24acaa0..20a23e0 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -65,6 +65,11 @@
           gbp.get(), String8(name).string());
 }
 
+OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation) {
+    mGbp = gbp;
+    mRotation = rotation;
+}
+
 status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
 
     parcel.writeInt32(mRotation);
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 5d37f9e..3777d94 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -17,7 +17,8 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_SRC_FILES:= \
-	VendorTagDescriptorTests.cpp
+	VendorTagDescriptorTests.cpp \
+	CameraBinderTests.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
new file mode 100644
index 0000000..572fb72
--- /dev/null
+++ b/camera/tests/CameraBinderTests.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2015 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_NDEBUG 0
+#define LOG_TAG "CameraBinderTests"
+
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <system/graphics.h>
+#include <hardware/gralloc.h>
+
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/ICameraServiceListener.h>
+#include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <utility>
+#include <vector>
+#include <map>
+#include <algorithm>
+
+using namespace android;
+
+#define ASSERT_NOT_NULL(x) \
+    ASSERT_TRUE((x) != nullptr)
+
+#define SETUP_TIMEOUT 2000000000 // ns
+#define IDLE_TIMEOUT 2000000000 // ns
+
+// Stub listener implementation
+class TestCameraServiceListener : public BnCameraServiceListener {
+    std::map<String16, TorchStatus> mCameraTorchStatuses;
+    std::map<int32_t, Status> mCameraStatuses;
+    mutable Mutex mLock;
+    mutable Condition mCondition;
+    mutable Condition mTorchCondition;
+public:
+    virtual ~TestCameraServiceListener() {};
+
+    virtual void onStatusChanged(Status status, int32_t cameraId) {
+        Mutex::Autolock l(mLock);
+        mCameraStatuses[cameraId] = status;
+        mCondition.broadcast();
+    };
+
+    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+        Mutex::Autolock l(mLock);
+        mCameraTorchStatuses[cameraId] = status;
+        mTorchCondition.broadcast();
+    };
+
+    bool waitForNumCameras(size_t num) const {
+        Mutex::Autolock l(mLock);
+
+        if (mCameraStatuses.size() == num) {
+            return true;
+        }
+
+        while (mCameraStatuses.size() < num) {
+            if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+                return false;
+            }
+        }
+        return true;
+    };
+
+    bool waitForTorchState(TorchStatus status, int32_t cameraId) const {
+        Mutex::Autolock l(mLock);
+
+        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+        if (iter != mCameraTorchStatuses.end() && iter->second == status) {
+            return true;
+        }
+
+        bool foundStatus = false;
+        while (!foundStatus) {
+            if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
+                return false;
+            }
+            const auto& iter =
+                    mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+            foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
+        }
+        return true;
+    };
+
+    TorchStatus getTorchStatus(int32_t cameraId) const {
+        Mutex::Autolock l(mLock);
+        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+        if (iter == mCameraTorchStatuses.end()) {
+            return ICameraServiceListener::TORCH_STATUS_UNKNOWN;
+        }
+        return iter->second;
+    };
+
+    Status getStatus(int32_t cameraId) const {
+        Mutex::Autolock l(mLock);
+        const auto& iter = mCameraStatuses.find(cameraId);
+        if (iter == mCameraStatuses.end()) {
+            return ICameraServiceListener::STATUS_UNKNOWN;
+        }
+        return iter->second;
+    };
+};
+
+// Callback implementation
+class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks {
+public:
+    enum Status {
+        IDLE,
+        ERROR,
+        PREPARED,
+        RUNNING,
+        SENT_RESULT,
+        UNINITIALIZED
+    };
+
+protected:
+    bool mError;
+    Status mLastStatus;
+    mutable std::vector<Status> mStatusesHit;
+    mutable Mutex mLock;
+    mutable Condition mStatusCondition;
+public:
+    TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {}
+
+    virtual ~TestCameraDeviceCallbacks() {}
+
+    virtual void onDeviceError(CameraErrorCode errorCode,
+            const CaptureResultExtras& resultExtras) {
+        ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode));
+        Mutex::Autolock l(mLock);
+        mError = true;
+        mLastStatus = ERROR;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+    }
+
+    virtual void onDeviceIdle() {
+        Mutex::Autolock l(mLock);
+        mLastStatus = IDLE;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+    }
+
+    virtual void onCaptureStarted(const CaptureResultExtras& resultExtras,
+            int64_t timestamp) {
+        Mutex::Autolock l(mLock);
+        mLastStatus = RUNNING;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+    }
+
+
+    virtual void onResultReceived(const CameraMetadata& metadata,
+            const CaptureResultExtras& resultExtras) {
+        Mutex::Autolock l(mLock);
+        mLastStatus = SENT_RESULT;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+    }
+
+    virtual void onPrepared(int streamId) {
+        Mutex::Autolock l(mLock);
+        mLastStatus = PREPARED;
+        mStatusesHit.push_back(mLastStatus);
+        mStatusCondition.broadcast();
+    }
+
+    // Test helper functions:
+
+    bool hadError() const {
+        Mutex::Autolock l(mLock);
+        return mError;
+    }
+
+    bool waitForStatus(Status status) const {
+        Mutex::Autolock l(mLock);
+        if (mLastStatus == status) {
+            return true;
+        }
+
+        while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status)
+                == mStatusesHit.end()) {
+
+            if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) {
+                mStatusesHit.clear();
+                return false;
+            }
+        }
+        mStatusesHit.clear();
+
+        return true;
+
+    }
+
+    void clearStatus() const {
+        Mutex::Autolock l(mLock);
+        mStatusesHit.clear();
+    }
+
+    bool waitForIdle() const {
+        return waitForStatus(IDLE);
+    }
+
+};
+
+// Exercise basic binder calls for the camera service
+TEST(CameraServiceBinderTest, CheckBinderCameraService) {
+    ProcessState::self()->startThreadPool();
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("media.camera"));
+    ASSERT_NOT_NULL(binder);
+    sp<ICameraService> service = interface_cast<ICameraService>(binder);
+
+
+    int32_t numCameras = service->getNumberOfCameras();
+    EXPECT_LE(0, numCameras);
+
+    // Check listener binder calls
+    sp<TestCameraServiceListener> listener(new TestCameraServiceListener());
+    EXPECT_EQ(OK, service->addListener(listener));
+
+    EXPECT_TRUE(listener->waitForNumCameras(numCameras));
+
+    for (int32_t i = 0; i < numCameras; i++) {
+        // We only care about binder calls for the Camera2 API.  Camera1 is deprecated.
+        status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2);
+        if (camera2Support != OK) {
+            EXPECT_EQ(-EOPNOTSUPP, camera2Support);
+            continue;
+        }
+
+        // Check metadata binder call
+        CameraMetadata metadata;
+        EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata));
+        EXPECT_FALSE(metadata.isEmpty());
+
+        // Make sure we're available, or skip device tests otherwise
+        ICameraServiceListener::Status s = listener->getStatus(i);
+        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+            continue;
+        }
+
+        // Check connect binder calls
+        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+        sp<ICameraDeviceUser> device;
+        EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
+                ICameraService::USE_CALLING_UID, /*out*/device));
+        ASSERT_NE(nullptr, device.get());
+        device->disconnect();
+        EXPECT_FALSE(callbacks->hadError());
+
+        ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i);
+        if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
+            // Check torch calls
+            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+                    /*enabled*/true, callbacks));
+            EXPECT_TRUE(listener->waitForTorchState(
+                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
+            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
+                    /*enabled*/false, callbacks));
+            EXPECT_TRUE(listener->waitForTorchState(
+                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
+        }
+    }
+
+    EXPECT_EQ(OK, service->removeListener(listener));
+}
+
+// Test fixture for client focused binder tests
+class CameraClientBinderTest : public testing::Test {
+protected:
+    sp<ICameraService> service;
+    int32_t numCameras;
+    std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList;
+    sp<TestCameraServiceListener> serviceListener;
+
+    std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) {
+
+        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
+        sp<ICameraDeviceUser> device;
+        {
+            SCOPED_TRACE("openNewDevice");
+            EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
+                    ICameraService::USE_CALLING_UID, /*out*/device));
+        }
+        auto p = std::make_pair(callbacks, device);
+        openDeviceList.push_back(p);
+        return p;
+    }
+
+    void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) {
+        if (p.second.get() != nullptr) {
+            p.second->disconnect();
+            {
+                SCOPED_TRACE("closeDevice");
+                EXPECT_FALSE(p.first->hadError());
+            }
+        }
+        auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p);
+        if (iter != openDeviceList.end()) {
+            openDeviceList.erase(iter);
+        }
+    }
+
+    virtual void SetUp() {
+        ProcessState::self()->startThreadPool();
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->getService(String16("media.camera"));
+        service = interface_cast<ICameraService>(binder);
+        serviceListener = new TestCameraServiceListener();
+        service->addListener(serviceListener);
+        numCameras = service->getNumberOfCameras();
+    }
+
+    virtual void TearDown() {
+        service = nullptr;
+        numCameras = 0;
+        for (auto& p : openDeviceList) {
+            closeDevice(p);
+        }
+    }
+
+};
+
+TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
+    ASSERT_NOT_NULL(service);
+
+    EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
+    for (int32_t i = 0; i < numCameras; i++) {
+        // Make sure we're available, or skip device tests otherwise
+        ICameraServiceListener::Status s = serviceListener->getStatus(i);
+        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
+        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
+            continue;
+        }
+
+        auto p = openNewDevice(i);
+        sp<TestCameraDeviceCallbacks> callbacks = p.first;
+        sp<ICameraDeviceUser> device = p.second;
+
+        // Setup a buffer queue; I'm just using the vendor opaque format here as that is
+        // guaranteed to be present
+        sp<IGraphicBufferProducer> gbProducer;
+        sp<IGraphicBufferConsumer> gbConsumer;
+        BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+        sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer,
+                GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true);
+        EXPECT_TRUE(opaqueConsumer.get() != nullptr);
+        opaqueConsumer->setName(String8("nom nom nom"));
+
+        // Set to VGA dimens for default, as that is guaranteed to be present
+        EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480));
+        EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
+
+        sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
+
+        OutputConfiguration output(gbProducer, /*rotation*/0);
+
+        // Can we configure?
+        EXPECT_EQ(OK, device->beginConfigure());
+        status_t streamId = device->createStream(output);
+        EXPECT_LE(0, streamId);
+        EXPECT_EQ(OK, device->endConfigure());
+        EXPECT_FALSE(callbacks->hadError());
+
+        // Can we make requests?
+        CameraMetadata requestTemplate;
+        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+                /*out*/&requestTemplate));
+        sp<CaptureRequest> request(new CaptureRequest());
+        request->mMetadata = requestTemplate;
+        request->mSurfaceList.add(surface);
+        request->mIsReprocess = false;
+        int64_t lastFrameNumber = 0;
+        int64_t lastFrameNumberPrev = 0;
+        callbacks->clearStatus();
+        int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber);
+        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+        EXPECT_LE(0, requestId);
+
+        // Can we stop requests?
+        EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber));
+        EXPECT_TRUE(callbacks->waitForIdle());
+        EXPECT_FALSE(callbacks->hadError());
+
+        // Can we do it again?
+        lastFrameNumberPrev = lastFrameNumber;
+        lastFrameNumber = 0;
+        requestTemplate.clear();
+        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+                /*out*/&requestTemplate));
+        sp<CaptureRequest> request2(new CaptureRequest());
+        request2->mMetadata = requestTemplate;
+        request2->mSurfaceList.add(surface);
+        request2->mIsReprocess = false;
+        callbacks->clearStatus();
+        int requestId2 = device->submitRequest(request2, /*streaming*/true,
+                /*out*/&lastFrameNumber);
+        EXPECT_EQ(-1, lastFrameNumber);
+        lastFrameNumber = 0;
+        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+        EXPECT_LE(0, requestId2);
+        EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber));
+        EXPECT_TRUE(callbacks->waitForIdle());
+        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+        sleep(/*second*/1); // allow some time for errors to show up, if any
+        EXPECT_FALSE(callbacks->hadError());
+
+        // Can we do it with a request list?
+        lastFrameNumberPrev = lastFrameNumber;
+        lastFrameNumber = 0;
+        requestTemplate.clear();
+        CameraMetadata requestTemplate2;
+        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+                /*out*/&requestTemplate));
+        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
+                /*out*/&requestTemplate2));
+        sp<CaptureRequest> request3(new CaptureRequest());
+        sp<CaptureRequest> request4(new CaptureRequest());
+        request3->mMetadata = requestTemplate;
+        request3->mSurfaceList.add(surface);
+        request3->mIsReprocess = false;
+        request4->mMetadata = requestTemplate2;
+        request4->mSurfaceList.add(surface);
+        request4->mIsReprocess = false;
+        List<sp<CaptureRequest>> requestList;
+        requestList.push_back(request3);
+        requestList.push_back(request4);
+
+        callbacks->clearStatus();
+        int requestId3 = device->submitRequestList(requestList, /*streaming*/false,
+                /*out*/&lastFrameNumber);
+        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
+        EXPECT_TRUE(callbacks->waitForIdle());
+        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
+        sleep(/*second*/1); // allow some time for errors to show up, if any
+        EXPECT_FALSE(callbacks->hadError());
+
+        // Can we unconfigure?
+        EXPECT_EQ(OK, device->beginConfigure());
+        EXPECT_EQ(OK, device->deleteStream(streamId));
+        EXPECT_EQ(OK, device->endConfigure());
+        sleep(/*second*/1); // allow some time for errors to show up, if any
+        EXPECT_FALSE(callbacks->hadError());
+
+        closeDevice(p);
+    }
+
+};
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 6624e79..9082dbf 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -53,6 +53,10 @@
 
 extern "C" {
 
+static int zero_get_tag_count(const vendor_tag_ops_t* vOps) {
+    return 0;
+}
+
 static int default_get_tag_count(const vendor_tag_ops_t* vOps) {
     return VENDOR_TAG_COUNT_ERR;
 }
@@ -173,10 +177,13 @@
     vendor_tag_ops_t vOps;
     FillWithDefaults(&vOps);
 
+    // Make empty tag count
+    vOps.get_tag_count = zero_get_tag_count;
+
     // Ensure create fails when using null vOps
     EXPECT_EQ(BAD_VALUE, VendorTagDescriptor::createDescriptorFromOps(/*vOps*/NULL, vDesc));
 
-    // Ensure create works when there are no vtags defined in a well-formed vOps
+    // Ensure creat succeeds for empty vendor tag ops
     ASSERT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc));
 
     // Ensure defaults are returned when no vtags are defined, or tag is unknown
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
index e6b679f..5bcbe15 100644
--- a/include/camera/camera2/OutputConfiguration.h
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -39,6 +39,8 @@
     // getRotation will be INVALID_ROTATION if error occurred
     OutputConfiguration(const Parcel& parcel);
 
+    OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation);
+
 private:
     sp<IGraphicBufferProducer> mGbp;
     int                        mRotation;
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index a991b02..71f58a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -108,6 +108,9 @@
     bool mStarted;
     bool mStopping;
     bool mDoMoreWorkPending;
+    bool mSetEncoderFormat;
+    int mEncoderFormat;
+    int mEncoderDataSpace;
     sp<AMessage> mEncoderActivityNotify;
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
     sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index ca80123..726b197 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -70,7 +70,9 @@
     kKeyDriftTime         = 'dftT',  // int64_t (usecs)
     kKeyAnchorTime        = 'ancT',  // int64_t (usecs)
     kKeyDuration          = 'dura',  // int64_t (usecs)
-    kKeyColorFormat       = 'colf',
+    kKeyPixelFormat       = 'pixf',  // int32_t
+    kKeyColorFormat       = 'colf',  // int32_t
+    kKeyColorSpace        = 'cols',  // int32_t
     kKeyPlatformPrivate   = 'priv',  // pointer
     kKeyDecoderComponent  = 'decC',  // cstring
     kKeyBufferID          = 'bfID',
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index bb53ce6..7452e4b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1639,6 +1639,14 @@
         if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
             mInputMetadataType = kMetadataBufferTypeCameraSource;
         }
+
+        uint32_t usageBits;
+        if (mOMX->getParameter(
+                mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+                &usageBits, sizeof(usageBits)) == OK) {
+            inputFormat->setInt32(
+                    "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+        }
     }
 
     int32_t prependSPSPPS = 0;
@@ -5234,6 +5242,7 @@
         if (err == OK) {
             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
         } else {
+            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
             mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
             info->mStatus = BufferInfo::OWNED_BY_US;
             // keeping read fence as write fence to avoid clobbering
@@ -5748,6 +5757,14 @@
         }
     }
 
+    uint32_t usageBits;
+    if (mCodec->mOMX->getParameter(
+            mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+            &usageBits, sizeof(usageBits)) == OK) {
+        mCodec->mInputFormat->setInt32(
+                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 2606e44..bc34bcf 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -670,9 +670,13 @@
             mNumInputBuffers = nBuffers;
         }
 
-        // TODO: Read in format/dataspace from somewhere
-        // Uncomment to test SW encoders until TODO is resolved
-        // mEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+        // apply encoder color format if specified
+        if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) {
+            ALOGV("Using encoder format: %#x", mEncoderFormat);
+        }
+        if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
+            ALOGV("Using encoder data space: %#x", mEncoderDataSpace);
+        }
     }
 
     status_t err;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b576cd9..69f44ed 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2528,7 +2528,25 @@
         err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
         if (err == BAD_VALUE) {
             ALOGI("native window already connected. Assuming no change of surface");
-        } else if (err != OK) {
+        } else if (err == OK) {
+            // Require a fresh set of buffers after each connect by using a unique generation
+            // number. Rely on the fact that max supported process id by Linux is 2^22.
+            // PID is never 0 so we don't have to worry that we use the default generation of 0.
+            // TODO: come up with a unique scheme if other producers also set the generation number.
+            static uint32_t mSurfaceGeneration = 0;
+            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
+            surface->setGenerationNumber(generation);
+            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
+
+            // HACK: clear any free buffers. Remove when connect will automatically do this.
+            // This is needed as the consumer may be holding onto stale frames that it can reattach
+            // to this surface after disconnect/connect, and those free frames would inherit the new
+            // generation number. Disconnecting after setting a unique generation prevents this.
+            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+        }
+
+        if (err != OK) {
             ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
         }
     }
@@ -2538,6 +2556,8 @@
 status_t MediaCodec::disconnectFromSurface() {
     status_t err = OK;
     if (mSurface != NULL) {
+        // Resetting generation is not technically needed, but there is no need to keep it either
+        mSurface->setGenerationNumber(0);
         err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
         if (err != OK) {
             ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index ab49c11..7ea5cbd 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -175,6 +175,7 @@
       mUpdate(false),
       mGlobalSettings(new AMessage()) {
     parseTopLevelXMLFile("/etc/media_codecs.xml");
+    parseTopLevelXMLFile("/etc/media_codecs_performance.xml", true/* ignore_errors */);
     parseTopLevelXMLFile(kProfilingResults, true/* ignore_errors */);
 }
 
@@ -935,7 +936,7 @@
     if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
             || name == "blocks-per-second" || name == "complexity"
             || name == "frame-rate" || name == "quality" || name == "size"
-            || name == "measured-blocks-per-second" || name == "measured-frame-rate") {
+            || name == "measured-blocks-per-second" || name.startsWith("measured-frame-rate-")) {
         AString min, max;
         if (msg->findString("min", &min) && msg->findString("max", &max)) {
             min.append("-");
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index e089c46..7f9f824 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -39,6 +39,9 @@
 
 namespace android {
 
+const int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+const int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
+
 struct MediaCodecSource::Puller : public AHandler {
     Puller(const sp<MediaSource> &source);
 
@@ -341,6 +344,9 @@
       mStarted(false),
       mStopping(false),
       mDoMoreWorkPending(false),
+      mSetEncoderFormat(false),
+      mEncoderFormat(0),
+      mEncoderDataSpace(0),
       mGraphicBufferConsumer(consumer),
       mFirstSampleTimeUs(-1ll),
       mEncoderReachedEOS(false),
@@ -438,6 +444,18 @@
         }
     }
 
+    sp<AMessage> inputFormat;
+    int32_t usingSwReadOften;
+    mSetEncoderFormat = false;
+    if (mEncoder->getInputFormat(&inputFormat) == OK
+            && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
+            && usingSwReadOften) {
+        // this is a SW encoder; signal source to allocate SW readable buffers
+        mSetEncoderFormat = true;
+        mEncoderFormat = kDefaultSwVideoEncoderFormat;
+        mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace;
+    }
+
     err = mEncoder->start();
 
     if (err != OK) {
@@ -632,8 +650,17 @@
         resume(startTimeUs);
     } else {
         CHECK(mPuller != NULL);
+        sp<MetaData> meta = params;
+        if (mSetEncoderFormat) {
+            if (meta == NULL) {
+                meta = new MetaData;
+            }
+            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
+            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
+        }
+
         sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
-        err = mPuller->start(params, notify);
+        err = mPuller->start(meta.get(), notify);
         if (err != OK) {
             return err;
         }
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index b402e48..52077a7 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -558,7 +558,6 @@
             return;
         }
     }
-    ++mNumOutstandingBuffers;
 
     // Acquire and detach the buffer from the input.
     BufferItem bufferItem;
@@ -567,6 +566,7 @@
         ALOGE("acquiring buffer from input failed (%d)", status);
         return;
     }
+    ++mNumOutstandingBuffers;
 
     ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId());
 
@@ -608,6 +608,7 @@
 
     // Attach and queue the buffer to the output.
     int slot;
+    mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber());
     status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer);
     ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status);
     if (status == NO_ERROR) {
@@ -695,16 +696,13 @@
         ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status);
     }
 
-    if (status != NO_ERROR) {
-        // TODO: do we need to try to return this buffer later?
-        return;
-    }
-
-    ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
-
     // Notify any waiting onFrameAvailable calls.
     --mNumOutstandingBuffers;
     mReleaseCondition.signal();
+
+    if (status == NO_ERROR) {
+        ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
+    }
 }
 
 void MediaSync::onAbandoned_l(bool isInput) {
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 5396022..f743b1c 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -283,6 +283,11 @@
             } else {
                 // This is recoverable, just ignore the current frame and
                 // play silence instead.
+
+                // TODO: should we skip silence (and consume input data)
+                // if mIsFirst is true as we may not have a valid
+                // mConfig->samplingRate and mConfig->num_channels?
+                ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
                 memset(outHeader->pBuffer,
                        0,
                        mConfig->outputFrameSize * sizeof(int16_t));
@@ -317,8 +322,7 @@
         }
 
         outHeader->nTimeStamp =
-            mAnchorTimeUs
-                + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;
+            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
 
         if (inHeader) {
             CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 31c6975..1a7dc9d 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -23,6 +23,7 @@
 #include "GraphicBufferSource.h"
 
 #include <OMX_Core.h>
+#include <OMX_IndexExt.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
@@ -110,6 +111,7 @@
         uint32_t bufferWidth,
         uint32_t bufferHeight,
         uint32_t bufferCount,
+        uint32_t consumerUsage,
         const sp<IGraphicBufferConsumer> &consumer) :
     mInitCheck(UNKNOWN_ERROR),
     mNodeInstance(nodeInstance),
@@ -152,7 +154,12 @@
 
         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
         mConsumer->setConsumerName(name);
-        mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
+
+        // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
+        // for backward compatibility.
+        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+        mConsumer->setConsumerUsageBits(consumerUsage);
+
         mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
         if (mInitCheck != NO_ERROR) {
             ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
@@ -836,13 +843,15 @@
         mConsumer->detachBuffer(id);
         mBufferSlot[id] = NULL;
 
-        mConsumer->attachBuffer(&id, buffer);
-        mConsumer->releaseBuffer(
-                id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+        if (mConsumer->attachBuffer(&id, buffer) == OK) {
+            mConsumer->releaseBuffer(
+                    id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+        }
     } else {
         mConsumer->releaseBuffer(
                 id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
     }
+    id = -1; // invalidate id
     mNumBufferAcquired--;
 }
 
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 3f64088..2f929d9 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -55,6 +55,7 @@
             uint32_t bufferWidth,
             uint32_t bufferHeight,
             uint32_t bufferCount,
+            uint32_t consumerUsage,
             const sp<IGraphicBufferConsumer> &consumer = NULL
     );
 
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 147aae7..9f1c5d8 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -834,7 +834,8 @@
     }
 
     CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
-            portString(portIndex), portIndex, buffer, graphicBuffer->handle);
+            portString(portIndex), portIndex, buffer,
+            graphicBuffer == NULL ? NULL : graphicBuffer->handle);
     return OK;
 }
 
@@ -885,10 +886,18 @@
         return INVALID_OPERATION;
     }
 
+    uint32_t usageBits;
+    oerr = OMX_GetParameter(
+            mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
+    if (oerr != OMX_ErrorNone) {
+        usageBits = 0;
+    }
+
     sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this,
             def.format.video.nFrameWidth,
             def.format.video.nFrameHeight,
             def.nBufferCountActual,
+            usageBits,
             bufferConsumer);
 
     if ((err = bufferSource->initCheck()) != OK) {
@@ -1607,7 +1616,12 @@
         return NULL;
     }
     Mutex::Autolock autoLock(mBufferIDLock);
-    return mBufferIDToBufferHeader.valueFor(buffer);
+    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
+    if (index < 0) {
+        CLOGW("findBufferHeader: buffer %u not found", buffer);
+        return NULL;
+    }
+    return mBufferIDToBufferHeader.valueAt(index);
 }
 
 OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) {
@@ -1615,7 +1629,12 @@
         return 0;
     }
     Mutex::Autolock autoLock(mBufferIDLock);
-    return mBufferHeaderToBufferID.valueFor(bufferHeader);
+    ssize_t index = mBufferHeaderToBufferID.indexOfKey(bufferHeader);
+    if (index < 0) {
+        CLOGW("findBufferID: bufferHeader %p not found", bufferHeader);
+        return 0;
+    }
+    return mBufferHeaderToBufferID.valueAt(index);
 }
 
 void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) {
@@ -1623,8 +1642,13 @@
         return;
     }
     Mutex::Autolock autoLock(mBufferIDLock);
-    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer));
-    mBufferIDToBufferHeader.removeItem(buffer);
+    ssize_t index = mBufferIDToBufferHeader.indexOfKey(buffer);
+    if (index < 0) {
+        CLOGW("invalidateBufferID: buffer %u not found", buffer);
+        return;
+    }
+    mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueAt(index));
+    mBufferIDToBufferHeader.removeItemsAt(index);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 9dd26fb..8ea7a6e 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -34,6 +34,8 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferMapper.h>
 
+#include <OMX_IndexExt.h>
+
 namespace android {
 
 const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
@@ -293,7 +295,7 @@
 
 OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR param) {
-    switch (index) {
+    switch ((int)index) {
         case OMX_IndexParamVideoErrorCorrection:
         {
             return OMX_ErrorNotImplemented;
@@ -343,6 +345,13 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamConsumerUsageBits:
+        {
+            OMX_U32 *usageBits = (OMX_U32 *)param;
+            *usageBits = GRALLOC_USAGE_SW_READ_OFTEN;
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalGetParameter(index, param);
     }
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 9248bba..f6078a2 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -481,22 +481,31 @@
     if (patch->mRecordThread != 0) {
         if (patch->mPatchRecord != 0) {
             patch->mRecordThread->deletePatchRecord(patch->mPatchRecord);
-            patch->mPatchRecord.clear();
         }
         audioflinger->closeInputInternal_l(patch->mRecordThread);
-        patch->mRecordThread.clear();
     }
     if (patch->mPlaybackThread != 0) {
         if (patch->mPatchTrack != 0) {
             patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack);
-            patch->mPatchTrack.clear();
         }
         // if num sources == 2 we are reusing an existing playback thread so we do not close it
         if (patch->mAudioPatch.num_sources != 2) {
             audioflinger->closeOutputInternal_l(patch->mPlaybackThread);
         }
+    }
+    if (patch->mRecordThread != 0) {
+        if (patch->mPatchRecord != 0) {
+            patch->mPatchRecord.clear();
+        }
+        patch->mRecordThread.clear();
+    }
+    if (patch->mPlaybackThread != 0) {
+        if (patch->mPatchTrack != 0) {
+            patch->mPatchTrack.clear();
+        }
         patch->mPlaybackThread.clear();
     }
+
 }
 
 /* Disconnect a patch */
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c8f9be0..d3ea9d8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -375,6 +375,7 @@
         AUDIO_DEVICE_OUT_FM,                "FM",
         AUDIO_DEVICE_OUT_AUX_LINE,          "AUX_LINE",
         AUDIO_DEVICE_OUT_SPEAKER_SAFE,      "SPEAKER_SAFE",
+        AUDIO_DEVICE_OUT_IP,                "IP",
         AUDIO_DEVICE_NONE,                  "NONE",         // must be last
     }, mappingsIn[] = {
         AUDIO_DEVICE_IN_COMMUNICATION,      "COMMUNICATION",
@@ -397,6 +398,7 @@
         AUDIO_DEVICE_IN_SPDIF,              "SPDIF",
         AUDIO_DEVICE_IN_BLUETOOTH_A2DP,     "BLUETOOTH_A2DP",
         AUDIO_DEVICE_IN_LOOPBACK,           "LOOPBACK",
+        AUDIO_DEVICE_IN_IP,                 "IP",
         AUDIO_DEVICE_NONE,                  "NONE",         // must be last
     };
     String8 result;
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index a39006e..78d2cdf 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -73,6 +73,7 @@
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -94,6 +95,7 @@
     STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_IP),
 };
 
 const StringToEnum sDeviceNameToEnumTable[] = {
@@ -124,6 +126,7 @@
     NAME_TO_ENUM("S/PDIF Out", AUDIO_DEVICE_OUT_SPDIF),
     NAME_TO_ENUM("FM transceiver Out", AUDIO_DEVICE_OUT_FM),
     NAME_TO_ENUM("Aux Line Out", AUDIO_DEVICE_OUT_AUX_LINE),
+    NAME_TO_ENUM("IP Out", AUDIO_DEVICE_OUT_IP),
     NAME_TO_ENUM("Ambient Mic", AUDIO_DEVICE_IN_AMBIENT),
     NAME_TO_ENUM("Built-In Mic", AUDIO_DEVICE_IN_BUILTIN_MIC),
     NAME_TO_ENUM("BT SCO Headset Mic", AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -145,6 +148,7 @@
     NAME_TO_ENUM("S/PDIF In", AUDIO_DEVICE_IN_SPDIF),
     NAME_TO_ENUM("BT A2DP In", AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
     NAME_TO_ENUM("Loopback In", AUDIO_DEVICE_IN_LOOPBACK),
+    NAME_TO_ENUM("IP In", AUDIO_DEVICE_IN_IP),
 };
 
 const StringToEnum sOutputFlagNameToEnumTable[] = {
@@ -156,11 +160,15 @@
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
 };
 
 const StringToEnum sInputFlagNameToEnumTable[] = {
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
     STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_RAW),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_SYNC),
 };
 
 const StringToEnum sFormatNameToEnumTable[] = {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ee25b71..6983b5c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -427,7 +427,7 @@
     /// Opens: can these line be executed after the switch of volume curves???
     // if leaving call state, handle special case of active streams
     // pertaining to sonification strategy see handleIncallSonification()
-    if (isInCall()) {
+    if (isStateInCall(oldState)) {
         ALOGV("setPhoneState() in call state management: new state is %d", state);
         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
             if (stream == AUDIO_STREAM_PATCH) {
@@ -436,7 +436,7 @@
             handleIncallSonification((audio_stream_type_t)stream, false, true);
         }
 
-        // force reevaluating accessibility routing when call starts
+        // force reevaluating accessibility routing when call stops
         mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
     }
 
@@ -514,6 +514,9 @@
             }
             handleIncallSonification((audio_stream_type_t)stream, true, true);
         }
+
+        // force reevaluating accessibility routing when call starts
+        mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
     }
 
     // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index fbe4f18..eefff3d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -930,6 +930,7 @@
                 patch2 = ((CreateAudioPatchData *)command2->mParam.get())->mPatch;
             } else {
                 handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle;
+                memset(&patch2, 0, sizeof(patch2));
             }
             if (handle != handle2) break;
             /* Filter CREATE_AUDIO_PATCH commands only when they are issued for
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f42fada..92df4e3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1292,7 +1292,7 @@
 status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {
     ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
 
-    if (listener == 0) {
+    if (listener == nullptr) {
         ALOGE("%s: Listener must not be null", __FUNCTION__);
         return BAD_VALUE;
     }
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index 85d4488..1ae01ae 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -154,6 +154,18 @@
     mCameraInfoMap.setCapacity(getNumberOfCameras());
 }
 
+CameraModule::~CameraModule()
+{
+    while (mCameraInfoMap.size() > 0) {
+        camera_info cameraInfo = mCameraInfoMap.editValueAt(0);
+        if (cameraInfo.static_camera_characteristics != NULL) {
+            free_camera_metadata(
+                    const_cast<camera_metadata_t*>(cameraInfo.static_camera_characteristics));
+        }
+        mCameraInfoMap.removeItemsAt(0);
+    }
+}
+
 int CameraModule::init() {
     if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
             mModule->init != NULL) {
@@ -192,12 +204,9 @@
         CameraMetadata m;
         m = rawInfo.static_camera_characteristics;
         deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
-        mCameraCharacteristicsMap.add(cameraId, m);
         cameraInfo = rawInfo;
-        cameraInfo.static_camera_characteristics =
-                mCameraCharacteristicsMap.valueFor(cameraId).getAndLock();
-        mCameraInfoMap.add(cameraId, cameraInfo);
-        index = mCameraInfoMap.indexOfKey(cameraId);
+        cameraInfo.static_camera_characteristics = m.release();
+        index = mCameraInfoMap.add(cameraId, cameraInfo);
     }
 
     assert(index != NAME_NOT_FOUND);
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
index c21092e..36822c7 100644
--- a/services/camera/libcameraservice/common/CameraModule.h
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -33,6 +33,7 @@
 class CameraModule {
 public:
     CameraModule(camera_module_t *module);
+    virtual ~CameraModule();
 
     // Must be called after construction
     // Returns OK on success, NO_INIT on failure
@@ -60,7 +61,6 @@
 
     camera_module_t *mModule;
     KeyedVector<int, camera_info> mCameraInfoMap;
-    KeyedVector<int, CameraMetadata> mCameraCharacteristicsMap;
     Mutex mCameraInfoLock;
 };
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4b55dad..9e73b5c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -164,9 +164,17 @@
         return res;
     }
 
-    /** Start up request queue thread */
+    bool aeLockAvailable = false;
+    camera_metadata_ro_entry aeLockAvailableEntry;
+    res = find_camera_metadata_ro_entry(info.static_camera_characteristics,
+            ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry);
+    if (res == OK && aeLockAvailableEntry.count > 0) {
+        aeLockAvailable = (aeLockAvailableEntry.data.u8[0] ==
+                ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
+    }
 
-    mRequestThread = new RequestThread(this, mStatusTracker, device);
+    /** Start up request queue thread */
+    mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable);
     res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
     if (res != OK) {
         SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -2472,7 +2480,8 @@
 
 Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
         sp<StatusTracker> statusTracker,
-        camera3_device_t *hal3Device) :
+        camera3_device_t *hal3Device,
+        bool aeLockAvailable) :
         Thread(/*canCallJava*/false),
         mParent(parent),
         mStatusTracker(statusTracker),
@@ -2485,19 +2494,9 @@
         mLatestRequestId(NAME_NOT_FOUND),
         mCurrentAfTriggerId(0),
         mCurrentPreCaptureTriggerId(0),
-        mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
+        mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES),
+        mAeLockAvailable(aeLockAvailable) {
     mStatusId = statusTracker->addComponent();
-
-    mAeLockAvailable = false;
-    sp<Camera3Device> p = parent.promote();
-    if (p != NULL) {
-        camera_metadata_ro_entry aeLockAvailable =
-                p->info().find(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
-        if (aeLockAvailable.count > 0) {
-            mAeLockAvailable = (aeLockAvailable.data.u8[0] ==
-                    ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
-        }
-    }
 }
 
 void Camera3Device::RequestThread::setNotificationListener(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bb4bcc4..31b6132 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -389,7 +389,8 @@
 
         RequestThread(wp<Camera3Device> parent,
                 sp<camera3::StatusTracker> statusTracker,
-                camera3_device_t *hal3Device);
+                camera3_device_t *hal3Device,
+                bool aeLockAvailable);
 
         void     setNotificationListener(NotificationListener *listener);