Merge "Less verbose logging, lots of references." into jb-mr1-dev
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 5709837..597866a 100755
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -517,6 +517,10 @@
     webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
     webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
 
+    if (audio_is_input_device(device)) {
+        return 0;
+    }
+
     switch(device) {
     case AUDIO_DEVICE_OUT_EARPIECE:
         mode = webrtc::EchoControlMobile::kEarpiece;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 5060525..8ea6306 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -177,7 +177,7 @@
 
     // validate framecount
     int minFrameCount = 0;
-    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
+    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
     if (status != NO_ERROR) {
         return status;
     }
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7d49ef0..dc8e4a3 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1665,15 +1665,26 @@
                     mLastCommentData.setTo((const char *)buffer + 8);
                     break;
             }
-            if (mLastCommentMean == "com.apple.iTunes"
-                    && mLastCommentName == "iTunSMPB"
-                    && mLastCommentData.length() != 0) {
-                int32_t delay, padding;
-                if (sscanf(mLastCommentData,
-                           " %*x %x %x %*x", &delay, &padding) == 2) {
-                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
-                    mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
+
+            // Once we have a set of mean/name/data info, go ahead and process
+            // it to see if its something we are interested in.  Whether or not
+            // were are interested in the specific tag, make sure to clear out
+            // the set so we can be ready to process another tuple should one
+            // show up later in the file.
+            if ((mLastCommentMean.length() != 0) &&
+                (mLastCommentName.length() != 0) &&
+                (mLastCommentData.length() != 0)) {
+
+                if (mLastCommentMean == "com.apple.iTunes"
+                        && mLastCommentName == "iTunSMPB") {
+                    int32_t delay, padding;
+                    if (sscanf(mLastCommentData,
+                               " %*x %x %x %*x", &delay, &padding) == 2) {
+                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
+                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
+                    }
                 }
+
                 mLastCommentMean.clear();
                 mLastCommentName.clear();
                 mLastCommentData.clear();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index c27b4a2..a5d4c6c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -291,6 +291,14 @@
         for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
             loadHwModule_l(audio_interfaces[i]);
         }
+        // then try to find a module supporting the requested device.
+        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+            AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
+            audio_hw_device_t *dev = audioHwDevice->hwDevice();
+            if ((dev->get_supported_devices != NULL) &&
+                    (dev->get_supported_devices(dev) & devices) == devices)
+                return audioHwDevice;
+        }
     } else {
         // check a match for the requested module handle
         AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module);
@@ -298,13 +306,6 @@
             return audioHwDevice;
         }
     }
-    // then try to find a module supporting the requested device.
-    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
-        audio_hw_device_t *dev = audioHwDevice->hwDevice();
-        if ((dev->get_supported_devices(dev) & devices) == devices)
-            return audioHwDevice;
-    }
 
     return NULL;
 }
@@ -884,7 +885,7 @@
             if (mBtNrecIsOff != btNrecIsOff) {
                 for (size_t i = 0; i < mRecordThreads.size(); i++) {
                     sp<RecordThread> thread = mRecordThreads.valueAt(i);
-                    audio_devices_t device = thread->device() & AUDIO_DEVICE_IN_ALL;
+                    audio_devices_t device = thread->inDevice();
                     bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
                     // collect all of the thread's session IDs
                     KeyedVector<int, bool> ids = thread->sessionIds();
@@ -1133,7 +1134,7 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        audio_devices_t device, type_t type)
+        audio_devices_t outDevice, audio_devices_t inDevice, type_t type)
     :   Thread(false /*canCallJava*/),
         mType(type),
         mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mNormalFrameCount(0),
@@ -1141,7 +1142,8 @@
         mChannelCount(0),
         mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
         mParamStatus(NO_ERROR),
-        mStandby(false), mDevice(device), mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
+        mStandby(false), mOutDevice(outDevice), mInDevice(inDevice),
+        mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
         // mName will be set by concrete (non-virtual) subclass
         mDeathRecipient(new PMDeathRecipient(this))
 {
@@ -1518,7 +1520,7 @@
                                              audio_io_handle_t id,
                                              audio_devices_t device,
                                              type_t type)
