Reconcile with jb-mr2-release jb-mr2-zeroday-release - do not merge

Change-Id: Idf0f0cdf02e6e94603ff003b6baf869b4414e1cf
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 34bae29..df25d7b 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -278,7 +278,7 @@
     void deferMessage(const sp<AMessage> &msg);
     void processDeferredMessages();
 
-    void sendFormatChange();
+    void sendFormatChange(const sp<AMessage> &reply);
 
     void signalError(
             OMX_ERRORTYPE error = OMX_ErrorUndefined,
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 54f8d9e..85232e7 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -82,7 +82,7 @@
         {0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
         {0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
         EFFECT_CONTROL_API_VERSION,
-        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_DEVICE_IND
         | EFFECT_FLAG_VOLUME_CTRL),
         BASS_BOOST_CUP_LOAD_ARM9E,
         BUNDLE_MEM_USAGE,
@@ -108,7 +108,7 @@
         {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
         {0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid Eq NXP
         EFFECT_CONTROL_API_VERSION,
-        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL),
         EQUALIZER_CUP_LOAD_ARM9E,
         BUNDLE_MEM_USAGE,
         "Equalizer",
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 68cbdf5..963b04f 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -124,7 +124,7 @@
             mCurrentState = MEDIA_PLAYER_INITIALIZED;
             err = NO_ERROR;
         } else {
-            ALOGE("Unable to to create media player");
+            ALOGE("Unable to create media player");
         }
     }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index acff958..57ec7ea 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -321,7 +321,7 @@
                 mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
         result.append(buffer);
     }
-    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
+    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
             mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
     result.append(buffer);
     snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
@@ -535,8 +535,8 @@
     {
         Mutex::Autolock l(mLock);
         p = mPlayer;
+        mClient.clear();
     }
-    mClient.clear();
 
     mPlayer.clear();
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 64e3885..cf41cf2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2229,7 +2229,7 @@
     }
 }
 
-void ACodec::sendFormatChange() {
+void ACodec::sendFormatChange(const sp<AMessage> &reply) {
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", kWhatOutputFormatChanged);
 
@@ -2294,14 +2294,12 @@
                         rect.nTop + rect.nHeight - 1);
 
                 if (mNativeWindow != NULL) {
-                    android_native_rect_t crop;
-                    crop.left = rect.nLeft;
-                    crop.top = rect.nTop;
-                    crop.right = rect.nLeft + rect.nWidth;
-                    crop.bottom = rect.nTop + rect.nHeight;
-
-                    CHECK_EQ(0, native_window_set_crop(
-                                mNativeWindow.get(), &crop));
+                    reply->setRect(
+                            "crop",
+                            rect.nLeft,
+                            rect.nTop,
+                            rect.nLeft + rect.nWidth,
+                            rect.nTop + rect.nHeight);
                 }
             }
             break;
@@ -3057,8 +3055,11 @@
                 break;
             }
 
+            sp<AMessage> reply =
+                new AMessage(kWhatOutputBufferDrained, mCodec->id());
+
             if (!mCodec->mSentFormat) {
-                mCodec->sendFormatChange();
+                mCodec->sendFormatChange(reply);
             }
 
             info->mData->setRange(rangeOffset, rangeLength);
@@ -3081,9 +3082,6 @@
             notify->setBuffer("buffer", info->mData);
             notify->setInt32("flags", flags);
 
-            sp<AMessage> reply =
-                new AMessage(kWhatOutputBufferDrained, mCodec->id());
-
             reply->setPointer("buffer-id", info->mBufferID);
 
             notify->setMessage("reply", reply);
@@ -3127,6 +3125,13 @@
         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
 
