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 5fdec34..081fdec 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -102,6 +102,9 @@
     String8 threadName;
 
     mStreamingProcessor = new StreamingProcessor(this);
+    threadName = String8::format("C2-%d-StreamProc",
+            mCameraId);
+    mStreamingProcessor->run(threadName.string());
 
     mFrameProcessor = new FrameProcessor(mDevice, this);
     threadName = String8::format("C2-%d-FrameProc",
@@ -411,6 +414,7 @@
     mCallbackProcessor->deleteStream();
     mZslProcessor->deleteStream();
 
+    mStreamingProcessor->requestExit();
     mFrameProcessor->requestExit();
     mCaptureSequencer->requestExit();
     mJpegProcessor->requestExit();
@@ -419,6 +423,7 @@
 
     ALOGV("Camera %d: Waiting for threads", mCameraId);
 
+    mStreamingProcessor->join();
     mFrameProcessor->join();
     mCaptureSequencer->join();
     mJpegProcessor->join();
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index f4a9217..fed05a6 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -41,6 +41,7 @@
         mPreviewStreamId(NO_STREAM),
         mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
         mRecordingStreamId(NO_STREAM),
+        mRecordingFrameAvailable(false),
         mRecordingHeapCount(kDefaultRecordingHeapCount)
 {
 }
@@ -536,6 +537,36 @@
 
 void StreamingProcessor::onFrameAvailable() {
     ATRACE_CALL();
+    Mutex::Autolock l(mMutex);
+    if (!mRecordingFrameAvailable) {
+        mRecordingFrameAvailable = true;
+        mRecordingFrameAvailableSignal.signal();
+    }
+
+}
+
+bool StreamingProcessor::threadLoop() {
+    status_t res;
+
+    {
+        Mutex::Autolock l(mMutex);
+        while (!mRecordingFrameAvailable) {
+            res = mRecordingFrameAvailableSignal.waitRelative(
+                mMutex, kWaitDuration);
+            if (res == TIMED_OUT) return true;
+        }
+        mRecordingFrameAvailable = false;
+    }
+
+    do {
+        res = processRecordingFrame();
+    } while (res == OK);
+
+    return true;
+}
+
+status_t StreamingProcessor::processRecordingFrame() {
+    ATRACE_CALL();
     status_t res;
     sp<Camera2Heap> recordingHeap;
     size_t heapIdx = 0;
@@ -547,12 +578,14 @@
         BufferItemConsumer::BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer);
         if (res != OK) {
-            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
-                    __FUNCTION__, mId, strerror(-res), res);
-            return;
+            if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
+                ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
+                        __FUNCTION__, mId, strerror(-res), res);
+            }
+            return res;
         }
         mRecordingConsumer->releaseBuffer(imgBuffer);
-        return;
+        return OK;
     }
 
     {
@@ -563,23 +596,24 @@
         BufferItemConsumer::BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer);
         if (res != OK) {
-            ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
-                    __FUNCTION__, mId, strerror(-res), res);
-            return;
+            if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
+                ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
+                        __FUNCTION__, mId, strerror(-res), res);
+            }
+            return res;
         }
         timestamp = imgBuffer.mTimestamp;
 
         mRecordingFrameCount++;
         ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
 
-        // TODO: Signal errors here upstream
         if (l.mParameters.state != Parameters::RECORD &&
                 l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
             ALOGV("%s: Camera %d: Discarding recording image buffers "
                     "received after recording done", __FUNCTION__,
                     mId);
             mRecordingConsumer->releaseBuffer(imgBuffer);
-            return;
+            return INVALID_OPERATION;
         }
 
         if (mRecordingHeap == 0) {
@@ -594,7 +628,7 @@
                 ALOGE("%s: Camera %d: Unable to allocate memory for recording",
                         __FUNCTION__, mId);
                 mRecordingConsumer->releaseBuffer(imgBuffer);
-                return;
+                return NO_MEMORY;
             }
             for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
                 if (mRecordingBuffers[i].mBuf !=
@@ -615,7 +649,7 @@
             ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
                     __FUNCTION__, mId);
             mRecordingConsumer->releaseBuffer(imgBuffer);
-            return;
+            return NO_MEMORY;
         }
 
         heapIdx = mRecordingHeapHead;
@@ -649,6 +683,7 @@
                 CAMERA_MSG_VIDEO_FRAME,
                 recordingHeap->mBuffers[heapIdx]);
     }
+    return OK;
 }
 
 void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index 281b344..9f71fa0 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -37,7 +37,8 @@
 /**
  * Management and processing for preview and recording streams
  */
-class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
+class StreamingProcessor:
+            public Thread, public BufferItemConsumer::FrameAvailableListener {
   public:
     StreamingProcessor(sp<Camera2Client> client);
     ~StreamingProcessor();
@@ -103,6 +104,8 @@
     sp<ANativeWindow> mPreviewWindow;
 
     // Recording-related members
+    static const nsecs_t kWaitDuration = 50000000; // 50 ms
+
     int32_t mRecordingRequestId;
     int mRecordingStreamId;
     int mRecordingFrameCount;
@@ -111,11 +114,17 @@
     CameraMetadata mRecordingRequest;
     sp<camera2::Camera2Heap> mRecordingHeap;
 
+    bool mRecordingFrameAvailable;
+    Condition mRecordingFrameAvailableSignal;
+
     static const size_t kDefaultRecordingHeapCount = 8;
     size_t mRecordingHeapCount;
     Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
     size_t mRecordingHeapHead, mRecordingHeapFree;
 
+    virtual bool threadLoop();
+
+    status_t processRecordingFrame();
 };