-    :   ThreadBase(audioFlinger, id, device, type),
+    :   ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type),
         mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
@@ -3451,7 +3453,7 @@
 #ifdef ADD_BATTERY_DATA
             // when changing the audio output device, call addBatteryData to notify
             // the change
-            if (mDevice != value) {
+            if (mOutDevice != value) {
                 uint32_t params = 0;
                 // check whether speaker is on
                 if (value & AUDIO_DEVICE_OUT_SPEAKER) {
@@ -3473,9 +3475,9 @@
 
             // forward device change to effects that have requested to be
             // aware of attached audio device.
-            mDevice = value;
+            mOutDevice = value;
             for (size_t i = 0; i < mEffectChains.size(); i++) {
-                mEffectChains[i]->setDevice_l(mDevice);
+                mEffectChains[i]->setDevice_l(mOutDevice);
             }
         }
 
@@ -3930,7 +3932,7 @@
 
 AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
         AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
-    :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
+    :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(), DUPLICATING),
         mWaitTimeMs(UINT_MAX)
 {
     addOutputTrack(mainThread);
@@ -5936,7 +5938,7 @@
                                          audio_channel_mask_t channelMask,
                                          audio_io_handle_t id,
                                          audio_devices_t device) :
-    ThreadBase(audioFlinger, id, device, RECORD),
+    ThreadBase(audioFlinger, id, AUDIO_DEVICE_NONE, device, RECORD),
     mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
     // mRsmpInIndex and mInputBytes set by readInputParameters()
     mReqChannelCount(popcount(channelMask)),
@@ -6215,7 +6217,7 @@
         mTracks.add(track);
 
         // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
-        bool suspend = audio_is_bluetooth_sco_device(mDevice & AUDIO_DEVICE_IN_ALL) &&
+        bool suspend = audio_is_bluetooth_sco_device(mInDevice) &&
                         mAudioFlinger->btNrecIsOff();
         setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
         setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
@@ -6568,19 +6570,19 @@
             for (size_t i = 0; i < mEffectChains.size(); i++) {
                 mEffectChains[i]->setDevice_l(value);
             }
+
             // store input device and output device but do not forward output device to audio HAL.
             // Note that status is ignored by the caller for output device
             // (see AudioFlinger::setParameters()
-            audio_devices_t newDevice = mDevice;
-            if (value & AUDIO_DEVICE_OUT_ALL) {
-                newDevice &= ~(value & AUDIO_DEVICE_OUT_ALL);
+            if (audio_is_output_devices(value)) {
+                mOutDevice = value;
                 status = BAD_VALUE;
             } else {
-                newDevice &= ~(value & AUDIO_DEVICE_IN_ALL);
+                mInDevice = value;
                 // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
                 if (mTracks.size() > 0) {
-                    bool suspend = audio_is_bluetooth_sco_device(
-                            (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
+                    bool suspend = audio_is_bluetooth_sco_device(mInDevice) &&
+                                        mAudioFlinger->btNrecIsOff();
                     for (size_t i = 0; i < mTracks.size(); i++) {
                         sp<RecordTrack> track = mTracks[i];
                         setEffectSuspended_l(FX_IID_AEC, suspend, track->sessionId());
@@ -6588,8 +6590,6 @@
                     }
                 }
             }
-            newDevice |= value;
-            mDevice = newDevice;    // since mDevice is read by other threads, only write to it once
         }
         if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR &&
                 mAudioSource != (audio_source_t)value) {
@@ -7331,7 +7331,7 @@
         return 0;
     }
 
-    return thread->device();
+    return thread->outDevice();
 }
 
 sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
@@ -7744,7 +7744,8 @@
             }
             effectCreated = true;
 
-            effect->setDevice(mDevice);
+            effect->setDevice(mOutDevice);
+            effect->setDevice(mInDevice);
             effect->setMode(mAudioFlinger->getMode());
             effect->setAudioSource(mAudioSource);
         }
@@ -7822,7 +7823,8 @@
         return status;
     }
 
