From 7adb52f9fcbe9e72ac29f89bfdabea093a0a0804 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Thu, 20 Sep 2012 14:44:20 -0700 Subject: Camera2: Clean up startup/shutdown sequences. - 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 | 35 ++++++--- services/camera/libcameraservice/Camera2Device.cpp | 85 +++++++++++++++------- services/camera/libcameraservice/Camera2Device.h | 2 +- 3 files changed, 85 insertions(+), 37 deletions(-) (limited to 'services/camera/libcameraservice') diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 4fad83e..495feda 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -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& 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(); } diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp index a171c46..81c0496 100644 --- a/services/camera/libcameraservice/Camera2Device.cpp +++ b/services/camera/libcameraservice/Camera2Device.cpp @@ -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(&mDevice)); + reinterpret_cast(&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& 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; } diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h index a327d8d..38662e3 100644 --- a/services/camera/libcameraservice/Camera2Device.h +++ b/services/camera/libcameraservice/Camera2Device.h @@ -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& args); @@ -191,7 +192,6 @@ class Camera2Device : public virtual RefBase { buffer_handle_t *buffer, wp listener); private: - const int mId; camera2_device_t *mDevice; -- cgit v1.1