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
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 04d3639..f829b65 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1619,6 +1619,15 @@
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,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
@@ -2130,6 +2139,12 @@
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 @@
// 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<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());
- 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 @@
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(
std::vector<std::pair<int32_t, int32_t>>* out) {
std::lock_guard<std::mutex> lock(mInflightLock);
@@ -4418,6 +4470,7 @@
mReconfigured(false),
mDoPause(false),
mPaused(true),
+ mNotifyPipelineDrain(false),
mFrameNumber(0),
mLatestRequestId(NAME_NOT_FOUND),
mCurrentAfTriggerId(0),
@@ -5369,6 +5422,21 @@
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() {
ATRACE_CALL();
Mutex::Autolock al(mInFlightLock);
@@ -5546,6 +5614,11 @@
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 @@
if (statusTracker != 0) {
statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
}
+ if (mNotifyPipelineDrain) {
+ mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
+ mNotifyPipelineDrain = false;
+ mStreamIdsToBeDrained.clear();
+ }
}
res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);