-    effect->setDevice(mDevice);
+    effect->setDevice(mOutDevice);
+    effect->setDevice(mInDevice);
     effect->setMode(mAudioFlinger->getMode());
     effect->setAudioSource(mAudioSource);
     return NO_ERROR;
@@ -8661,44 +8663,23 @@
 
 status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
 {
+    if (device == AUDIO_DEVICE_NONE) {
+        return NO_ERROR;
+    }
+
     Mutex::Autolock _l(mLock);
     status_t status = NO_ERROR;
     if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
-        // audio pre processing modules on RecordThread can receive both output and
-        // input device indication in the same call
-        audio_devices_t dev = device & AUDIO_DEVICE_OUT_ALL;
-        if (dev) {
-            status_t cmdStatus;
-            uint32_t size = sizeof(status_t);
-
-            status = (*mEffectInterface)->command(mEffectInterface,
-                                                  EFFECT_CMD_SET_DEVICE,
-                                                  sizeof(uint32_t),
-                                                  &dev,
-                                                  &size,
-                                                  &cmdStatus);
-            if (status == NO_ERROR) {
-                status = cmdStatus;
-            }
-        }
-        dev = device & AUDIO_DEVICE_IN_ALL;
-        if (dev) {
-            status_t cmdStatus;
-            uint32_t size = sizeof(status_t);
-
-            status_t status2 = (*mEffectInterface)->command(mEffectInterface,
-                                                  EFFECT_CMD_SET_INPUT_DEVICE,
-                                                  sizeof(uint32_t),
-                                                  &dev,
-                                                  &size,
-                                                  &cmdStatus);
-            if (status2 == NO_ERROR) {
-                status2 = cmdStatus;
-            }
-            if (status == NO_ERROR) {
-                status = status2;
-            }
-        }
+        status_t cmdStatus;
+        uint32_t size = sizeof(status_t);
+        uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
+                            EFFECT_CMD_SET_INPUT_DEVICE;
+        status = (*mEffectInterface)->command(mEffectInterface,
+                                              cmd,
+                                              sizeof(uint32_t),
+                                              &device,
+                                              &size,
+                                              &cmdStatus);
     }
     return status;
 }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 0fad7c7..5ffa5a6 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -353,7 +353,8 @@
             RECORD              // Thread class is RecordThread
         };
 
-        ThreadBase (const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, audio_devices_t device, type_t type);
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+                    audio_devices_t outDevice, audio_devices_t inDevice, type_t type);
         virtual             ~ThreadBase();
 
         void dumpBase(int fd, const Vector<String16>& args);
@@ -519,9 +520,10 @@
                     void        sendConfigEvent_l(int event, int param = 0);
                     void        processConfigEvents();
 
-                    // see note at declaration of mStandby and mDevice
+                    // see note at declaration of mStandby, mOutDevice and mInDevice
                     bool        standby() const { return mStandby; }
-                    audio_devices_t device() const { return mDevice; }
+                    audio_devices_t outDevice() const { return mOutDevice; }
+                    audio_devices_t inDevice() const { return mInDevice; }
 
         virtual     audio_stream_t* stream() const = 0;
 
@@ -667,13 +669,14 @@
                     Vector<ConfigEvent>     mConfigEvents;
 
                     // These fields are written and read by thread itself without lock or barrier,
-                    // and read by other threads without lock or barrier via standby() and device().
+                    // and read by other threads without lock or barrier via standby() , outDevice()
+                    // and inDevice().
                     // Because of the absence of a lock or barrier, any other thread that reads
                     // these fields must use the information in isolation, or be prepared to deal
                     // with possibility that it might be inconsistent with other information.
                     bool                    mStandby;   // Whether thread is currently in standby.
-                    audio_devices_t         mDevice;    // output device for PlaybackThread
-                                                        // input + output devices for RecordThread
+                    audio_devices_t         mOutDevice;   // output device
+                    audio_devices_t         mInDevice;    // input device
                     audio_source_t          mAudioSource; // (see audio.h, audio_source_t)
 
                     const audio_io_handle_t mId;
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 5400604..7abb405 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -156,6 +156,11 @@
     disconnect();
 
     mFrameProcessor->requestExit();
