OSDN Git Service

Camera2: Clean up startup/shutdown sequences.
authorEino-Ville Talvala <etalvala@google.com>
Thu, 20 Sep 2012 21:44:20 +0000 (14:44 -0700)
committerThe Android Automerger <android-build@android.com>
Fri, 21 Sep 2012 00:52:10 +0000 (17:52 -0700)
- Close camera device on startup errors

- Make sure all threads are shut down and the device is closed before
  returning from ICamera::disconnect.

Bug: 7172680
Change-Id: I98611448ec5f2311e6604fa8ee5f9dde7bfdd988

services/camera/libcameraservice/Camera2Client.cpp
services/camera/libcameraservice/Camera2Device.cpp
services/camera/libcameraservice/Camera2Device.h

index 4fad83e..495feda 100644 (file)
@@ -137,7 +137,6 @@ status_t Camera2Client::initialize(camera_module_t *module)
 
 Camera2Client::~Camera2Client() {
     ATRACE_CALL();
-    ALOGV("Camera %d: Shutting down", mCameraId);
 
     mDestructionStarted = true;
 
@@ -145,12 +144,6 @@ Camera2Client::~Camera2Client() {
     mClientPid = getCallingPid();
     disconnect();
 
-    mFrameProcessor->requestExit();
-    mCaptureSequencer->requestExit();
-    mJpegProcessor->requestExit();
-    mZslProcessor->requestExit();
-    mCallbackProcessor->requestExit();
-
     ALOGI("Camera %d: Closed", mCameraId);
 }
 
@@ -365,15 +358,21 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
 
 void Camera2Client::disconnect() {
     ATRACE_CALL();
-    ALOGV("%s: E", __FUNCTION__);
     Mutex::Autolock icl(mICameraLock);
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return;
 
     if (mDevice == 0) return;
 
+    ALOGV("Camera %d: Shutting down", mCameraId);
+
     stopPreviewL();
 
+    {
+        SharedParameters::Lock l(mParameters);
+        l.mParameters.state = Parameters::DISCONNECTED;
+    }
+
     if (mPreviewStreamId != NO_STREAM) {
         mDevice->deleteStream(mPreviewStreamId);
         mPreviewStreamId = NO_STREAM;
@@ -390,9 +389,25 @@ void Camera2Client::disconnect() {
 
     mZslProcessor->deleteStream();
 
+    mFrameProcessor->requestExit();
+    mCaptureSequencer->requestExit();
+    mJpegProcessor->requestExit();
+    mZslProcessor->requestExit();
+    mCallbackProcessor->requestExit();
+
+    ALOGV("Camera %d: Waiting for threads", mCameraId);
+
+    mFrameProcessor->join();
+    mCaptureSequencer->join();
+    mJpegProcessor->join();
+    mZslProcessor->join();
+    mCallbackProcessor->join();
+
+    ALOGV("Camera %d: Disconnecting device", mCameraId);
+
+    mDevice->disconnect();
+
     mDevice.clear();
-    SharedParameters::Lock l(mParameters);
-    l.mParameters.state = Parameters::DISCONNECTED;
 
     CameraService::Client::disconnect();
 }
index a171c46..81c0496 100644 (file)
@@ -38,30 +38,25 @@ Camera2Device::Camera2Device(int id):
 
 Camera2Device::~Camera2Device()
 {
-    ALOGV("%s: Shutting down device for camera %d", __FUNCTION__, mId);
-    if (mDevice) {
-        status_t res;
-        res = mDevice->common.close(&mDevice->common);
-        if (res != OK) {
-            ALOGE("%s: Could not close camera %d: %s (%d)",
-                    __FUNCTION__,
-                    mId, strerror(-res), res);
-        }
-        mDevice = NULL;
-    }
-    ALOGV("%s: Shutdown complete", __FUNCTION__);
+    disconnect();
 }
 
 status_t Camera2Device::initialize(camera_module_t *module)
 {
     ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
+    if (mDevice != NULL) {
+        ALOGE("%s: Already initialized!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
 
     status_t res;
     char name[10];
     snprintf(name, sizeof(name), "%d", mId);
 
+    camera2_device_t *device;
+
     res = module->common.methods->open(&module->common, name,
-            reinterpret_cast<hw_device_t**>(&mDevice));
+            reinterpret_cast<hw_device_t**>(&device));
 
     if (res != OK) {
         ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -69,11 +64,12 @@ status_t Camera2Device::initialize(camera_module_t *module)
         return res;
     }
 
-    if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
+    if (device->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
         ALOGE("%s: Could not open camera %d: "
                 "Camera device is not version %x, reports %x instead",
                 __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
-                mDevice->common.version);
+                device->common.version);
+        device->common.close(&device->common);
         return BAD_VALUE;
     }
 
@@ -81,45 +77,81 @@ status_t Camera2Device::initialize(camera_module_t *module)
     res = module->get_camera_info(mId, &info);
     if (res != OK ) return res;
 
-    if (info.device_version != mDevice->common.version) {
+    if (info.device_version != device->common.version) {
         ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
                 " and device version (%x).", __FUNCTION__,
-                mDevice->common.version, info.device_version);
+                device->common.version, info.device_version);
+        device->common.close(&device->common);
         return BAD_VALUE;
     }
 
-    mDeviceInfo = info.static_camera_characteristics;
-
-    res = mRequestQueue.setConsumerDevice(mDevice);
+    res = mRequestQueue.setConsumerDevice(device);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
                 __FUNCTION__, mId, strerror(-res), res);
+        device->common.close(&device->common);
         return res;
     }
-    res = mFrameQueue.setProducerDevice(mDevice);
+    res = mFrameQueue.setProducerDevice(device);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
                 __FUNCTION__, mId, strerror(-res), res);
