From 7447f0fc15347d0fe4d5cda256fe680c50391a93 Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Thu, 11 Oct 2018 15:28:12 -0700 Subject: [PATCH] Camera: implement signalPipelineDrain API SignalPipelineDrain will be sent after the request thread has stopped sending capture requests so HAL can expect no more capture requests are sent after they receive this call. Test: CTS Bug: 109829698 Change-Id: I6f75c28ff0998a8edc80f9af9ebe727c585ea6e9 --- .../device3/Camera3Device.cpp | 106 +++++++++++++++--- .../libcameraservice/device3/Camera3Device.h | 12 +- 2 files changed, 102 insertions(+), 16 deletions(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 04d3639283..f829b65eea 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1619,6 +1619,15 @@ void Camera3Device::StreamSet::clear() { return mData.clear(); } +std::vector Camera3Device::StreamSet::getStreamIds() { + std::lock_guard lock(mLock); + std::vector streamIds(mData.size()); + for (size_t i = 0; i < mData.size(); i++) { + streamIds[i] = mData.keyAt(i); + } + return streamIds; +} + status_t Camera3Device::createStream(sp consumer, uint32_t width, uint32_t height, int format, android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id, @@ -2130,6 +2139,12 @@ status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) { break; } + // Notify HAL to start draining + if (!active && mUseHalBufManager) { + auto streamIds = mOutputStreams.getStreamIds(); + mRequestThread->signalPipelineDrain(streamIds); + } + res = mStatusChanged.waitRelative(mLock, timeout); if (res != OK) break; @@ -3902,26 +3917,49 @@ status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t * // Invoke configureStreams device::V3_3::HalStreamConfiguration finalConfiguration; + device::V3_4::HalStreamConfiguration finalConfiguration3_4; common::V1_0::Status status; - // See if we have v3.4 or v3.3 HAL - if (mHidlSession_3_4 != nullptr) { - // We do; use v3.4 for the call - ALOGV("%s: v3.4 device found", __FUNCTION__); - device::V3_4::HalStreamConfiguration finalConfiguration3_4; - auto err = mHidlSession_3_4->configureStreams_3_4(requestedConfiguration3_4, - [&status, &finalConfiguration3_4] + auto configStream34Cb = [&status, &finalConfiguration3_4] (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) { finalConfiguration3_4 = halConfiguration; status = s; - }); - if (!err.isOk()) { - ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); - return DEAD_OBJECT; + }; + + auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4] + (hardware::Return& err) -> status_t { + if (!err.isOk()) { + ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); + return DEAD_OBJECT; + } + finalConfiguration.streams.resize(finalConfiguration3_4.streams.size()); + for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) { + finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3; + } + return OK; + }; + + // See if we have v3.4 or v3.3 HAL + if (mHidlSession_3_5 != nullptr) { + ALOGV("%s: v3.5 device found", __FUNCTION__); + device::V3_5::StreamConfiguration requestedConfiguration3_5; + requestedConfiguration3_5.v3_4 = requestedConfiguration3_4; + requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++; + auto err = mHidlSession_3_5->configureStreams_3_5( + requestedConfiguration3_5, configStream34Cb); + res = postprocConfigStream34(err); + if (res != OK) { + return res; } - finalConfiguration.streams.resize(finalConfiguration3_4.streams.size()); - for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) { - finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3; + } else if (mHidlSession_3_4 != nullptr) { + // We do; use v3.4 for the call + ALOGV("%s: v3.4 device found", __FUNCTION__); + device::V3_4::HalStreamConfiguration finalConfiguration3_4; + auto err = mHidlSession_3_4->configureStreams_3_4( + requestedConfiguration3_4, configStream34Cb); + res = postprocConfigStream34(err); + if (res != OK) { + return res; } } else if (mHidlSession_3_3 != nullptr) { // We do; use v3.3 for the call @@ -4292,6 +4330,20 @@ status_t Camera3Device::HalInterface::close() { return res; } +void Camera3Device::HalInterface::signalPipelineDrain(const std::vector& streamIds) { + ATRACE_NAME("CameraHal::signalPipelineDrain"); + if (!valid() || mHidlSession_3_5 == nullptr) { + ALOGE("%s called on invalid camera!", __FUNCTION__); + return; + } + + auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter); + if (!err.isOk()) { + ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); + return; + } +} + void Camera3Device::HalInterface::getInflightBufferKeys( std::vector>* out) { std::lock_guard lock(mInflightLock); @@ -4418,6 +4470,7 @@ Camera3Device::RequestThread::RequestThread(wp parent, mReconfigured(false), mDoPause(false), mPaused(true), + mNotifyPipelineDrain(false), mFrameNumber(0), mLatestRequestId(NAME_NOT_FOUND), mCurrentAfTriggerId(0), @@ -5369,6 +5422,21 @@ bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t s return false; } +void Camera3Device::RequestThread::signalPipelineDrain(const std::vector& streamIds) { + if (!mUseHalBufManager) { + ALOGE("%s called for camera device not supporting HAL buffer management", __FUNCTION__); + return; + } + + Mutex::Autolock pl(mPauseLock); + if (mPaused) { + return mInterface->signalPipelineDrain(streamIds); + } + // If request thread is still busy, wait until paused then notify HAL + mNotifyPipelineDrain = true; + mStreamIdsToBeDrained = streamIds; +} + nsecs_t Camera3Device::getExpectedInFlightDuration() { ATRACE_CALL(); Mutex::Autolock al(mInFlightLock); @@ -5546,6 +5614,11 @@ sp if (statusTracker != 0) { statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE); } + if (mNotifyPipelineDrain) { + mInterface->signalPipelineDrain(mStreamIdsToBeDrained); + mNotifyPipelineDrain = false; + mStreamIdsToBeDrained.clear(); + } } // Stop waiting for now and let thread management happen return NULL; @@ -5630,6 +5703,11 @@ bool Camera3Device::RequestThread::waitIfPaused() { if (statusTracker != 0) { statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE); } + if (mNotifyPipelineDrain) { + mInterface->signalPipelineDrain(mStreamIdsToBeDrained); + mNotifyPipelineDrain = false; + mStreamIdsToBeDrained.clear(); + } } res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout); diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 4ed6d9dd6b..5c0f570ad8 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -285,6 +285,8 @@ class Camera3Device : status_t dump(int fd); status_t close(); + void signalPipelineDrain(const std::vector& streamIds); + // method to extract buffer's unique ID // return pair of (newlySeenBuffer?, bufferId) std::pair getBufferId(const buffer_handle_t& buf, int streamId); @@ -372,6 +374,8 @@ class Camera3Device : // Buffers given to HAL through requestStreamBuffer API std::mutex mRequestedBuffersLock; std::unordered_map mRequestedBuffers; + + uint32_t mNextStreamConfigCounter = 1; }; sp mInterface; @@ -415,6 +419,7 @@ class Camera3Device : // get by (underlying) vector index sp operator[] (size_t index); size_t size() const; + std::vector getStreamIds(); void clear(); private: @@ -808,6 +813,8 @@ class Camera3Device : mRequestLatency.dump(fd, name); } + void signalPipelineDrain(const std::vector& streamIds); + protected: virtual bool threadLoop(); @@ -917,12 +924,13 @@ class Camera3Device : bool mReconfigured; - // Used by waitIfPaused, waitForNextRequest, and waitUntilPaused + // Used by waitIfPaused, waitForNextRequest, waitUntilPaused, and signalPipelineDrain Mutex mPauseLock; bool mDoPause; Condition mDoPauseSignal; bool mPaused; - Condition mPausedSignal; + bool mNotifyPipelineDrain; + std::vector mStreamIdsToBeDrained; sp mPrevRequest; int32_t mPrevTriggers;