+    mCaptureSequencer->requestExit();
+    mJpegProcessor->requestExit();
+    mZslProcessor->requestExit();
+    mCallbackProcessor->requestExit();
+
     ALOGI("Camera %d: Closed", mCameraId);
 }
 
@@ -391,6 +396,8 @@
 
     mCallbackProcessor->deleteStream();
 
+    mZslProcessor->deleteStream();
+
     mDevice.clear();
     SharedParameters::Lock l(mParameters);
     l.mParameters.state = Parameters::DISCONNECTED;
@@ -639,7 +646,7 @@
             return res;
         }
     }
-    if (params.zslMode) {
+    if (params.zslMode && !params.recordingHint) {
         res = mZslProcessor->updateStream(params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
@@ -648,10 +655,45 @@
         }
     }
 
-    if (mPreviewRequest.entryCount() == 0) {
-        res = updatePreviewRequest(params);
+    CameraMetadata *request;
+    if (!params.recordingHint) {
+        if (mPreviewRequest.entryCount() == 0) {
+            res = updatePreviewRequest(params);
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to create preview request: %s (%d)",
+                        __FUNCTION__, mCameraId, strerror(-res), res);
+                return res;
+            }
+        }
+        request = &mPreviewRequest;
+    } 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.
+        if (mRecordingRequest.entryCount() == 0) {
+            res = updateRecordingRequest(params);
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to create recording preview "
+                        "request: %s (%d)",
+                        __FUNCTION__, mCameraId, strerror(-res), res);
+                return res;
+            }
+        }
+        request = &mRecordingRequest;
+
+        res = updateRecordingStream(params);
         if (res != OK) {
-            ALOGE("%s: Camera %d: Unable to create preview request: %s (%d)",
+            ALOGE("%s: Camera %d: Unable to pre-configure recording "
+                    "stream: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+
+        res = mJpegProcessor->updateStream(params);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't pre-configure still image "
+                    "stream: %s (%d)",
                     __FUNCTION__, mCameraId, strerror(-res), res);
             return res;
         }
@@ -663,11 +705,11 @@
     if (callbacksEnabled) {
         outputStreams.push(getCallbackStreamId());
     }
-    if (params.zslMode) {
+    if (params.zslMode && !params.recordingHint) {
         outputStreams.push(getZslStreamId());
     }
 
-    res = mPreviewRequest.update(
+    res = request->update(
         ANDROID_REQUEST_OUTPUT_STREAMS,
         outputStreams);
 
@@ -676,14 +718,14 @@
                 __FUNCTION__, mCameraId, strerror(-res), res);
         return res;
     }
-    res = mPreviewRequest.sort();
+    res = request->sort();
     if (res != OK) {
         ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
                 __FUNCTION__, mCameraId, strerror(-res), res);
         return res;
     }
 
-    res = mDevice->setStreamingRequest(mPreviewRequest);
+    res = mDevice->setStreamingRequest(*request);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
                 "%s (%d)",
@@ -816,6 +858,8 @@
         return INVALID_OPERATION;
     }
 
+    mCameraService->playSound(CameraService::SOUND_RECORDING);
+
     res = updateRecordingStream(params);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update recording stream: %s (%d)",
@@ -910,19 +954,13 @@
             return;
     };
 
-    // Back to preview. Since record can only be reached through preview,
-    // all preview stream setup should be up to date.
-    res = mDevice->setStreamingRequest(mPreviewRequest);
+    mCameraService->playSound(CameraService::SOUND_RECORDING);
+
+    res = startPreviewL(l.mParameters, true);
     if (res != OK) {
-        ALOGE("%s: Camera %d: Unable to switch back to preview request: "
-                "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
-        return;
+        ALOGE("%s: Camera %d: Unable to return to preview",
+                __FUNCTION__, mCameraId);
     }
-
-    // TODO: Should recording heap be freed? Can't do it yet since requests
-    // could still be in flight.
-
-    l.mParameters.state = Parameters::PREVIEW;
 }
 
 bool Camera2Client::recordingEnabled() {
@@ -1448,6 +1486,10 @@
     return mDevice;
 }
 