+        device->common.close(&device->common);
         return res;
     }
 
-    res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
+    res = device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps);
     if (res != OK ) {
         ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
                 __FUNCTION__, mId, strerror(-res), res);
+        device->common.close(&device->common);
         return res;
     }
     res = set_camera_metadata_vendor_tag_ops(mVendorTagOps);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
             __FUNCTION__, mId, strerror(-res), res);
+        device->common.close(&device->common);
+        return res;
+    }
+    res = device->ops->set_notify_callback(device, notificationCallback,
+            NULL);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to initialize notification callback!",
+                __FUNCTION__, mId);
+        device->common.close(&device->common);
         return res;
     }
-    setNotifyCallback(NULL);
+
+    mDeviceInfo = info.static_camera_characteristics;
+    mDevice = device;
 
     return OK;
 }
 
+status_t Camera2Device::disconnect() {
+    status_t res = OK;
+    if (mDevice) {
+        ALOGV("%s: Closing device for camera %d", __FUNCTION__, mId);
+
+        int inProgressCount = mDevice->ops->get_in_progress_count(mDevice);
+        if (inProgressCount > 0) {
+            ALOGW("%s: Closing camera device %d with %d requests in flight!",
+                    __FUNCTION__, mId, inProgressCount);
+        }
+        mStreams.clear();
+        res = mDevice->common.close(&mDevice->common);
+        if (res != OK) {
+            ALOGE("%s: Could not close camera %d: %s (%d)",
+                    __FUNCTION__,
+                    mId, strerror(-res), res);
+        }
+        mDevice = NULL;
+        ALOGV("%s: Shutdown complete", __FUNCTION__);
+    }
+    return res;
+}
+
 status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
 
     String8 result;
@@ -354,7 +386,7 @@ status_t Camera2Device::createDefaultRequest(int templateId,
 status_t Camera2Device::waitUntilDrained() {
     static const uint32_t kSleepTime = 50000; // 50 ms
     static const uint32_t kMaxSleepTime = 10000000; // 10 s
-    ALOGV("%s: E", __FUNCTION__);
+    ALOGV("%s: Camera %d: Starting wait", __FUNCTION__, mId);
     if (mRequestQueue.getBufferCount() ==
             CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
 
@@ -364,11 +396,12 @@ status_t Camera2Device::waitUntilDrained() {
         usleep(kSleepTime);
         totalTime += kSleepTime;
         if (totalTime > kMaxSleepTime) {
-            ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
-                    totalTime);
+            ALOGE("%s: Waited %d us, %d requests still in flight", __FUNCTION__,
+                    mDevice->ops->get_in_progress_count(mDevice), totalTime);
             return TIMED_OUT;
         }
     }
+    ALOGV("%s: Camera %d: HAL is idle", __FUNCTION__, mId);
     return OK;
 }
 
index a327d8d..38662e3 100644 (file)
@@ -40,6 +40,7 @@ class Camera2Device : public virtual RefBase {
     ~Camera2Device();
 
     status_t initialize(camera_module_t *module);
+    status_t disconnect();
 
     status_t dump(int fd, const Vector<String16>& args);
 
@@ -191,7 +192,6 @@ class Camera2Device : public virtual RefBase {
             buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
 
   private:
-
     const int mId;
     camera2_device_t *mDevice;