+    android_native_rect_t crop;
+    if (msg->findRect("crop",
+            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+        CHECK_EQ(0, native_window_set_crop(
+                mCodec->mNativeWindow.get(), &crop));
+    }
+
     int32_t render;
     if (mCodec->mNativeWindow != NULL
             && msg->findInt32("render", &render) && render != 0
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index a01ec97..ae6ae2d 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -282,6 +282,7 @@
     if (!usesReservoir()) {
         if (u.ext_data) {
             free(u.ext_data);
+            u.ext_data = NULL;
         }
     }
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 8bc0275..e02af90 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -748,10 +748,10 @@
         outQueue.erase(outQueue.begin());
         CHECK(!mInputBufferInfoVec.empty());
         InputBufferInfo *inputBufInfo = mInputBufferInfoVec.begin();
-        mInputBufferInfoVec.erase(mInputBufferInfoVec.begin());
         outHeader->nTimeStamp = inputBufInfo->mTimeUs;
         outHeader->nFlags |= (inputBufInfo->mFlags | OMX_BUFFERFLAG_ENDOFFRAME);
         outHeader->nFilledLen = dataLength;
+        mInputBufferInfoVec.erase(mInputBufferInfoVec.begin());
         outInfo->mOwnedByUs = false;
         notifyFillBufferDone(outHeader);
     }
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 501a970..af369b5 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -117,7 +117,8 @@
 
     bumpSocketBufferSize(*rtcpSocket);
 
-    unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
+    /* rand() * 1000 may overflow int type, use long long */
+    unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
     start &= ~1;
 
     for (unsigned port = start; port < 65536; port += 2) {
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 4256fc4..2706880 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -49,6 +49,8 @@
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleepUs = 20000;
 
+static const nsecs_t kAudioCommandTimeout = 3000000000; // 3 seconds
+
 namespace {
     extern struct audio_policy_service_ops aps_ops;
 };
@@ -707,7 +709,7 @@
                                                                     data->mIO);
                     if (command->mWaitStatus) {
                         command->mCond.signal();
-                        mWaitWorkCV.wait(mLock);
+                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
                     }
                     delete data;
                     }break;
@@ -718,7 +720,7 @@
                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
                     if (command->mWaitStatus) {
                         command->mCond.signal();
-                        mWaitWorkCV.wait(mLock);
+                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
                     }
                     delete data;
                     }break;
@@ -729,7 +731,7 @@
                     command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
                     if (command->mWaitStatus) {
                         command->mCond.signal();
-                        mWaitWorkCV.wait(mLock);
+                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
                     }
                     delete data;
                     }break;
@@ -837,7 +839,7 @@
     if (command->mWaitStatus) {
         command->mCond.wait(mLock);
         status =  command->mStatus;
-        mWaitWorkCV.signal();
+        command->mCond.signal();
     }
     return status;
 }
@@ -862,7 +864,7 @@
     if (command->mWaitStatus) {
         command->mCond.wait(mLock);
         status =  command->mStatus;
-        mWaitWorkCV.signal();
+        command->mCond.signal();
     }
     return status;
 }
@@ -883,7 +885,7 @@
     if (command->mWaitStatus) {
         command->mCond.wait(mLock);
         status =  command->mStatus;
-        mWaitWorkCV.signal();
+        command->mCond.signal();
     }
     return status;
 }
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index d66294c..942ea35 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -680,7 +680,7 @@
         return mStatus;
     }
     status_t status = NO_ERROR;
-    if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
         status_t cmdStatus;
         uint32_t size = sizeof(status_t);
         uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6b3ded9..97f66f4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2990,9 +2990,11 @@
 
             // forward device change to effects that have requested to be
             // aware of attached audio device.
-            mOutDevice = value;
-            for (size_t i = 0; i < mEffectChains.size(); i++) {
-                mEffectChains[i]->setDevice_l(mOutDevice);
+            if (value != AUDIO_DEVICE_NONE) {
+                mOutDevice = value;
+                for (size_t i = 0; i < mEffectChains.size(); i++) {
+                    mEffectChains[i]->setDevice_l(mOutDevice);
+                }
             }
         }
 
diff --git a/services/audioflinger/test-resample.cpp b/services/audioflinger/test-resample.cpp
index b082e8c..7a314cf 100644
--- a/services/audioflinger/test-resample.cpp
+++ b/services/audioflinger/test-resample.cpp
@@ -219,12 +219,12 @@
 
         memset(output_vaddr, 0, output_size);
         timespec start, end;
-        clock_gettime(CLOCK_MONOTONIC_HR, &start);
+        clock_gettime(CLOCK_MONOTONIC, &start);
         resampler->resample((int*) output_vaddr, out_frames, &provider);
         resampler->resample((int*) output_vaddr, out_frames, &provider);
         resampler->resample((int*) output_vaddr, out_frames, &provider);
         resampler->resample((int*) output_vaddr, out_frames, &provider);
