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
gugelfrei
Yin-Chia Yeh 6 years ago
parent 4ee3543809
commit 7447f0fc15

@ -1619,6 +1619,15 @@ void Camera3Device::StreamSet::clear() {
return mData.clear(); return mData.clear();
} }
std::vector<int> Camera3Device::StreamSet::getStreamIds() {
std::lock_guard<std::mutex> lock(mLock);
std::vector<int> streamIds(mData.size());
for (size_t i = 0; i < mData.size(); i++) {
streamIds[i] = mData.keyAt(i);
}
return streamIds;
}
status_t Camera3Device::createStream(sp<Surface> consumer, status_t Camera3Device::createStream(sp<Surface> consumer,
uint32_t width, uint32_t height, int format, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id, android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
@ -2130,6 +2139,12 @@ status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
break; break;
} }
// Notify HAL to start draining
if (!active && mUseHalBufManager) {
auto streamIds = mOutputStreams.getStreamIds();
mRequestThread->signalPipelineDrain(streamIds);
}
res = mStatusChanged.waitRelative(mLock, timeout); res = mStatusChanged.waitRelative(mLock, timeout);
if (res != OK) break; if (res != OK) break;
@ -3902,26 +3917,49 @@ status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *
// Invoke configureStreams // Invoke configureStreams
device::V3_3::HalStreamConfiguration finalConfiguration; device::V3_3::HalStreamConfiguration finalConfiguration;
device::V3_4::HalStreamConfiguration finalConfiguration3_4;
common::V1_0::Status status; common::V1_0::Status status;
// See if we have v3.4 or v3.3 HAL auto configStream34Cb = [&status, &finalConfiguration3_4]
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]
(common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) { (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
finalConfiguration3_4 = halConfiguration; finalConfiguration3_4 = halConfiguration;
status = s; status = s;
}); };
if (!err.isOk()) {
ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
return DEAD_OBJECT; (hardware::Return<void>& 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()); } else if (mHidlSession_3_4 != nullptr) {
for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) { // We do; use v3.4 for the call
finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3; 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) { } else if (mHidlSession_3_3 != nullptr) {
// We do; use v3.3 for the call // We do; use v3.3 for the call
@ -4292,6 +4330,20 @@ status_t Camera3Device::HalInterface::close() {
return res; return res;
} }
void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& 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( void Camera3Device::HalInterface::getInflightBufferKeys(
std::vector<std::pair<int32_t, int32_t>>* out) { std::vector<std::pair<int32_t, int32_t>>* out) {
std::lock_guard<std::mutex> lock(mInflightLock); std::lock_guard<std::mutex> lock(mInflightLock);
@ -4418,6 +4470,7 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
mReconfigured(false), mReconfigured(false),
mDoPause(false), mDoPause(false),
mPaused(true), mPaused(true),
mNotifyPipelineDrain(false),
mFrameNumber(0), mFrameNumber(0),
mLatestRequestId(NAME_NOT_FOUND), mLatestRequestId(NAME_NOT_FOUND),
mCurrentAfTriggerId(0), mCurrentAfTriggerId(0),
@ -5369,6 +5422,21 @@ bool Camera3Device::RequestThread::isOutputSurfacePending(int streamId, size_t s
return false; return false;
} }
void Camera3Device::RequestThread::signalPipelineDrain(const std::vector<int>& 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() { nsecs_t Camera3Device::getExpectedInFlightDuration() {
ATRACE_CALL(); ATRACE_CALL();
Mutex::Autolock al(mInFlightLock); Mutex::Autolock al(mInFlightLock);
@ -5546,6 +5614,11 @@ sp<Camera3Device::CaptureRequest>
if (statusTracker != 0) { if (statusTracker != 0) {
statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE); statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
} }
if (mNotifyPipelineDrain) {
mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
mNotifyPipelineDrain = false;
mStreamIdsToBeDrained.clear();
}
} }
// Stop waiting for now and let thread management happen // Stop waiting for now and let thread management happen
return NULL; return NULL;
@ -5630,6 +5703,11 @@ bool Camera3Device::RequestThread::waitIfPaused() {
if (statusTracker != 0) { if (statusTracker != 0) {
statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE); statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
} }
if (mNotifyPipelineDrain) {
mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
mNotifyPipelineDrain = false;
mStreamIdsToBeDrained.clear();
}
} }
res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout); res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);

@ -285,6 +285,8 @@ class Camera3Device :
status_t dump(int fd); status_t dump(int fd);
status_t close(); status_t close();
void signalPipelineDrain(const std::vector<int>& streamIds);
// method to extract buffer's unique ID // method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId) // return pair of (newlySeenBuffer?, bufferId)
std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId); std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
@ -372,6 +374,8 @@ class Camera3Device :
// Buffers given to HAL through requestStreamBuffer API // Buffers given to HAL through requestStreamBuffer API
std::mutex mRequestedBuffersLock; std::mutex mRequestedBuffersLock;
std::unordered_map<uint64_t, buffer_handle_t*> mRequestedBuffers; std::unordered_map<uint64_t, buffer_handle_t*> mRequestedBuffers;
uint32_t mNextStreamConfigCounter = 1;
}; };
sp<HalInterface> mInterface; sp<HalInterface> mInterface;
@ -415,6 +419,7 @@ class Camera3Device :
// get by (underlying) vector index // get by (underlying) vector index
sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index); sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index);
size_t size() const; size_t size() const;
std::vector<int> getStreamIds();
void clear(); void clear();
private: private:
@ -808,6 +813,8 @@ class Camera3Device :
mRequestLatency.dump(fd, name); mRequestLatency.dump(fd, name);
} }
void signalPipelineDrain(const std::vector<int>& streamIds);
protected: protected:
virtual bool threadLoop(); virtual bool threadLoop();
@ -917,12 +924,13 @@ class Camera3Device :
bool mReconfigured; bool mReconfigured;
// Used by waitIfPaused, waitForNextRequest, and waitUntilPaused // Used by waitIfPaused, waitForNextRequest, waitUntilPaused, and signalPipelineDrain
Mutex mPauseLock; Mutex mPauseLock;
bool mDoPause; bool mDoPause;
Condition mDoPauseSignal; Condition mDoPauseSignal;
bool mPaused; bool mPaused;
Condition mPausedSignal; bool mNotifyPipelineDrain;
std::vector<int> mStreamIdsToBeDrained;
sp<CaptureRequest> mPrevRequest; sp<CaptureRequest> mPrevRequest;
int32_t mPrevTriggers; int32_t mPrevTriggers;

Loading…
Cancel
Save