+const sp<CameraService>& Camera2Client::getCameraService() {
+    return mCameraService;
+}
+
 camera2::SharedParameters& Camera2Client::getParameters() {
     return mParameters;
 }
@@ -1612,7 +1654,7 @@
 
 /** Utility methods */
 
-status_t Camera2Client::updateRequests(const Parameters &params) {
+status_t Camera2Client::updateRequests(Parameters &params) {
     status_t res;
 
     res = updatePreviewRequest(params);
@@ -1629,7 +1671,7 @@
     }
 
     if (params.state == Parameters::PREVIEW) {
-        res = mDevice->setStreamingRequest(mPreviewRequest);
+        res = startPreviewL(params, true);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error streaming new preview request: %s (%d)",
                     __FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index df5dbf4..1eb024a 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -99,6 +99,7 @@
 
     int getCameraId() const;
     const sp<Camera2Device>& getCameraDevice();
+    const sp<CameraService>& getCameraService();
     camera2::SharedParameters& getParameters();
 
     int getPreviewStreamId() const;
@@ -176,7 +177,7 @@
     /** Camera device-related private members */
 
     void     setPreviewCallbackFlagL(Parameters &params, int flag);
-    status_t updateRequests(const Parameters &params);
+    status_t updateRequests(Parameters &params);
 
     // Used with stream IDs
     static const int NO_STREAM = -1;
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index bccb18e..ca917f2 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -39,6 +39,7 @@
 
 CallbackProcessor::~CallbackProcessor() {
     ALOGV("%s: Exit", __FUNCTION__);
+    deleteStream();
 }
 
 void CallbackProcessor::onFrameAvailable() {
@@ -126,6 +127,11 @@
         sp<Camera2Device> device = client->getCameraDevice();
 
         device->deleteStream(mCallbackStreamId);
+
+        mCallbackHeap.clear();
+        mCallbackWindow.clear();
+        mCallbackConsumer.clear();
+
         mCallbackStreamId = NO_STREAM;
     }
     return OK;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 532d2aa..1c42cbf 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -388,6 +388,10 @@
         return DONE;
     }
 
+    if (l.mParameters.playShutterSound) {
+        client->getCameraService()->playSound(CameraService::SOUND_SHUTTER);
+    }
+
     mTimeoutCount = kMaxTimeoutsForCaptureEnd;
     return STANDARD_CAPTURE_WAIT;
 }
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 92148ca..b230d2d 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -42,6 +42,7 @@
 
 JpegProcessor::~JpegProcessor() {
     ALOGV("%s: Exit", __FUNCTION__);
+    deleteStream();
 }
 
 void JpegProcessor::onFrameAvailable() {
@@ -142,6 +143,11 @@
         sp<Camera2Device> device = client->getCameraDevice();
 
         device->deleteStream(mCaptureStreamId);
+
+        mCaptureHeap.clear();
+        mCaptureWindow.clear();
+        mCaptureConsumer.clear();
+
         mCaptureStreamId = NO_STREAM;
     }
     return OK;
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index e71d086..509cc85 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -141,7 +141,7 @@
     } state;
 
     // Number of zoom steps to simulate
-    static const unsigned int NUM_ZOOM_STEPS = 10;
+    static const unsigned int NUM_ZOOM_STEPS = 30;
 
     // Full static camera info, object owned by someone else, such as
     // Camera2Device.
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index a39585e..ac02afc 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -58,6 +58,7 @@
 
 ZslProcessor::~ZslProcessor() {
     ALOGV("%s: Exit", __FUNCTION__);
+    deleteStream();
 }
 
 void ZslProcessor::onFrameAvailable() {
@@ -191,6 +192,10 @@
         device->deleteStream(mZslReprocessStreamId);
         mZslReprocessStreamId = NO_STREAM;
         device->deleteStream(mZslStreamId);
+
+        mZslWindow.clear();
+        mZslConsumer.clear();
+
         mZslStreamId = NO_STREAM;
     }
     return OK;