-        clock_gettime(CLOCK_MONOTONIC_HR, &end);
+        clock_gettime(CLOCK_MONOTONIC, &end);
         int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
         int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
         int64_t time = (end_ns - start_ns)/4;
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 081fdec..16688cf 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -611,27 +611,35 @@
 
 void Camera2Client::setPreviewCallbackFlagL(Parameters &params, int flag) {
     status_t res = OK;
+
+    switch(params.state) {
+        case Parameters::STOPPED:
+        case Parameters::WAITING_FOR_PREVIEW_WINDOW:
+        case Parameters::PREVIEW:
+            // OK
+            break;
+        default:
+            if (flag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+                ALOGE("%s: Camera %d: Can't use preview callbacks "
+                        "in state %d", __FUNCTION__, mCameraId, params.state);
+                return;
+            }
+    }
+
     if (flag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
         ALOGV("%s: setting oneshot", __FUNCTION__);
         params.previewCallbackOneShot = true;
     }
     if (params.previewCallbackFlags != (uint32_t)flag) {
         params.previewCallbackFlags = flag;
-        switch(params.state) {
-        case Parameters::PREVIEW:
+
+        if (params.state == Parameters::PREVIEW) {
             res = startPreviewL(params, true);
-            break;
-        case Parameters::RECORD:
-        case Parameters::VIDEO_SNAPSHOT:
-            res = startRecordingL(params, true);
-            break;
-        default:
-            break;
-        }
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Unable to refresh request in state %s",
-                    __FUNCTION__, mCameraId,
-                    Parameters::getStateName(params.state));
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to refresh request in state %s",
+                        __FUNCTION__, mCameraId,
+                        Parameters::getStateName(params.state));
+            }
         }
     }
 
@@ -682,10 +690,46 @@
         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;
     if (callbacksEnabled) {
+        // Can't have recording stream hanging around when enabling callbacks,
+        // since it exceeds the max stream count on some devices.
+        if (mStreamingProcessor->getRecordingStreamId() != NO_STREAM) {
+            ALOGV("%s: Camera %d: Clearing out recording stream before "
+                    "creating callback stream", __FUNCTION__, mCameraId);
+            res = mStreamingProcessor->stopStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Can't stop streaming to delete "
+                        "recording stream", __FUNCTION__, mCameraId);
+                return res;
+            }
+            res = mStreamingProcessor->deleteRecordingStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to delete recording stream before "
+                        "enabling callbacks: %s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+                return res;
+            }
+        }
+
         res = mCallbackProcessor->updateStream(params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
@@ -719,18 +763,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) {
@@ -894,6 +926,29 @@
         }
     }
 
+    // Not all devices can support a preview callback stream and a recording
+    // stream at the same time, so assume none of them can.
+    if (mCallbackProcessor->getStreamId() != NO_STREAM) {
+        ALOGV("%s: Camera %d: Clearing out callback stream before "
+                "creating recording stream", __FUNCTION__, mCameraId);
+        res = mStreamingProcessor->stopStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
+                    __FUNCTION__, mCameraId);
+            return res;
+        }
+        res = mCallbackProcessor->deleteStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to delete callback stream before "
+                    "record: %s (%d)", __FUNCTION__, mCameraId,
+                    strerror(-res), res);
+            return res;
+        }
+    }
+    // Disable callbacks if they're enabled; can't record and use callbacks,
+    // and we can't fail record start without stagefright asserting.
+    params.previewCallbackFlags = 0;
+
     res = updateProcessorStream<
             StreamingProcessor,
             &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
@@ -905,17 +960,6 @@
     }
 
     Vector<uint8_t> outputStreams;
-    bool callbacksEnabled = params.previewCallbackFlags &
-        CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
-    if (callbacksEnabled) {
-        res = mCallbackProcessor->updateStream(params);
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
-                    __FUNCTION__, mCameraId, strerror(-res), res);
-            return res;
-        }
-        outputStreams.push(getCallbackStreamId());
-    }
     outputStreams.push(getPreviewStreamId());
     outputStreams.push(getRecordingStreamId());
 
