diff options
| author | Eino-Ville Talvala <etalvala@google.com> | 2015-07-15 16:04:27 -0700 | 
|---|---|---|
| committer | Eino-Ville Talvala <etalvala@google.com> | 2015-07-16 14:55:33 -0700 | 
| commit | b25e3c87724b6147ed1da7c1d6617c39bfce2fbf (patch) | |
| tree | c0e95e487b2583b8ba87e2ce5505fb74dec9d2d8 /services/camera | |
| parent | 1bc88814f530bf67e425cfb8cea0f2b8dce3c03f (diff) | |
| download | frameworks_av-b25e3c87724b6147ed1da7c1d6617c39bfce2fbf.zip frameworks_av-b25e3c87724b6147ed1da7c1d6617c39bfce2fbf.tar.gz frameworks_av-b25e3c87724b6147ed1da7c1d6617c39bfce2fbf.tar.bz2  | |
Camera: Add hidden experimental tearDown method.
Bug: 18949148
Change-Id: Ie86ec7d1ec3db54e1154563b2339a208a935f849
Diffstat (limited to 'services/camera')
10 files changed, 164 insertions, 1 deletions
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 3b83f63..c717a56 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -719,6 +719,38 @@ status_t CameraDeviceClient::prepare(int streamId) {      return res;  } +status_t CameraDeviceClient::tearDown(int streamId) { +    ATRACE_CALL(); +    ALOGV("%s", __FUNCTION__); + +    status_t res = OK; +    if ( (res = checkPid(__FUNCTION__) ) != OK) return res; + +    Mutex::Autolock icl(mBinderSerializationLock); + +    // Guard against trying to prepare non-created streams +    ssize_t index = NAME_NOT_FOUND; +    for (size_t i = 0; i < mStreamMap.size(); ++i) { +        if (streamId == mStreamMap.valueAt(i)) { +            index = i; +            break; +        } +    } + +    if (index == NAME_NOT_FOUND) { +        ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream " +              "created yet", __FUNCTION__, mCameraId, streamId); +        return BAD_VALUE; +    } + +    // Also returns BAD_VALUE if stream ID was not valid or if the stream is in +    // use +    res = mDevice->tearDown(streamId); + +    return res; +} + +  status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {      String8 result;      result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n", diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index 0f485ca..1f8b39d 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -111,6 +111,9 @@ public:      // Prepare stream by preallocating its buffers      virtual status_t      prepare(int streamId); +    // Tear down stream resources by freeing its unused buffers +    virtual status_t      tearDown(int streamId); +      /**       * Interface used by CameraService       */ diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h index 06177e3..cd25949 100644 --- a/services/camera/libcameraservice/common/CameraDeviceBase.h +++ b/services/camera/libcameraservice/common/CameraDeviceBase.h @@ -289,6 +289,11 @@ class CameraDeviceBase : public virtual RefBase {      virtual status_t prepare(int streamId) = 0;      /** +     * Free stream resources by dumping its unused gralloc buffers. +     */ +    virtual status_t tearDown(int streamId) = 0; + +    /**       * Get the HAL device version.       */      virtual uint32_t getDeviceVersion() = 0; diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp index dfe5565..c9c990c 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.cpp +++ b/services/camera/libcameraservice/device2/Camera2Device.cpp @@ -626,6 +626,12 @@ status_t Camera2Device::prepare(int streamId) {      return NO_INIT;  } +status_t Camera2Device::tearDown(int streamId) { +    ATRACE_CALL(); +    ALOGE("%s: Camera %d: unimplemented", __FUNCTION__, mId); +    return NO_INIT; +} +  uint32_t Camera2Device::getDeviceVersion() {      ATRACE_CALL();      return mDeviceVersion; diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h index c9f3a2c..34c1ded 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.h +++ b/services/camera/libcameraservice/device2/Camera2Device.h @@ -85,8 +85,9 @@ class Camera2Device: public CameraDeviceBase {              buffer_handle_t *buffer, wp<BufferReleasedListener> listener);      // Flush implemented as just a wait      virtual status_t flush(int64_t *lastFrameNumber = NULL); -    // Prepare is a no-op +    // Prepare and tearDown are no-ops      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/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<Camera3StreamInterface> 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.       *  | 
