android: hal: implement signalStreamFlush with race condition handling

Add proper implementation of signalStreamFlush() to handle stream buffer
flushing before reconfiguration. Features:
- Stream configuration counter to prevent race conditions
- Validation of stream IDs against configured streams
- Inflight buffer tracking and reporting for affected streams
- Warning when buffers are detected to prevent fatal errors

Increments mStreamConfigCounter during configureStreams() and uses atomic
operations to detect stale signalStreamFlush() calls, ensuring proper
synchronization during stream reconfiguration.

Further details about the race condition scenario can be found at [1].

[1] https://android.googlesource.com/platform/hardware/interfaces/+/master/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl#489

Signed-off-by: Maxime Fournier <mfournier@baylibre.com>
This commit is contained in:
Maxime Fournier
2025-08-27 14:07:33 +02:00
committed by Konsta
parent 7e2ca2b541
commit b02341aa90
2 changed files with 70 additions and 2 deletions

View File

@@ -1092,6 +1092,8 @@ ScopedAStatus LibcameraDeviceSession::configureStreams(
convertToAidl(static_cast<Camera3Stream*>(streams[i]), &out[i]);
}
mFirstRequest = true;
// Increment stream configuration counter for signalStreamFlush race condition handling
mStreamConfigCounter++;
}
return fromStatus(status);
}
@@ -1710,8 +1712,70 @@ ScopedAStatus LibcameraDeviceSession::isReconfigurationRequired(
}
ScopedAStatus LibcameraDeviceSession::signalStreamFlush(const std::vector<int32_t>& in_streamIds,
int32_t in_streamConfigCounter) {
ALOGI("%s()", __func__);
return fromStatus(Status::INTERNAL_ERROR);
ALOGV("%s: streamIds size %zu, configCounter %d", __FUNCTION__,
in_streamIds.size(), in_streamConfigCounter);
Status status = initStatus();
if (status != Status::OK) {
ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
return fromStatus(status);
}
// Check for race condition - if the counter is less than our last configureStreams,
// this call is stale and should be ignored
int32_t currentCounter = mStreamConfigCounter.load();
if (in_streamConfigCounter < currentCounter) {
ALOGD("%s: Stale signalStreamFlush call (counter %d < current %d), ignoring",
__FUNCTION__, in_streamConfigCounter, currentCounter);
return fromStatus(Status::OK);
}
// Validate stream IDs
for (int32_t streamId : in_streamIds) {
if (mStreamMap.find(streamId) == mStreamMap.end()) {
ALOGE("%s: Invalid stream ID %d", __FUNCTION__, streamId);
return fromStatus(Status::ILLEGAL_ARGUMENT);
}
}
ALOGD("%s: Flushing buffers for %zu streams before reconfiguration",
__FUNCTION__, in_streamIds.size());
// Check current inflight buffers for the specified streams
{
Mutex::Autolock _l(mInflightLock);
size_t totalInflightBuffers = 0;
for (int32_t streamId : in_streamIds) {
size_t streamInflightCount = 0;
for (const auto& pair : mInflightBuffers) {
if (pair.first.first == streamId) {
streamInflightCount++;
}
}
if (streamInflightCount > 0) {
ALOGD("%s: Stream %d has %zu inflight buffers",
__FUNCTION__, streamId, streamInflightCount);
totalInflightBuffers += streamInflightCount;
}
}
if (totalInflightBuffers > 0) {
ALOGW("%s: Total %zu inflight buffers detected for streams being flushed. "
"HAL should return these buffers promptly to avoid fatal errors.",
__FUNCTION__, totalInflightBuffers);
} else {
ALOGV("%s: No inflight buffers found for specified streams", __FUNCTION__);
}
}
// This is mainly a hint/notification from camera service
// The actual buffer return will happen through normal capture request completion
// or error callbacks. We just log the request and let the system know we received it.
ALOGV("%s: Stream flush signal processed successfully", __FUNCTION__);
return fromStatus(Status::OK);
}
ScopedAStatus LibcameraDeviceSession::switchToOffline(
const std::vector<int32_t>& in_streamsToKeep,

View File

@@ -25,6 +25,7 @@
#include "convert.h"
#include <atomic>
#include <deque>
#include <map>
#include <unordered_map>
@@ -158,6 +159,9 @@ protected:
// Stream ID -> Camera3Stream cache
std::map<int, Camera3Stream> mStreamMap;
// Stream configuration counter to handle race conditions in signalStreamFlush
std::atomic<int32_t> mStreamConfigCounter{0};
mutable Mutex mInflightLock; // protecting mInflightBuffers and mCirculatingBuffers
// (streamID, frameNumber) -> inflight buffer cache
std::map<std::pair<int, uint32_t>, camera3_stream_buffer_t> mInflightBuffers;