From b25e3c87724b6147ed1da7c1d6617c39bfce2fbf Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Wed, 15 Jul 2015 16:04:27 -0700 Subject: Camera: Add hidden experimental tearDown method. Bug: 18949148 Change-Id: Ie86ec7d1ec3db54e1154563b2339a208a935f849 --- .../libcameraservice/device3/Camera3Device.cpp | 31 ++++++++++++ .../libcameraservice/device3/Camera3Device.h | 2 + .../libcameraservice/device3/Camera3Stream.cpp | 55 ++++++++++++++++++++++ .../libcameraservice/device3/Camera3Stream.h | 14 ++++++ .../device3/Camera3StreamInterface.h | 14 ++++++ 5 files changed, 116 insertions(+) (limited to 'services/camera/libcameraservice/device3') diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 9e73b5c..3afbd89 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1384,6 +1384,37 @@ status_t Camera3Device::prepare(int streamId) { return mPreparerThread->prepare(stream); } +status_t Camera3Device::tearDown(int streamId) { + ATRACE_CALL(); + ALOGV("%s: Camera %d: Tearing down stream %d", __FUNCTION__, mId, streamId); + Mutex::Autolock il(mInterfaceLock); + Mutex::Autolock l(mLock); + + // Teardown can only be accomplished on devices that don't require register_stream_buffers, + // since we cannot call register_stream_buffers except right after configure_streams. + if (mHal3Device->common.version < CAMERA_DEVICE_API_VERSION_3_2) { + ALOGE("%s: Unable to tear down streams on device HAL v%x", + __FUNCTION__, mHal3Device->common.version); + return NO_INIT; + } + + sp stream; + ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId); + if (outputStreamIdx == NAME_NOT_FOUND) { + CLOGE("Stream %d does not exist", streamId); + return BAD_VALUE; + } + + stream = mOutputStreams.editValueAt(outputStreamIdx); + + if (stream->hasOutstandingBuffers() || mRequestThread->isStreamPending(stream)) { + CLOGE("Stream %d is a target of a in-progress request", streamId); + return BAD_VALUE; + } + + return stream->tearDown(); +} + uint32_t Camera3Device::getDeviceVersion() { ATRACE_CALL(); Mutex::Autolock il(mInterfaceLock); diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 31b6132..140da98 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -141,6 +141,8 @@ class Camera3Device : virtual status_t prepare(int streamId); + virtual status_t tearDown(int streamId); + virtual uint32_t getDeviceVersion(); virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const; diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp index 4c40bb6..2527fd6 100644 --- a/services/camera/libcameraservice/device3/Camera3Stream.cpp +++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp @@ -364,6 +364,61 @@ status_t Camera3Stream::cancelPrepareLocked() { return res; } +status_t Camera3Stream::tearDown() { + ATRACE_CALL(); + Mutex::Autolock l(mLock); + + status_t res = OK; + + // This function should be only called when the stream is configured. + if (mState != STATE_CONFIGURED) { + ALOGE("%s: Stream %d: Can't tear down stream if stream is not in " + "CONFIGURED state %d", __FUNCTION__, mId, mState); + return INVALID_OPERATION; + } + + // If any buffers have been handed to the HAL, the stream cannot be torn down. + if (getHandoutOutputBufferCountLocked() > 0) { + ALOGE("%s: Stream %d: Can't tear down a stream that has outstanding buffers", + __FUNCTION__, mId); + return INVALID_OPERATION; + } + + // Free buffers by disconnecting and then reconnecting to the buffer queue + // Only unused buffers will be dropped immediately; buffers that have been filled + // and are waiting to be acquired by the consumer and buffers that are currently + // acquired will be freed once they are released by the consumer. + + res = disconnectLocked(); + if (res != OK) { + if (res == -ENOTCONN) { + // queue has been disconnected, nothing left to do, so exit with success + return OK; + } + ALOGE("%s: Stream %d: Unable to disconnect to tear down buffers: %s (%d)", + __FUNCTION__, mId, strerror(-res), res); + return res; + } + + mState = STATE_IN_CONFIG; + + res = configureQueueLocked(); + if (res != OK) { + ALOGE("%s: Unable to configure stream %d queue: %s (%d)", + __FUNCTION__, mId, strerror(-res), res); + mState = STATE_ERROR; + return res; + } + + // Reset prepared state, since we've reconnected to the queue and can prepare again. + mPrepared = false; + mStreamUnpreparable = false; + + mState = STATE_CONFIGURED; + + return OK; +} + status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) { ATRACE_CALL(); Mutex::Autolock l(mLock); diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h index 0543c66..bab2177 100644 --- a/services/camera/libcameraservice/device3/Camera3Stream.h +++ b/services/camera/libcameraservice/device3/Camera3Stream.h @@ -247,6 +247,20 @@ class Camera3Stream : status_t cancelPrepare(); /** + * Tear down memory for this stream. This frees all unused gralloc buffers + * allocated for this stream, but leaves it ready for operation afterward. + * + * May only be called in the CONFIGURED state, and keeps the stream in + * the CONFIGURED state. + * + * Returns: + * OK if teardown succeeded. + * INVALID_OPERATION if not in the CONFIGURED state + * NO_INIT in case of a serious error from the HAL device + */ + status_t tearDown(); + + /** * Fill in the camera3_stream_buffer with the next valid buffer for this * stream, to hand over to the HAL. * diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h index 6c87a45..c086eaf 100644 --- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h +++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h @@ -152,6 +152,20 @@ class Camera3StreamInterface : public virtual RefBase { virtual status_t cancelPrepare() = 0; /** + * Tear down memory for this stream. This frees all unused gralloc buffers + * allocated for this stream, but leaves it ready for operation afterward. + * + * May only be called in the CONFIGURED state, and keeps the stream in + * the CONFIGURED state. + * + * Returns: + * OK if teardown succeeded. + * INVALID_OPERATION if not in the CONFIGURED state + * NO_INIT in case of a serious error from the HAL device + */ + virtual status_t tearDown() = 0; + + /** * Fill in the camera3_stream_buffer with the next valid buffer for this * stream, to hand over to the HAL. * -- cgit v1.1