ExternalCameraHAL: fix CTS failures with callback for errors
For every request, either requestStreamBuffers fails or handling of the requested buffer fails, always trigger the processCaptureResult callback by notifying the request is ready. This avoids the errors like the service side receives fewer results than the requests and waits until timeout. Bug: 299182874 Test: cts cts-tradefed run cts \ --include-filter "CtsCameraTestCases android.hardware.camera2.cts.RobustnessTest" \ --include-filter "CtsCameraTestCases android.hardware.camera2.cts.PerformanceTest" \ --include-filter "CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest" \ --include-filter "CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest" \ --include-filter "CtsCameraTestCases android.hardware.cts.CameraGLTest" \ --include-filter "CtsCameraTestCases android.hardware.cts.LegacyCameraPerformanceTest" \ Merged-in: I86ba422524e79af6b318b50bd6eebe2cb27fa50a Change-Id: I86ba422524e79af6b318b50bd6eebe2cb27fa50a
This commit is contained in:
parent
895f5bbddc
commit
45d7a9e1b4
1 changed files with 38 additions and 5 deletions
|
@ -1965,6 +1965,12 @@ int ExternalCameraDeviceSession::BufferRequestThread::waitForBufferRequestDone(
|
||||||
ALOGE("%s: wait for buffer request finish timeout!", __FUNCTION__);
|
ALOGE("%s: wait for buffer request finish timeout!", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPendingReturnBufferReqs.empty()) {
|
||||||
|
mRequestingBuffer = false;
|
||||||
|
ALOGE("%s: cameraservice did not return any buffers!", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mRequestingBuffer = false;
|
mRequestingBuffer = false;
|
||||||
*outBufReqs = std::move(mPendingReturnBufferReqs);
|
*outBufReqs = std::move(mPendingReturnBufferReqs);
|
||||||
|
@ -2014,6 +2020,8 @@ bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
|
||||||
if (!ret.isOk()) {
|
if (!ret.isOk()) {
|
||||||
ALOGE("%s: Transaction error: %d:%d", __FUNCTION__, ret.getExceptionCode(),
|
ALOGE("%s: Transaction error: %d:%d", __FUNCTION__, ret.getExceptionCode(),
|
||||||
ret.getServiceSpecificError());
|
ret.getServiceSpecificError());
|
||||||
|
mBufferReqs.clear();
|
||||||
|
mRequestDoneCond.notify_one();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2022,17 +2030,24 @@ bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
|
||||||
if (bufRets.size() != mHalBufferReqs.size()) {
|
if (bufRets.size() != mHalBufferReqs.size()) {
|
||||||
ALOGE("%s: expect %zu buffer requests returned, only got %zu", __FUNCTION__,
|
ALOGE("%s: expect %zu buffer requests returned, only got %zu", __FUNCTION__,
|
||||||
mHalBufferReqs.size(), bufRets.size());
|
mHalBufferReqs.size(), bufRets.size());
|
||||||
|
mBufferReqs.clear();
|
||||||
|
lk.unlock();
|
||||||
|
mRequestDoneCond.notify_one();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parent = mParent.lock();
|
auto parent = mParent.lock();
|
||||||
if (parent == nullptr) {
|
if (parent == nullptr) {
|
||||||
ALOGE("%s: session has been disconnected!", __FUNCTION__);
|
ALOGE("%s: session has been disconnected!", __FUNCTION__);
|
||||||
|
mBufferReqs.clear();
|
||||||
|
lk.unlock();
|
||||||
|
mRequestDoneCond.notify_one();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> importedFences;
|
std::vector<int> importedFences;
|
||||||
importedFences.resize(bufRets.size());
|
importedFences.resize(bufRets.size());
|
||||||
|
bool hasError = false;
|
||||||
for (size_t i = 0; i < bufRets.size(); i++) {
|
for (size_t i = 0; i < bufRets.size(); i++) {
|
||||||
int streamId = bufRets[i].streamId;
|
int streamId = bufRets[i].streamId;
|
||||||
switch (bufRets[i].val.getTag()) {
|
switch (bufRets[i].val.getTag()) {
|
||||||
|
@ -2043,7 +2058,8 @@ bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
|
||||||
bufRets[i].val.get<StreamBuffersVal::Tag::buffers>();
|
bufRets[i].val.get<StreamBuffersVal::Tag::buffers>();
|
||||||
if (hBufs.size() != 1) {
|
if (hBufs.size() != 1) {
|
||||||
ALOGE("%s: expect 1 buffer returned, got %zu!", __FUNCTION__, hBufs.size());
|
ALOGE("%s: expect 1 buffer returned, got %zu!", __FUNCTION__, hBufs.size());
|
||||||
return false;
|
hasError = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
const StreamBuffer& hBuf = hBufs[0];
|
const StreamBuffer& hBuf = hBufs[0];
|
||||||
|
|
||||||
|
@ -2060,26 +2076,38 @@ bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
|
||||||
if (s != Status::OK) {
|
if (s != Status::OK) {
|
||||||
ALOGE("%s: stream %d import buffer failed!", __FUNCTION__, streamId);
|
ALOGE("%s: stream %d import buffer failed!", __FUNCTION__, streamId);
|
||||||
cleanupInflightFences(importedFences, i - 1);
|
cleanupInflightFences(importedFences, i - 1);
|
||||||
return false;
|
hasError = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
h = makeFromAidl(hBuf.acquireFence);
|
h = makeFromAidl(hBuf.acquireFence);
|
||||||
if (!sHandleImporter.importFence(h, mBufferReqs[i].acquireFence)) {
|
if (!sHandleImporter.importFence(h, mBufferReqs[i].acquireFence)) {
|
||||||
ALOGE("%s: stream %d import fence failed!", __FUNCTION__, streamId);
|
ALOGE("%s: stream %d import fence failed!", __FUNCTION__, streamId);
|
||||||
cleanupInflightFences(importedFences, i - 1);
|
cleanupInflightFences(importedFences, i - 1);
|
||||||
native_handle_delete(h);
|
native_handle_delete(h);
|
||||||
return false;
|
hasError = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
native_handle_delete(h);
|
native_handle_delete(h);
|
||||||
importedFences[i] = mBufferReqs[i].acquireFence;
|
importedFences[i] = mBufferReqs[i].acquireFence;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
ALOGE("%s: Unknown StreamBuffersVal!", __FUNCTION__);
|
ALOGE("%s: Unknown StreamBuffersVal!", __FUNCTION__);
|
||||||
return false;
|
hasError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hasError) {
|
||||||
|
mBufferReqs.clear();
|
||||||
|
lk.unlock();
|
||||||
|
mRequestDoneCond.notify_one();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ALOGE("%s: requestStreamBuffers call failed!", __FUNCTION__);
|
ALOGE("%s: requestStreamBuffers call failed!", __FUNCTION__);
|
||||||
return false;
|
mBufferReqs.clear();
|
||||||
|
lk.unlock();
|
||||||
|
mRequestDoneCond.notify_one();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPendingReturnBufferReqs = std::move(mBufferReqs);
|
mPendingReturnBufferReqs = std::move(mBufferReqs);
|
||||||
|
@ -2784,6 +2812,11 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
// For some webcam, the first few V4L2 frames might be malformed...
|
// For some webcam, the first few V4L2 frames might be malformed...
|
||||||
ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
|
ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
|
||||||
|
|
||||||
|
ATRACE_BEGIN("Wait for BufferRequest done");
|
||||||
|
res = waitForBufferRequestDone(&req->buffers);
|
||||||
|
ATRACE_END();
|
||||||
|
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
Status st = parent->processCaptureRequestError(req);
|
Status st = parent->processCaptureRequestError(req);
|
||||||
if (st != Status::OK) {
|
if (st != Status::OK) {
|
||||||
|
|
Loading…
Reference in a new issue