summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-09-20 14:44:20 -0700
committerEino-Ville Talvala <etalvala@google.com>2012-09-20 14:44:20 -0700
commit7adb52f9fcbe9e72ac29f89bfdabea093a0a0804 (patch)
tree8aa6bc3280a936ee593d95e1175c9ed1aa13baed /services/camera/libcameraservice
parent5f8002eacb12e4305963322ee362429de3209c86 (diff)
downloadframeworks_av-7adb52f9fcbe9e72ac29f89bfdabea093a0a0804.zip
frameworks_av-7adb52f9fcbe9e72ac29f89bfdabea093a0a0804.tar.gz
frameworks_av-7adb52f9fcbe9e72ac29f89bfdabea093a0a0804.tar.bz2
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
Diffstat (limited to 'services/camera/libcameraservice')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp35
-rw-r--r--services/camera/libcameraservice/Camera2Device.cpp85
-rw-r--r--services/camera/libcameraservice/Camera2Device.h2
3 files changed, 85 insertions, 37 deletions
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<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();
}
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<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;
}
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<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;