merge in jb-mr2-release history after reset to jb-mr2-dev
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index f09ce75..f55b697 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1012,6 +1012,7 @@
         if (lStatus == NO_ERROR) {
             // If the tone was restarted exit now before calling clearWaveGens();
             if (mState != TONE_INIT) {
+                mLock.unlock();
                 return;
             }
             ALOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 48f3606..2e01dae 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -690,7 +690,7 @@
         outputStreams.push(getCallbackStreamId());
     }
     if (params.zslMode && !params.recordingHint) {
-        res = mZslProcessor->updateStream(params);
+        res = updateProcessorStream(mZslProcessor, params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
                     __FUNCTION__, mCameraId, strerror(-res), res);
@@ -718,7 +718,7 @@
         // assumption that the user will record video. To optimize recording
         // startup time, create the necessary output streams for recording and
         // video snapshot now if they don't already exist.
-        res = mJpegProcessor->updateStream(params);
+        res = updateProcessorStream(mJpegProcessor, params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't pre-configure still image "
                     "stream: %s (%d)",
@@ -1125,7 +1125,7 @@
 
         ALOGV("%s: Camera %d: Starting picture capture", __FUNCTION__, mCameraId);
 
-        res = mJpegProcessor->updateStream(l.mParameters);
+        res = updateProcessorStream(mJpegProcessor, l.mParameters);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)",
                     __FUNCTION__, mCameraId, strerror(-res), res);
@@ -1605,5 +1605,47 @@
     return res;
 }
 
+template <typename ProcessorT>
+status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
+                                              camera2::Parameters params) {
+    status_t res;
+
+    res = processor->updateStream(params);
+
+    /**
+     * Can't update the stream if it's busy?
+     *
+     * Then we need to stop the device (by temporarily clearing the request
+     * queue) and then try again. Resume streaming once we're done.
+     */
+    if (res == -EBUSY) {
+        res = mStreamingProcessor->togglePauseStream(/*pause*/true);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+
+        res = mDevice->waitUntilDrained();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+
+        res = processor->updateStream(params);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Failed to update processing stream "
+                  " despite having halted streaming first: %s (%d)",
+                  __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+
+        res = mStreamingProcessor->togglePauseStream(/*pause*/false);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't unpause streaming: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+    }
+
+    return res;
+}
 
 } // namespace android
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index af72ab2..f42d022 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -159,6 +159,9 @@
     // Used with stream IDs
     static const int NO_STREAM = -1;
 
+    template <typename ProcessorT>
+    status_t updateProcessorStream(sp<ProcessorT> processor, Parameters params);
+
     sp<camera2::FrameProcessor> mFrameProcessor;
 
     /* Preview/Recording related members */
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index 5e5bfc2..6f4f4c8 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -680,8 +680,8 @@
     // CameraDevice semantics require device to already be idle before
     // deleteStream is called, unlike for createStream.
     if (mStatus != STATUS_IDLE) {
-        CLOGE("Device not idle");
-        return INVALID_OPERATION;
+        ALOGV("%s: Camera %d: Device not idle", __FUNCTION__, mId);
+        return -EBUSY;
     }
 
     sp<Camera3StreamInterface> deletedStream;
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 01d7f9c..f0a13ca 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -113,7 +113,11 @@
             ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
                 __FUNCTION__, mId, mCaptureStreamId);
             res = device->deleteStream(mCaptureStreamId);
-            if (res != OK) {
+            if (res == -EBUSY) {
+                ALOGV("%s: Camera %d: Device is busy, call updateStream again "
+                      " after it becomes idle", __FUNCTION__, mId);
+                return res;
+            } else if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
                         "for capture: %s (%d)", __FUNCTION__,
                         mId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index c36cf87..ab83714 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -36,6 +36,7 @@
         mDevice(client->getCameraDevice()),
         mId(client->getCameraId()),
         mActiveRequest(NONE),
+        mPaused(false),
         mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
         mPreviewStreamId(NO_STREAM),
         mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
@@ -419,10 +420,59 @@
         return res;
     }
     mActiveRequest = type;
+    mPaused = false;
 
     return OK;
 }
 
+status_t StreamingProcessor::togglePauseStream(bool pause) {
+    ATRACE_CALL();
+    status_t res;
+
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
+
+    ALOGV("%s: Camera %d: toggling pause to %d", __FUNCTION__, mId, pause);
+
+    Mutex::Autolock m(mMutex);
+
+    if (mActiveRequest == NONE) {
+        ALOGE("%s: Camera %d: Can't toggle pause, streaming was not started",
+              __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
+
+    if (mPaused == pause) {
+        return OK;
+    }
+
+    if (pause) {
+        res = device->clearStreamingRequest();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
+                    __FUNCTION__, mId, strerror(-res), res);
+            return res;
+        }
+    } else {
+        CameraMetadata &request =
+                (mActiveRequest == PREVIEW) ? mPreviewRequest
+                                            : mRecordingRequest;
+        res = device->setStreamingRequest(request);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to set preview request to resume: "
+                    "%s (%d)",
+                    __FUNCTION__, mId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    mPaused = pause;
+    return OK;
+}
+
 status_t StreamingProcessor::stopStream() {
     ATRACE_CALL();
     status_t res;
@@ -443,6 +493,7 @@
     }
 
     mActiveRequest = NONE;
+    mPaused = false;
 
     return OK;
 }
@@ -662,20 +713,29 @@
         result.append("    Preview request:\n");
         write(fd, result.string(), result.size());
         mPreviewRequest.dump(fd, 2, 6);
+        result.clear();
     } else {
         result.append("    Preview request: undefined\n");
-        write(fd, result.string(), result.size());
     }
 
     if (mRecordingRequest.entryCount() != 0) {
         result = "    Recording request:\n";
         write(fd, result.string(), result.size());
         mRecordingRequest.dump(fd, 2, 6);
+        result.clear();
     } else {
         result = "    Recording request: undefined\n";
-        write(fd, result.string(), result.size());
     }
 
+    const char* streamTypeString[] = {
+        "none", "preview", "record"
+    };
+    result.append(String8::format("   Active request: %s (paused: %s)\n",
+                                  streamTypeString[mActiveRequest],
+                                  mPaused ? "yes" : "no"));
+
+    write(fd, result.string(), result.size());
+
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index 643114e..281b344 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -65,6 +65,9 @@
     status_t startStream(StreamType type,
             const Vector<uint8_t> &outputStreams);
 
+    // Toggle between paused and unpaused. Stream must be started first.
+    status_t togglePauseStream(bool pause);
+
     status_t stopStream();
 
     // Returns the request ID for the currently streaming request
@@ -91,6 +94,7 @@
     int mId;
 
     StreamType mActiveRequest;
+    bool mPaused;
 
     // Preview-related members
     int32_t mPreviewRequestId;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
index be1ffeb..defcafc 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
@@ -112,7 +112,11 @@
                   "dimensions changed",
                 __FUNCTION__, client->getCameraId(), mZslStreamId);
             res = device->deleteStream(mZslStreamId);
-            if (res != OK) {
+            if (res == -EBUSY) {
+                ALOGV("%s: Camera %d: Device is busy, call updateStream again "
+                      " after it becomes idle", __FUNCTION__, mId);
+                return res;
+            } else if(res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
                         "for ZSL: %s (%d)", __FUNCTION__,
                         client->getCameraId(), strerror(-res), res);