merge in jb-mr2-zeroday-release history after reset to jb-mr2-dev
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 081fdec..a1971e3 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -682,6 +682,22 @@
         return res;
     }
 
+    // We could wait to create the JPEG output stream until first actual use
+    // (first takePicture call). However, this would substantially increase the
+    // first capture latency on HAL3 devices, and potentially on some HAL2
+    // devices. So create it unconditionally at preview start. As a drawback,
+    // this increases gralloc memory consumption for applications that don't
+    // ever take a picture.
+    // TODO: Find a better compromise, though this likely would involve HAL
+    // changes.
+    res = updateProcessorStream(mJpegProcessor, params);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Can't pre-configure still image "
+                "stream: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
     Vector<uint8_t> outputStreams;
     bool callbacksEnabled = params.previewCallbackFlags &
         CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
@@ -719,18 +735,6 @@
         res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,
                 outputStreams);
     } else {
-        // With recording hint set, we're going to be operating under the
-        // 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 = updateProcessorStream(mJpegProcessor, params);
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Can't pre-configure still image "
-                    "stream: %s (%d)",
-                    __FUNCTION__, mCameraId, strerror(-res), res);
-            return res;
-        }
-
         if (!restart) {
             res = mStreamingProcessor->updateRecordingRequest(params);
             if (res != OK) {
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index bc4db91..cc7802b 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -181,24 +181,29 @@
 
     ALOGV("%s: E", __FUNCTION__);
 
-    status_t res;
-    if (mStatus == STATUS_UNINITIALIZED) return OK;
+    status_t res = OK;
+    if (mStatus == STATUS_UNINITIALIZED) return res;
 
     if (mStatus == STATUS_ACTIVE ||
             (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
         res = mRequestThread->clearRepeatingRequests();
         if (res != OK) {
             SET_ERR_L("Can't stop streaming");
-            return res;
-        }
-        res = waitUntilDrainedLocked();
-        if (res != OK) {
-            SET_ERR_L("Timeout waiting for HAL to drain");
-            return res;
+            // Continue to close device even in case of error
+        } else {
+            res = waitUntilDrainedLocked();
+            if (res != OK) {
+                SET_ERR_L("Timeout waiting for HAL to drain");
+                // Continue to close device even in case of error
+            }
         }
     }
     assert(mStatus == STATUS_IDLE || mStatus == STATUS_ERROR);
 
+    if (mStatus == STATUS_ERROR) {
+        CLOGE("Shutting down in an error state");
+    }
+
     if (mRequestThread != NULL) {
         mRequestThread->requestExit();
     }
@@ -207,7 +212,12 @@
     mInputStream.clear();
 
     if (mRequestThread != NULL) {
-        mRequestThread->join();
+        if (mStatus != STATUS_ERROR) {
+            // HAL may be in a bad state, so waiting for request thread
+            // (which may be stuck in the HAL processCaptureRequest call)
+            // could be dangerous.
+            mRequestThread->join();
+        }
         mRequestThread.clear();
     }
 
@@ -219,7 +229,7 @@
     mStatus = STATUS_UNINITIALIZED;
 
     ALOGV("%s: X", __FUNCTION__);
-    return OK;
+    return res;
 }
 
 status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
@@ -1012,6 +1022,7 @@
 
     if (!mNeedConfig) {
         ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
+        mStatus = STATUS_ACTIVE;
         return OK;
     }
 
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 266e516..e5a011c 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -253,6 +253,12 @@
                 res = INVALID_OPERATION;
                 break;
             case Parameters::STILL_CAPTURE:
+                res = client->getCameraDevice()->waitUntilDrained();
+                if (res != OK) {
+                    ALOGE("%s: Camera %d: Can't idle after still capture: "
+                            "%s (%d)", __FUNCTION__, client->getCameraId(),
+                            strerror(-res), res);
+                }
                 l.mParameters.state = Parameters::STOPPED;
                 break;
             case Parameters::VIDEO_SNAPSHOT: