Camera2: Fix deadlock on shutdown due to client getting killed.

When the binder connection dies and is the only holder of a strong
pointer to the Camera2Client, disconnect is called from the
destructor. At this point, all weak pointers to Camera2Client are no
longer promotable, and lots of cleanup code paths are broken as a
result.

Rework all such code paths to not need the client pointer, and to
discard image buffers that arrive during shutdown.

Bug: 8696047
Change-Id: Ic0672ecde7c1baaf65079f925a45bd5be45f1fb3
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 9421a77..eae7461 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -135,6 +135,7 @@
 
 Camera2Client::~Camera2Client() {
     ATRACE_CALL();
+    ALOGV("~Camera2Client");
 
     mDestructionStarted = true;
 
@@ -369,6 +370,12 @@
 
     ALOGV("Camera %d: Shutting down", mCameraId);
 
+    /**
+     * disconnect() cannot call any methods that might need to promote a
+     * wp<Camera2Client>, since disconnect can be called from the destructor, at
+     * which point all such promotions will fail.
+     */
+
     stopPreviewL();
 
     {
@@ -538,7 +545,12 @@
             break;
         case Parameters::PREVIEW:
             // Already running preview - need to stop and create a new stream
-            mStreamingProcessor->stopStream();
+            res = stopStream();
+            if (res != OK) {
+                ALOGE("%s: Unable to stop preview to swap windows: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+                return res;
+            }
             state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
             break;
     }
@@ -745,7 +757,11 @@
             // no break
         case Parameters::RECORD:
         case Parameters::PREVIEW:
-            mStreamingProcessor->stopStream();
+            res = stopStream();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Can't stop 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)",
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 946cdba..77df152 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -1133,7 +1133,8 @@
 status_t Camera2Device::StreamAdapter::release() {
     ATRACE_CALL();
     status_t res;
-    ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
+    ALOGV("%s: Releasing stream %d (%d x %d, format %d)", __FUNCTION__, mId,
+            mWidth, mHeight, mFormat);
     if (mState >= ALLOCATED) {
         res = mHal2Device->ops->release_stream(mHal2Device, mId);
         if (res != OK) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2db5224..cdeb92e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -793,6 +793,7 @@
 
 // tear down the client
 CameraService::Client::~Client() {
+    ALOGV("~Client");
     mDestructionStarted = true;
 
     mCameraService->releaseSound();
@@ -820,10 +821,12 @@
 }
 
 CameraService::BasicClient::~BasicClient() {
+    ALOGV("~BasicClient");
     mDestructionStarted = true;
 }
 
 void CameraService::BasicClient::disconnect() {
+    ALOGV("BasicClient::disconnect");
     mCameraService->removeClientByRemote(mRemoteBinder);
     // client shouldn't be able to call into us anymore
     mClientPid = 0;
@@ -922,6 +925,7 @@
 
 // NOTE: function is idempotent
 void CameraService::Client::disconnect() {
+    ALOGV("Client::disconnect");
     BasicClient::disconnect();
     mCameraService->setCameraFree(mCameraId);
     mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index 30c14ef..dd37283 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -30,9 +30,11 @@
 namespace android {
 namespace camera2 {
 
-CallbackProcessor::CallbackProcessor(wp<Camera2Client> client):
+CallbackProcessor::CallbackProcessor(sp<Camera2Client> client):
         Thread(false),
         mClient(client),
+        mDevice(client->getCameraDevice()),
+        mId(client->getCameraId()),
         mCallbackAvailable(false),
         mCallbackStreamId(NO_STREAM) {
 }
@@ -56,9 +58,11 @@
 
     Mutex::Autolock l(mInputMutex);
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return OK;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     if (mCallbackConsumer == 0) {
         // Create CPU buffer queue endpoint
@@ -76,7 +80,7 @@
                 &currentWidth, &currentHeight, &currentFormat);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying callback output stream info: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -87,11 +91,11 @@
             // assuming that all existing use of old callback stream is
             // completed.
             ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
-                __FUNCTION__, client->getCameraId(), mCallbackStreamId);
+                __FUNCTION__, mId, mCallbackStreamId);
             res = device->deleteStream(mCallbackStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
-                        "for callbacks: %s (%d)", __FUNCTION__, client->getCameraId(),
+                        "for callbacks: %s (%d)", __FUNCTION__, mId,
                         strerror(-res), res);
                 return res;
             }
@@ -108,7 +112,7 @@
                 params.previewFormat, 0, &mCallbackStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -119,15 +123,24 @@
 
 status_t CallbackProcessor::deleteStream() {
     ATRACE_CALL();
+    sp<CameraDeviceBase> device;
 
-    Mutex::Autolock l(mInputMutex);
+    {
+        Mutex::Autolock l(mInputMutex);
 
-    if (mCallbackStreamId != NO_STREAM) {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return OK;
-        sp<CameraDeviceBase> device = client->getCameraDevice();
+        if (mCallbackStreamId == NO_STREAM) {
+            return OK;
+        }
+        device = mDevice.promote();
+        if (device == 0) {
+            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+            return INVALID_OPERATION;
+        }
+    }
+    device->deleteStream(mCallbackStreamId);
 
-        device->deleteStream(mCallbackStreamId);
+    {
+        Mutex::Autolock l(mInputMutex);
 
         mCallbackHeap.clear();
         mCallbackWindow.clear();
@@ -161,13 +174,32 @@
 
     do {
         sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return false;
-        res = processNewCallback(client);
+        if (client == 0) {
+            res = discardNewCallback();
+        } else {
+            res = processNewCallback(client);
+        }
     } while (res == OK);
 
     return true;
 }
 
+status_t CallbackProcessor::discardNewCallback() {
+    ATRACE_CALL();
+    status_t res;
+    CpuConsumer::LockedBuffer imgBuffer;
+    res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
+    if (res != OK) {
+        if (res != BAD_VALUE) {
+            ALOGE("%s: Camera %d: Error receiving next callback buffer: "
+                    "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
+        }
+        return res;
+    }
+    mCallbackConsumer->unlockBuffer(imgBuffer);
+    return OK;
+}
+
 status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
     ATRACE_CALL();
     status_t res;
@@ -181,12 +213,12 @@
     if (res != OK) {
         if (res != BAD_VALUE) {
             ALOGE("%s: Camera %d: Error receiving next callback buffer: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
         }
         return res;
     }
     ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__,
-            client->getCameraId());
+            mId);
 
     {
         SharedParameters::Lock l(client->getParameters());
@@ -195,7 +227,7 @@
                 && l.mParameters.state != Parameters::RECORD
                 && l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
             ALOGV("%s: Camera %d: No longer streaming",
-                    __FUNCTION__, client->getCameraId());
+                    __FUNCTION__, mId);
             mCallbackConsumer->unlockBuffer(imgBuffer);
             return OK;
         }
@@ -216,7 +248,7 @@
 
         if (imgBuffer.format != l.mParameters.previewFormat) {
             ALOGE("%s: Camera %d: Unexpected format for callback: "
-                    "%x, expected %x", __FUNCTION__, client->getCameraId(),
+                    "%x, expected %x", __FUNCTION__, mId,
                     imgBuffer.format, l.mParameters.previewFormat);
             mCallbackConsumer->unlockBuffer(imgBuffer);
             return INVALID_OPERATION;
@@ -241,7 +273,7 @@
                 "Camera2Client::CallbackHeap");
         if (mCallbackHeap->mHeap->getSize() == 0) {
             ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
-                    __FUNCTION__, client->getCameraId());
+                    __FUNCTION__, mId);
             mCallbackConsumer->unlockBuffer(imgBuffer);
             return INVALID_OPERATION;
         }
@@ -252,7 +284,7 @@
 
     if (mCallbackHeapFree == 0) {
         ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
-                __FUNCTION__, client->getCameraId());
+                __FUNCTION__, mId);
         mCallbackConsumer->unlockBuffer(imgBuffer);
         return OK;
     }
@@ -282,7 +314,7 @@
             l(client->mSharedCameraCallbacks);
         if (l.mRemoteCallback != 0) {
             ALOGV("%s: Camera %d: Invoking client data callback",
-                    __FUNCTION__, client->getCameraId());
+                    __FUNCTION__, mId);
             l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
                     mCallbackHeap->mBuffers[heapIdx], NULL);
         }
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.h b/services/camera/libcameraservice/camera2/CallbackProcessor.h
index e68bb75..1c40a03 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.h
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.h
@@ -30,6 +30,7 @@
 namespace android {
 
 class Camera2Client;
+class CameraDeviceBase;
 
 namespace camera2 {
 
@@ -39,7 +40,7 @@
 class CallbackProcessor:
             public Thread, public CpuConsumer::FrameAvailableListener {
   public:
-    CallbackProcessor(wp<Camera2Client> client);
+    CallbackProcessor(sp<Camera2Client> client);
     ~CallbackProcessor();
 
     void onFrameAvailable();
@@ -52,6 +53,8 @@
   private:
     static const nsecs_t kWaitDuration = 10000000; // 10 ms
     wp<Camera2Client> mClient;
+    wp<CameraDeviceBase> mDevice;
+    int mId;
 
     mutable Mutex mInputMutex;
     bool mCallbackAvailable;
@@ -72,7 +75,8 @@
     virtual bool threadLoop();
 
     status_t processNewCallback(sp<Camera2Client> &client);
-
+    // Used when shutting down
+    status_t discardNewCallback();
 };
 
 
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 286fac4..01d7f9c 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -35,11 +35,12 @@
 namespace camera2 {
 
 JpegProcessor::JpegProcessor(
-    wp<Camera2Client> client,
+    sp<Camera2Client> client,
     wp<CaptureSequencer> sequencer):
         Thread(false),
-        mClient(client),
+        mDevice(client->getCameraDevice()),
         mSequencer(sequencer),
+        mId(client->getCameraId()),
         mCaptureAvailable(false),
         mCaptureStreamId(NO_STREAM) {
 }
@@ -64,16 +65,18 @@
 
     Mutex::Autolock l(mInputMutex);
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return OK;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     // Find out buffer size for JPEG
     camera_metadata_ro_entry_t maxJpegSize =
             params.staticInfo(ANDROID_JPEG_MAX_SIZE);
     if (maxJpegSize.count == 0) {
         ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
-                __FUNCTION__, client->getCameraId());
+                __FUNCTION__, mId);
         return INVALID_OPERATION;
     }
 
@@ -89,7 +92,7 @@
                                        "Camera2Client::CaptureHeap");
         if (mCaptureHeap->getSize() == 0) {
             ALOGE("%s: Camera %d: Unable to allocate memory for capture",
-                    __FUNCTION__, client->getCameraId());
+                    __FUNCTION__, mId);
             return NO_MEMORY;
         }
     }
@@ -102,18 +105,18 @@
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying capture output stream info: "
                     "%s (%d)", __FUNCTION__,
-                    client->getCameraId(), strerror(-res), res);
+                    mId, strerror(-res), res);
             return res;
         }
         if (currentWidth != (uint32_t)params.pictureWidth ||
                 currentHeight != (uint32_t)params.pictureHeight) {
             ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
-                __FUNCTION__, client->getCameraId(), mCaptureStreamId);
+                __FUNCTION__, mId, mCaptureStreamId);
             res = device->deleteStream(mCaptureStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
                         "for capture: %s (%d)", __FUNCTION__,
-                        client->getCameraId(), strerror(-res), res);
+                        mId, strerror(-res), res);
                 return res;
             }
             mCaptureStreamId = NO_STREAM;
@@ -128,7 +131,7 @@
                 &mCaptureStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -143,9 +146,11 @@
     Mutex::Autolock l(mInputMutex);
 
     if (mCaptureStreamId != NO_STREAM) {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return OK;
-        sp<CameraDeviceBase> device = client->getCameraDevice();
+        sp<CameraDeviceBase> device = mDevice.promote();
+        if (device == 0) {
+            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+            return INVALID_OPERATION;
+        }
 
         device->deleteStream(mCaptureStreamId);
 
@@ -180,15 +185,13 @@
     }
 
     do {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return false;
-        res = processNewCapture(client);
+        res = processNewCapture();
     } while (res == OK);
 
     return true;
 }
 
-status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) {
+status_t JpegProcessor::processNewCapture() {
     ATRACE_CALL();
     status_t res;
     sp<Camera2Heap> captureHeap;
@@ -200,17 +203,17 @@
         if (res != BAD_VALUE) {
             ALOGE("%s: Camera %d: Error receiving still image buffer: "
                     "%s (%d)", __FUNCTION__,
-                    client->getCameraId(), strerror(-res), res);
+                    mId, strerror(-res), res);
         }
         return res;
     }
 
     ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
-            client->getCameraId());
+            mId);
 
     if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
         ALOGE("%s: Camera %d: Unexpected format for still image: "
-                "%x, expected %x", __FUNCTION__, client->getCameraId(),
+                "%x, expected %x", __FUNCTION__, mId,
                 imgBuffer.format,
                 HAL_PIXEL_FORMAT_BLOB);
         mCaptureConsumer->unlockBuffer(imgBuffer);
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.h b/services/camera/libcameraservice/camera2/JpegProcessor.h
index 74f4738..a38611c 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.h
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.h
@@ -29,6 +29,7 @@
 namespace android {
 
 class Camera2Client;
+class CameraDeviceBase;
 class MemoryHeapBase;
 
 namespace camera2 {
@@ -41,7 +42,7 @@
 class JpegProcessor:
             public Thread, public CpuConsumer::FrameAvailableListener {
   public:
-    JpegProcessor(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
+    JpegProcessor(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
     ~JpegProcessor();
 
     // CpuConsumer listener implementation
@@ -54,8 +55,9 @@
     void dump(int fd, const Vector<String16>& args) const;
   private:
     static const nsecs_t kWaitDuration = 10000000; // 10 ms
-    wp<Camera2Client> mClient;
+    wp<CameraDeviceBase> mDevice;
     wp<CaptureSequencer> mSequencer;
+    int mId;
 
     mutable Mutex mInputMutex;
     bool mCaptureAvailable;
@@ -72,7 +74,7 @@
 
     virtual bool threadLoop();
 
-    status_t processNewCapture(sp<Camera2Client> &client);
+    status_t processNewCapture();
     size_t findJpegSize(uint8_t* jpegBuffer, size_t maxSize);
 
 };
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index fbc5b93..c36cf87 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -31,8 +31,10 @@
 namespace android {
 namespace camera2 {
 
-StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
+StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
         mClient(client),
+        mDevice(client->getCameraDevice()),
+        mId(client->getCameraId()),
         mActiveRequest(NONE),
         mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
         mPreviewStreamId(NO_STREAM),
@@ -40,7 +42,6 @@
         mRecordingStreamId(NO_STREAM),
         mRecordingHeapCount(kDefaultRecordingHeapCount)
 {
-
 }
 
 StreamingProcessor::~StreamingProcessor() {
@@ -70,16 +71,19 @@
 status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
     ATRACE_CALL();
     status_t res;
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     Mutex::Autolock m(mMutex);
     if (mPreviewRequest.entryCount() == 0) {
-        res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+        res = device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                 &mPreviewRequest);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create default preview request: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
     }
@@ -87,7 +91,7 @@
     res = params.updateRequest(&mPreviewRequest);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update common entries of preview "
-                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
+                "request: %s (%d)", __FUNCTION__, mId,
                 strerror(-res), res);
         return res;
     }
@@ -96,7 +100,7 @@
             &mPreviewRequestId, 1);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update request id for preview: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
 
@@ -108,9 +112,11 @@
     Mutex::Autolock m(mMutex);
 
     status_t res;
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     if (mPreviewStreamId != NO_STREAM) {
         // Check if stream parameters have to change
@@ -119,24 +125,24 @@
                 &currentWidth, &currentHeight, 0);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying preview stream info: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
         if (currentWidth != (uint32_t)params.previewWidth ||
                 currentHeight != (uint32_t)params.previewHeight) {
             ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
-                    __FUNCTION__, client->getCameraId(), currentWidth, currentHeight,
+                    __FUNCTION__, mId, currentWidth, currentHeight,
                     params.previewWidth, params.previewHeight);
             res = device->waitUntilDrained();
             if (res != OK) {
                 ALOGE("%s: Camera %d: Error waiting for preview to drain: "
-                        "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                        "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
                 return res;
             }
             res = device->deleteStream(mPreviewStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
-                        "for preview: %s (%d)", __FUNCTION__, client->getCameraId(),
+                        "for preview: %s (%d)", __FUNCTION__, mId,
                         strerror(-res), res);
                 return res;
             }
@@ -151,7 +157,7 @@
                 &mPreviewStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
-                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
     }
@@ -160,7 +166,7 @@
             params.previewTransform);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to set preview stream transform: "
-                "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
 
@@ -174,12 +180,14 @@
     Mutex::Autolock m(mMutex);
 
     if (mPreviewStreamId != NO_STREAM) {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return INVALID_OPERATION;
-        sp<CameraDeviceBase> device = client->getCameraDevice();
+        sp<CameraDeviceBase> device = mDevice.promote();
+        if (device == 0) {
+            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+            return INVALID_OPERATION;
+        }
 
         ALOGV("%s: for cameraId %d on streamId %d",
-            __FUNCTION__, client->getCameraId(), mPreviewStreamId);
+            __FUNCTION__, mId, mPreviewStreamId);
 
         res = device->waitUntilDrained();
         if (res != OK) {
@@ -206,11 +214,9 @@
 status_t StreamingProcessor::setRecordingBufferCount(size_t count) {
     ATRACE_CALL();
     // 32 is the current upper limit on the video buffer count for BufferQueue
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
     if (count > 32) {
         ALOGE("%s: Camera %d: Error setting %d as video buffer count value",
-                __FUNCTION__, client->getCameraId(), count);
+                __FUNCTION__, mId, count);
         return BAD_VALUE;
     }
 
@@ -233,15 +239,18 @@
     status_t res;
     Mutex::Autolock m(mMutex);
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     if (mRecordingRequest.entryCount() == 0) {
-        res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
+        res = device->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
                 &mRecordingRequest);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create default recording request:"
-                    " %s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
             return res;
         }
     }
@@ -249,7 +258,7 @@
     res = params.updateRequest(&mRecordingRequest);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update common entries of recording "
-                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
+                "request: %s (%d)", __FUNCTION__, mId,
                 strerror(-res), res);
         return res;
     }
@@ -258,7 +267,7 @@
             &mRecordingRequestId, 1);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update request id for request: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
 
@@ -270,9 +279,11 @@
     status_t res;
     Mutex::Autolock m(mMutex);
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     if (mRecordingConsumer == 0) {
         // Create CPU buffer queue endpoint. We need one more buffer here so that we can
@@ -296,7 +307,7 @@
                 &currentWidth, &currentHeight, 0);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying recording output stream info: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -307,7 +318,7 @@
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
                         "for recording: %s (%d)", __FUNCTION__,
-                        client->getCameraId(), strerror(-res), res);
+                        mId, strerror(-res), res);
                 return res;
             }
             mRecordingStreamId = NO_STREAM;
@@ -321,7 +332,7 @@
                 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -337,9 +348,11 @@
     Mutex::Autolock m(mMutex);
 
     if (mRecordingStreamId != NO_STREAM) {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return INVALID_OPERATION;
-        sp<CameraDeviceBase> device = client->getCameraDevice();
+        sp<CameraDeviceBase> device = mDevice.promote();
+        if (device == 0) {
+            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+            return INVALID_OPERATION;
+        }
 
         res = device->waitUntilDrained();
         if (res != OK) {
@@ -369,10 +382,13 @@
 
     if (type == NONE) return INVALID_OPERATION;
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
+    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: type = %d", __FUNCTION__, client->getCameraId(), type);
+    ALOGV("%s: Camera %d: type = %d", __FUNCTION__, mId, type);
 
     Mutex::Autolock m(mMutex);
 
@@ -384,22 +400,22 @@
         outputStreams);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
 
     res = request.sort();
     if (res != OK) {
         ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
 
-    res = client->getCameraDevice()->setStreamingRequest(request);
+    res = device->setStreamingRequest(request);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
                 "%s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
     mActiveRequest = type;
@@ -413,16 +429,19 @@
 
     Mutex::Autolock m(mMutex);
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return INVALID_OPERATION;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     res = device->clearStreamingRequest();
     if (res != OK) {
         ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
+
     mActiveRequest = NONE;
 
     return OK;
@@ -466,7 +485,18 @@
     nsecs_t timestamp;
 
     sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return;
+    if (client == 0) {
+        // Discard frames during shutdown
+        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;
+        }
+        mRecordingConsumer->releaseBuffer(imgBuffer);
+        return;
+    }
 
     {
         /* acquire SharedParameters before mMutex so we don't dead lock
@@ -477,7 +507,7 @@
         res = mRecordingConsumer->acquireBuffer(&imgBuffer);
         if (res != OK) {
             ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
-                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                    __FUNCTION__, mId, strerror(-res), res);
             return;
         }
         timestamp = imgBuffer.mTimestamp;
@@ -490,7 +520,7 @@
                 l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
             ALOGV("%s: Camera %d: Discarding recording image buffers "
                     "received after recording done", __FUNCTION__,
-                    client->getCameraId());
+                    mId);
             mRecordingConsumer->releaseBuffer(imgBuffer);
             return;
         }
@@ -498,14 +528,14 @@
         if (mRecordingHeap == 0) {
             const size_t bufferSize = 4 + sizeof(buffer_handle_t);
             ALOGV("%s: Camera %d: Creating recording heap with %d buffers of "
-                    "size %d bytes", __FUNCTION__, client->getCameraId(),
+                    "size %d bytes", __FUNCTION__, mId,
                     mRecordingHeapCount, bufferSize);
 
             mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount,
                     "Camera2Client::RecordingHeap");
             if (mRecordingHeap->mHeap->getSize() == 0) {
                 ALOGE("%s: Camera %d: Unable to allocate memory for recording",
-                        __FUNCTION__, client->getCameraId());
+                        __FUNCTION__, mId);
                 mRecordingConsumer->releaseBuffer(imgBuffer);
                 return;
             }
@@ -513,7 +543,7 @@
                 if (mRecordingBuffers[i].mBuf !=
                         BufferItemConsumer::INVALID_BUFFER_SLOT) {
                     ALOGE("%s: Camera %d: Non-empty recording buffers list!",
-                            __FUNCTION__, client->getCameraId());
+                            __FUNCTION__, mId);
                 }
             }
             mRecordingBuffers.clear();
@@ -526,7 +556,7 @@
 
         if ( mRecordingHeapFree == 0) {
             ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
-                    __FUNCTION__, client->getCameraId());
+                    __FUNCTION__, mId);
             mRecordingConsumer->releaseBuffer(imgBuffer);
             return;
         }
@@ -536,7 +566,7 @@
         mRecordingHeapFree--;
 
         ALOGV("%s: Camera %d: Timestamp %lld",
-                __FUNCTION__, client->getCameraId(), timestamp);
+                __FUNCTION__, mId, timestamp);
 
         ssize_t offset;
         size_t size;
@@ -549,7 +579,7 @@
         *((uint32_t*)data) = type;
         *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
         ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
-                __FUNCTION__, client->getCameraId(),
+                __FUNCTION__, mId,
                 imgBuffer.mGraphicBuffer->handle);
         mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
         recordingHeap = mRecordingHeap;
@@ -568,9 +598,6 @@
     ATRACE_CALL();
     status_t res;
 
-    sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return;
-
     Mutex::Autolock m(mMutex);
     // Make sure this is for the current heap
     ssize_t offset;
@@ -578,7 +605,7 @@
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
     if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) {
         ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release "
-                "(got %x, expected %x)", __FUNCTION__, client->getCameraId(),
+                "(got %x, expected %x)", __FUNCTION__, mId,
                 heap->getHeapID(), mRecordingHeap->mHeap->getHeapID());
         return;
     }
@@ -586,7 +613,7 @@
     uint32_t type = *(uint32_t*)data;
     if (type != kMetadataBufferTypeGrallocSource) {
         ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)",
-                __FUNCTION__, client->getCameraId(), type,
+                __FUNCTION__, mId, type,
                 kMetadataBufferTypeGrallocSource);
         return;
     }
@@ -606,19 +633,19 @@
     }
     if (itemIndex == mRecordingBuffers.size()) {
         ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
-                "outstanding buffers", __FUNCTION__, client->getCameraId(),
+                "outstanding buffers", __FUNCTION__, mId,
                 imgHandle);
         return;
     }
 
     ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__,
-            client->getCameraId(), imgHandle);
+            mId, imgHandle);
 
     res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to free recording frame "
                 "(buffer_handle_t: %p): %s (%d)", __FUNCTION__,
-                client->getCameraId(), imgHandle, strerror(-res), res);
+                mId, imgHandle, strerror(-res), res);
         return;
     }
     mRecordingBuffers.replaceAt(itemIndex);
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index e5732ad..643114e 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -27,6 +27,7 @@
 namespace android {
 
 class Camera2Client;
+class CameraDeviceBase;
 class IMemory;
 
 namespace camera2 {
@@ -38,7 +39,7 @@
  */
 class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
   public:
-    StreamingProcessor(wp<Camera2Client> client);
+    StreamingProcessor(sp<Camera2Client> client);
     ~StreamingProcessor();
 
     status_t setPreviewWindow(sp<ANativeWindow> window);
@@ -86,6 +87,8 @@
     };
 
     wp<Camera2Client> mClient;
+    wp<CameraDeviceBase> mDevice;
+    int mId;
 
     StreamType mActiveRequest;
 
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 769d9bd..2c12fb0 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -38,12 +38,14 @@
 namespace camera2 {
 
 ZslProcessor::ZslProcessor(
-    wp<Camera2Client> client,
+    sp<Camera2Client> client,
     wp<CaptureSequencer> sequencer):
         Thread(false),
         mState(RUNNING),
         mClient(client),
+        mDevice(client->getCameraDevice()),
         mSequencer(sequencer),
+        mId(client->getCameraId()),
         mZslBufferAvailable(false),
         mZslStreamId(NO_STREAM),
         mZslReprocessStreamId(NO_STREAM),
@@ -69,7 +71,8 @@
     }
 }
 
-void ZslProcessor::onFrameAvailable(int32_t /*frameId*/, const CameraMetadata &frame) {
+void ZslProcessor::onFrameAvailable(int32_t /*frameId*/,
+        const CameraMetadata &frame) {
     Mutex::Autolock l(mInputMutex);
     camera_metadata_ro_entry_t entry;
     entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
@@ -113,8 +116,15 @@
     Mutex::Autolock l(mInputMutex);
 
     sp<Camera2Client> client = mClient.promote();
-    if (client == 0) return OK;
-    sp<CameraDeviceBase> device = client->getCameraDevice();
+    if (client == 0) {
+        ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
+    sp<CameraDeviceBase> device = mDevice.promote();
+    if (device == 0) {
+        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     if (mZslConsumer == 0) {
         // Create CPU buffer queue endpoint
@@ -136,7 +146,7 @@
         if (res != OK) {
             ALOGE("%s: Camera %d: Error querying capture output stream info: "
                     "%s (%d)", __FUNCTION__,
-                    client->getCameraId(), strerror(-res), res);
+                    mId, strerror(-res), res);
             return res;
         }
         if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
@@ -145,16 +155,16 @@
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old reprocess stream "
                         "for ZSL: %s (%d)", __FUNCTION__,
-                        client->getCameraId(), strerror(-res), res);
+                        mId, strerror(-res), res);
                 return res;
             }
             ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
-                __FUNCTION__, client->getCameraId(), mZslStreamId);
+                __FUNCTION__, mId, mZslStreamId);
             res = device->deleteStream(mZslStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
                         "for ZSL: %s (%d)", __FUNCTION__,
-                        client->getCameraId(), strerror(-res), res);
+                        mId, strerror(-res), res);
                 return res;
             }
             mZslStreamId = NO_STREAM;
@@ -173,7 +183,7 @@
                 &mZslStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -181,7 +191,7 @@
                 &mZslReprocessStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create reprocess stream for ZSL: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     strerror(-res), res);
             return res;
         }
@@ -200,14 +210,18 @@
     Mutex::Autolock l(mInputMutex);
 
     if (mZslStreamId != NO_STREAM) {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return OK;
-        sp<CameraDeviceBase> device = client->getCameraDevice();
+        sp<CameraDeviceBase> device = mDevice.promote();
+        if (device == 0) {
+            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+            return INVALID_OPERATION;
+        }
+
+        clearZslQueueLocked();
 
         res = device->deleteReprocessStream(mZslReprocessStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Cannot delete ZSL reprocessing stream %d: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     mZslReprocessStreamId, strerror(-res), res);
             return res;
         }
@@ -216,7 +230,7 @@
         res = device->deleteStream(mZslStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Cannot delete ZSL output stream %d: "
-                    "%s (%d)", __FUNCTION__, client->getCameraId(),
+                    "%s (%d)", __FUNCTION__, mId,
                     mZslStreamId, strerror(-res), res);
             return res;
         }
@@ -246,7 +260,10 @@
     status_t res;
     sp<Camera2Client> client = mClient.promote();
 
-    if (client == 0) return INVALID_OPERATION;
+    if (client == 0) {
+        ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);
+        return INVALID_OPERATION;
+    }
 
     IF_ALOGV() {
         dumpZslQueue(-1);
@@ -309,7 +326,7 @@
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
                 "%s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+                __FUNCTION__, mId, strerror(-res), res);
             return INVALID_OPERATION;
         }
         // TODO: have push-and-clear be atomic