@@ -1647,6 +1691,8 @@
      * queue) and then try again. Resume streaming once we're done.
      */
     if (res == -EBUSY) {
+        ALOGV("%s: Camera %d: Pausing to update stream", __FUNCTION__,
+                mCameraId);
         res = mStreamingProcessor->togglePauseStream(/*pause*/true);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index c7edb76..cc7802b 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -170,6 +170,7 @@
     mHal3Device = device;
     mStatus = STATUS_IDLE;
     mNextStreamId = 0;
+    mNeedConfig = true;
 
     return OK;
 }
@@ -180,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();
     }
@@ -206,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();
     }
 
@@ -218,7 +229,7 @@
     mStatus = STATUS_UNINITIALIZED;
 
     ALOGV("%s: X", __FUNCTION__);
-    return OK;
+    return res;
 }
 
 status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
@@ -582,6 +593,7 @@
     }
 
     *id = mNextStreamId++;
+    mNeedConfig = true;
 
     // Continue captures if active at start
     if (wasActive) {
@@ -707,6 +719,7 @@
         // fall through since we want to still list the stream as deleted.
     }
     mDeletedStreams.add(deletedStream);
+    mNeedConfig = true;
 
     return res;
 }
@@ -1007,6 +1020,12 @@
         return INVALID_OPERATION;
     }
 
+    if (!mNeedConfig) {
+        ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
+        mStatus = STATUS_ACTIVE;
+        return OK;
+    }
+
     // Start configuring the streams
 
     camera3_stream_configuration config;
@@ -1091,6 +1110,7 @@
     // Finish configuring the streams lazily on first reference
 
     mStatus = STATUS_ACTIVE;
+    mNeedConfig = false;
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 7a8c22a..faa42b9 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -149,6 +149,7 @@
     StreamSet                  mOutputStreams;
     sp<camera3::Camera3Stream> mInputStream;
     int                        mNextStreamId;
+    bool                       mNeedConfig;
 
     // Need to hold on to stream references until configure completes.
     Vector<sp<camera3::Camera3StreamInterface> > mDeletedStreams;
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index 4987ab6..522f49a 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -74,8 +74,10 @@
     }
 
     if (mCallbackConsumer == 0) {
-        // Create CPU buffer queue endpoint
-        mCallbackConsumer = new CpuConsumer(kCallbackHeapCount);
+        // Create CPU buffer queue endpoint. Make it async to avoid disconnect
+        // deadlocks.
+        mCallbackConsumer = new CpuConsumer(kCallbackHeapCount,
+                /*synchronized*/ false);
         mCallbackConsumer->setFrameAvailableListener(this);
         mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));
         mCallbackWindow = new Surface(
@@ -133,7 +135,7 @@
 status_t CallbackProcessor::deleteStream() {
     ATRACE_CALL();
     sp<CameraDeviceBase> device;
-
+    status_t res;
     {
         Mutex::Autolock l(mInputMutex);
 
@@ -146,7 +148,19 @@
             return INVALID_OPERATION;
         }
     }
-    device->deleteStream(mCallbackStreamId);
+    res = device->waitUntilDrained();
+    if (res != OK) {
+        ALOGE("%s: Error waiting for HAL to drain: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    res = device->deleteStream(mCallbackStreamId);
+    if (res != OK) {
+        ALOGE("%s: Unable to delete callback stream: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
 
     {
         Mutex::Autolock l(mInputMutex);
@@ -365,6 +379,9 @@
 
         ALOGV("%s: Freeing buffer", __FUNCTION__);
         mCallbackConsumer->unlockBuffer(imgBuffer);
+
+        // mCallbackHeap may get freed up once input mutex is released
+        callbackHeap = mCallbackHeap;
     }
 
     // Call outside parameter lock to allow re-entrancy from notification
@@ -375,7 +392,7 @@
             ALOGV("%s: Camera %d: Invoking client data callback",
                     __FUNCTION__, mId);
             l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
-                    mCallbackHeap->mBuffers[heapIdx], NULL);
+                    callbackHeap->mBuffers[heapIdx], NULL);
         }
     }
 
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:
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
index 2e06691..40c77df 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
@@ -329,8 +329,9 @@
 }
 
 bool ZslProcessor3::threadLoop() {
-    // TODO: remove dependency on thread
-    return true;
+    // TODO: remove dependency on thread. For now, shut thread down right
+    // away.
+    return false;
 }
 
 void ZslProcessor3::dumpZslQueue(int fd) const {