@@ -328,7 +345,7 @@
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to update JPEG entries of ZSL "
                         "capture request: %s (%d)", __FUNCTION__,
-                        client->getCameraId(),
+                        mId,
                         strerror(-res), res);
                 return res;
             }
@@ -397,26 +414,29 @@
     }
 
     do {
-        sp<Camera2Client> client = mClient.promote();
-        if (client == 0) return false;
-        res = processNewZslBuffer(client);
+        res = processNewZslBuffer();
     } while (res == OK);
 
     return true;
 }
 
-status_t ZslProcessor::processNewZslBuffer(sp<Camera2Client> &client) {
+status_t ZslProcessor::processNewZslBuffer() {
     ATRACE_CALL();
     status_t res;
-
+    sp<BufferItemConsumer> zslConsumer;
+    {
+        Mutex::Autolock l(mInputMutex);
+        if (mZslConsumer == 0) return OK;
+        zslConsumer = mZslConsumer;
+    }
     ALOGVV("Trying to get next buffer");
     BufferItemConsumer::BufferItem item;
-    res = mZslConsumer->acquireBuffer(&item);
+    res = zslConsumer->acquireBuffer(&item);
     if (res != OK) {
         if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
             ALOGE("%s: Camera %d: Error receiving ZSL image buffer: "
                     "%s (%d)", __FUNCTION__,
-                    client->getCameraId(), strerror(-res), res);
+                    mId, strerror(-res), res);
         } else {
             ALOGVV("  No buffer");
         }
@@ -427,7 +447,7 @@
 
     if (mState == LOCKED) {
         ALOGVV("In capture, discarding new ZSL buffers");
-        mZslConsumer->releaseBuffer(item);
+        zslConsumer->releaseBuffer(item);
         return OK;
     }
 
@@ -435,7 +455,7 @@
 
     if ( (mZslQueueHead + 1) % kZslBufferDepth == mZslQueueTail) {
         ALOGVV("Releasing oldest buffer");
-        mZslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer);
+        zslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer);
         mZslQueue.replaceAt(mZslQueueTail);
         mZslQueueTail = (mZslQueueTail + 1) % kZslBufferDepth;
     }
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index b2cf5b1..ee3bcd6 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -46,7 +46,7 @@
             virtual public FrameProcessor::FilteredListener,
             virtual public CameraDeviceBase::BufferReleasedListener {
   public:
-    ZslProcessor(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
+    ZslProcessor(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
     ~ZslProcessor();
 
     // From mZslConsumer
@@ -74,7 +74,9 @@
     } mState;
 
     wp<Camera2Client> mClient;
+    wp<CameraDeviceBase> mDevice;
     wp<CaptureSequencer> mSequencer;
+    int mId;
 
     mutable Mutex mInputMutex;
     bool mZslBufferAvailable;
@@ -109,7 +111,7 @@
 
     virtual bool threadLoop();
 
-    status_t processNewZslBuffer(sp<Camera2Client> &client);
+    status_t processNewZslBuffer();
 
     // Match up entries from frame list to buffers in ZSL queue
     void findMatchesLocked();