1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "device_cb.h"
18
19 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
20 #include <aidlcommonsupport/NativeHandle.h>
21 #include <grallocusage/GrallocUsageConversion.h>
22 #include <cinttypes>
23 #include <nativebase/nativebase.h>
24
25 using ::aidl::android::hardware::camera::device::BufferStatus;
26 using ::aidl::android::hardware::camera::device::ErrorMsg;
27 using ::aidl::android::hardware::camera::device::StreamBufferRequestError;
28 using ::aidl::android::hardware::camera::device::StreamBuffersVal;
29 using ::aidl::android::hardware::graphics::common::PixelFormat;
30
31 const int64_t kBufferReturnTimeoutSec = 1;
32
DeviceCb(CameraAidlTest * parent,camera_metadata_t * staticMeta)33 DeviceCb::DeviceCb(CameraAidlTest* parent, camera_metadata_t* staticMeta) : mParent(parent) {
34 mStaticMetadata = staticMeta;
35 }
36
notify(const std::vector<NotifyMsg> & msgs)37 ScopedAStatus DeviceCb::notify(const std::vector<NotifyMsg>& msgs) {
38 std::vector<std::pair<bool, nsecs_t>> readoutTimestamps;
39
40 size_t count = msgs.size();
41 readoutTimestamps.resize(count);
42
43 for (size_t i = 0; i < count; i++) {
44 const NotifyMsg& msg = msgs[i];
45 switch (msg.getTag()) {
46 case NotifyMsg::Tag::error:
47 readoutTimestamps[i] = {false, 0};
48 break;
49 case NotifyMsg::Tag::shutter:
50 const auto& shutter = msg.get<NotifyMsg::Tag::shutter>();
51 readoutTimestamps[i] = {true, shutter.readoutTimestamp};
52 break;
53 }
54 }
55
56 return notifyHelper(msgs, readoutTimestamps);
57 }
58
processCaptureResult(const std::vector<CaptureResult> & results)59 ScopedAStatus DeviceCb::processCaptureResult(const std::vector<CaptureResult>& results) {
60 if (nullptr == mParent) {
61 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
62 }
63
64 bool notify = false;
65 std::unique_lock<std::mutex> l(mParent->mLock);
66 for (const auto& result : results) {
67 notify = processCaptureResultLocked(result, result.physicalCameraMetadata);
68 }
69
70 l.unlock();
71 if (notify) {
72 mParent->mResultCondition.notify_one();
73 }
74
75 return ndk::ScopedAStatus::ok();
76 }
77
requestStreamBuffers(const std::vector<BufferRequest> & bufReqs,std::vector<StreamBufferRet> * buffers,BufferRequestStatus * _aidl_return)78 ScopedAStatus DeviceCb::requestStreamBuffers(const std::vector<BufferRequest>& bufReqs,
79 std::vector<StreamBufferRet>* buffers,
80 BufferRequestStatus* _aidl_return) {
81 std::vector<StreamBufferRet>& bufRets = *buffers;
82 std::unique_lock<std::mutex> l(mLock);
83
84 if (!mUseHalBufManager) {
85 ALOGE("%s: Camera does not support HAL buffer management", __FUNCTION__);
86 ADD_FAILURE();
87 *_aidl_return = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
88 return ScopedAStatus::ok();
89 }
90
91 if (bufReqs.size() > mStreams.size()) {
92 ALOGE("%s: illegal buffer request: too many requests!", __FUNCTION__);
93 ADD_FAILURE();
94 *_aidl_return = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
95 return ndk::ScopedAStatus::ok();
96 }
97
98 std::vector<size_t> indexes(bufReqs.size());
99 for (size_t i = 0; i < bufReqs.size(); i++) {
100 bool found = false;
101 for (size_t idx = 0; idx < mStreams.size(); idx++) {
102 if (bufReqs[i].streamId == mStreams[idx].id) {
103 found = true;
104 indexes[i] = idx;
105 break;
106 }
107 }
108 if (!found) {
109 ALOGE("%s: illegal buffer request: unknown streamId %d!", __FUNCTION__,
110 bufReqs[i].streamId);
111 ADD_FAILURE();
112 *_aidl_return = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
113 return ScopedAStatus::ok();
114 }
115 }
116
117 bool allStreamOk = true;
118 bool atLeastOneStreamOk = false;
119 bufRets.resize(bufReqs.size());
120
121 for (size_t i = 0; i < bufReqs.size(); i++) {
122 size_t idx = indexes[i];
123 const auto& stream = mStreams[idx];
124 const auto& halStream = mHalStreams[idx];
125 const BufferRequest& bufReq = bufReqs[i];
126
127 if (mOutstandingBufferIds[idx].size() + bufReq.numBuffersRequested > halStream.maxBuffers) {
128 bufRets[i].streamId = stream.id;
129 bufRets[i].val.set<StreamBuffersVal::Tag::error>(
130 StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
131 allStreamOk = false;
132 continue;
133 }
134
135 std::vector<StreamBuffer> tmpRetBuffers(bufReq.numBuffersRequested);
136 for (size_t j = 0; j < bufReq.numBuffersRequested; j++) {
137 buffer_handle_t handle;
138 uint32_t w = stream.width;
139 uint32_t h = stream.height;
140 if (stream.format == PixelFormat::BLOB) {
141 w = stream.bufferSize;
142 h = 1;
143 }
144
145 CameraAidlTest::allocateGraphicBuffer(
146 w, h,
147 ANDROID_NATIVE_UNSIGNED_CAST(android_convertGralloc1To0Usage(static_cast<uint64_t>(halStream.producerUsage),
148 static_cast<uint64_t>(halStream.consumerUsage))),
149 halStream.overrideFormat, &handle);
150
151 StreamBuffer streamBuffer = StreamBuffer();
152 StreamBuffer& sb = tmpRetBuffers[j];
153 sb = {
154 stream.id, mNextBufferId, ::android::dupToAidl(handle),
155 BufferStatus::OK, NativeHandle(), NativeHandle(),
156 };
157
158 mOutstandingBufferIds[idx][mNextBufferId++] = handle;
159 }
160 atLeastOneStreamOk = true;
161 bufRets[i].streamId = stream.id;
162 bufRets[i].val.set<StreamBuffersVal::Tag::buffers>(std::move(tmpRetBuffers));
163 }
164
165 if (allStreamOk) {
166 *_aidl_return = BufferRequestStatus::OK;
167 } else if (atLeastOneStreamOk) {
168 *_aidl_return = BufferRequestStatus::FAILED_PARTIAL;
169 } else {
170 *_aidl_return = BufferRequestStatus::FAILED_UNKNOWN;
171 }
172
173 if (!hasOutstandingBuffersLocked()) {
174 l.unlock();
175 mFlushedCondition.notify_one();
176 }
177
178 return ndk::ScopedAStatus::ok();
179 }
180
returnStreamBuffers(const std::vector<StreamBuffer> & buffers)181 ScopedAStatus DeviceCb::returnStreamBuffers(const std::vector<StreamBuffer>& buffers) {
182 if (!mUseHalBufManager) {
183 ALOGE("%s: Camera does not support HAL buffer management", __FUNCTION__);
184 ADD_FAILURE();
185 }
186
187 std::unique_lock<std::mutex> l(mLock);
188 for (const auto& buf : buffers) {
189 if (buf.bufferId == 0) {
190 // Don't return buffers of bufId 0 (empty buffer)
191 continue;
192 }
193 bool found = false;
194 for (size_t idx = 0; idx < mOutstandingBufferIds.size(); idx++) {
195 if (mStreams[idx].id == buf.streamId &&
196 mOutstandingBufferIds[idx].count(buf.bufferId) == 1) {
197 mOutstandingBufferIds[idx].erase(buf.bufferId);
198 // TODO: check do we need to close/delete native handle or assume we have enough
199 // memory to run till the test finish? since we do not capture much requests (and
200 // most of time one buffer is sufficient)
201 found = true;
202 break;
203 }
204 }
205 if (found) {
206 continue;
207 }
208 ALOGE("%s: unknown buffer ID %" PRIu64, __FUNCTION__, buf.bufferId);
209 ADD_FAILURE();
210 }
211 if (!hasOutstandingBuffersLocked()) {
212 l.unlock();
213 mFlushedCondition.notify_one();
214 }
215
216 return ndk::ScopedAStatus::ok();
217 }
218
setCurrentStreamConfig(const std::vector<Stream> & streams,const std::vector<HalStream> & halStreams)219 void DeviceCb::setCurrentStreamConfig(const std::vector<Stream>& streams,
220 const std::vector<HalStream>& halStreams) {
221 ASSERT_EQ(streams.size(), halStreams.size());
222 ASSERT_NE(streams.size(), 0);
223 for (size_t i = 0; i < streams.size(); i++) {
224 ASSERT_EQ(streams[i].id, halStreams[i].id);
225 }
226 std::lock_guard<std::mutex> l(mLock);
227 mUseHalBufManager = true;
228 mStreams = streams;
229 mHalStreams = halStreams;
230 mOutstandingBufferIds.clear();
231 for (size_t i = 0; i < streams.size(); i++) {
232 mOutstandingBufferIds.emplace_back();
233 }
234 }
235
waitForBuffersReturned()236 void DeviceCb::waitForBuffersReturned() {
237 std::unique_lock<std::mutex> lk(mLock);
238 if (hasOutstandingBuffersLocked()) {
239 auto timeout = std::chrono::seconds(kBufferReturnTimeoutSec);
240 auto st = mFlushedCondition.wait_for(lk, timeout);
241 ASSERT_NE(std::cv_status::timeout, st);
242 }
243 }
244
processCaptureResultLocked(const CaptureResult & results,std::vector<PhysicalCameraMetadata> physicalCameraMetadata)245 bool DeviceCb::processCaptureResultLocked(
246 const CaptureResult& results, std::vector<PhysicalCameraMetadata> physicalCameraMetadata) {
247 bool notify = false;
248 uint32_t frameNumber = results.frameNumber;
249
250 if ((results.result.metadata.empty()) && (results.outputBuffers.empty()) &&
251 (results.inputBuffer.buffer.fds.empty()) && (results.fmqResultSize == 0)) {
252 ALOGE("%s: No result data provided by HAL for frame %d result count: %d", __func__,
253 frameNumber, (int)results.fmqResultSize);
254 ADD_FAILURE();
255 return notify;
256 }
257
258 auto requestEntry = mParent->mInflightMap.find(frameNumber);
259 if (requestEntry == mParent->mInflightMap.end()) {
260 ALOGE("%s: Unexpected frame number! received: %u", __func__, frameNumber);
261 ADD_FAILURE();
262 return notify;
263 }
264
265 bool isPartialResult = false;
266 bool hasInputBufferInRequest = false;
267 auto& request = requestEntry->second;
268
269 CameraMetadata resultMetadata;
270 size_t resultSize = 0;
271 if (results.fmqResultSize > 0) {
272 resultMetadata.metadata.resize(results.fmqResultSize);
273 if (request->resultQueue == nullptr) {
274 ADD_FAILURE();
275 return notify;
276 }
277
278 if (!request->resultQueue->read(reinterpret_cast<int8_t*>(resultMetadata.metadata.data()),
279 results.fmqResultSize)) {
280 ALOGE("%s: Frame %d: Cannot read camera metadata from fmq,"
281 "size = %" PRIu64,
282 __func__, frameNumber, results.fmqResultSize);
283 ADD_FAILURE();
284 return notify;
285 }
286
287 // Physical device results are only expected in the last/final
288 // partial result notification.
289 bool expectPhysicalResults = !(request->usePartialResult &&
290 (results.partialResult < request->numPartialResults));
291 if (expectPhysicalResults &&
292 (physicalCameraMetadata.size() != request->expectedPhysicalResults.size())) {
293 ALOGE("%s: Frame %d: Returned physical metadata count %zu "
294 "must be equal to expected count %zu",
295 __func__, frameNumber, physicalCameraMetadata.size(),
296 request->expectedPhysicalResults.size());
297 ADD_FAILURE();
298 return notify;
299 }
300 std::vector<std::vector<uint8_t>> physResultMetadata;
301 physResultMetadata.resize(physicalCameraMetadata.size());
302 for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
303 physResultMetadata[i].resize(physicalCameraMetadata[i].fmqMetadataSize);
304 if (!request->resultQueue->read(reinterpret_cast<int8_t*>(physResultMetadata[i].data()),
305 physicalCameraMetadata[i].fmqMetadataSize)) {
306 ALOGE("%s: Frame %d: Cannot read physical camera metadata from fmq,"
307 "size = %" PRIu64,
308 __func__, frameNumber, physicalCameraMetadata[i].fmqMetadataSize);
309 ADD_FAILURE();
310 return notify;
311 }
312 }
313 resultSize = resultMetadata.metadata.size();
314 } else if (!results.result.metadata.empty()) {
315 resultMetadata = results.result;
316 resultSize = resultMetadata.metadata.size();
317 }
318
319 if (!request->usePartialResult && (resultSize > 0) && (results.partialResult != 1)) {
320 ALOGE("%s: Result is malformed for frame %d: partial_result %u "
321 "must be 1 if partial result is not supported",
322 __func__, frameNumber, results.partialResult);
323 ADD_FAILURE();
324 return notify;
325 }
326
327 if (results.partialResult != 0) {
328 request->partialResultCount = results.partialResult;
329 }
330
331 // Check if this result carries only partial metadata
332 if (request->usePartialResult && (resultSize > 0)) {
333 if ((results.partialResult > request->numPartialResults) || (results.partialResult < 1)) {
334 ALOGE("%s: Result is malformed for frame %d: partial_result %u"
335 " must be in the range of [1, %d] when metadata is "
336 "included in the result",
337 __func__, frameNumber, results.partialResult, request->numPartialResults);
338 ADD_FAILURE();
339 return notify;
340 }
341
342 // Verify no duplicate tags between partial results
343 const camera_metadata_t* partialMetadata =
344 reinterpret_cast<const camera_metadata_t*>(resultMetadata.metadata.data());
345 const camera_metadata_t* collectedMetadata = request->collectedResult.getAndLock();
346 camera_metadata_ro_entry_t searchEntry, foundEntry;
347 for (size_t i = 0; i < get_camera_metadata_entry_count(partialMetadata); i++) {
348 if (0 != get_camera_metadata_ro_entry(partialMetadata, i, &searchEntry)) {
349 ADD_FAILURE();
350 request->collectedResult.unlock(collectedMetadata);
351 return notify;
352 }
353 if (-ENOENT !=
354 find_camera_metadata_ro_entry(collectedMetadata, searchEntry.tag, &foundEntry)) {
355 ADD_FAILURE();
356 request->collectedResult.unlock(collectedMetadata);
357 return notify;
358 }
359 }
360 request->collectedResult.unlock(collectedMetadata);
361 request->collectedResult.append(partialMetadata);
362
363 isPartialResult = (results.partialResult < request->numPartialResults);
364 } else if (resultSize > 0) {
365 request->collectedResult.append(
366 reinterpret_cast<const camera_metadata_t*>(resultMetadata.metadata.data()));
367 isPartialResult = false;
368 }
369
370 hasInputBufferInRequest = request->hasInputBuffer;
371
372 // Did we get the (final) result metadata for this capture?
373 if ((resultSize > 0) && !isPartialResult) {
374 if (request->haveResultMetadata) {
375 ALOGE("%s: Called multiple times with metadata for frame %d", __func__, frameNumber);
376 ADD_FAILURE();
377 return notify;
378 }
379 request->haveResultMetadata = true;
380 request->collectedResult.sort();
381
382 // Verify final result metadata
383 camera_metadata_t* staticMetadataBuffer = mStaticMetadata;
384 bool isMonochrome = Status::OK == CameraAidlTest::isMonochromeCamera(staticMetadataBuffer);
385 if (isMonochrome) {
386 CameraAidlTest::verifyMonochromeCameraResult(request->collectedResult);
387 }
388
389 // Verify logical camera result metadata
390 bool isLogicalCamera =
391 Status::OK == CameraAidlTest::isLogicalMultiCamera(staticMetadataBuffer);
392 camera_metadata_t* collectedMetadata =
393 const_cast<camera_metadata_t*>(request->collectedResult.getAndLock());
394 uint8_t* rawMetadata = reinterpret_cast<uint8_t*>(collectedMetadata);
395 std::vector metadata =
396 std::vector(rawMetadata, rawMetadata + get_camera_metadata_size(collectedMetadata));
397 if (isLogicalCamera) {
398 CameraAidlTest::verifyLogicalCameraResult(staticMetadataBuffer, metadata);
399 }
400 CameraAidlTest::verifyLensIntrinsicsResult(metadata);
401 request->collectedResult.unlock(collectedMetadata);
402 }
403
404 uint32_t numBuffersReturned = results.outputBuffers.size();
405 auto& inputBuffer = results.inputBuffer.buffer;
406 if (!inputBuffer.fds.empty() && !inputBuffer.ints.empty()) {
407 if (hasInputBufferInRequest) {
408 numBuffersReturned += 1;
409 } else {
410 ALOGW("%s: Input buffer should be NULL if there is no input"
411 " buffer sent in the request",
412 __func__);
413 }
414 }
415 request->numBuffersLeft -= numBuffersReturned;
416 if (request->numBuffersLeft < 0) {
417 ALOGE("%s: Too many buffers returned for frame %d", __func__, frameNumber);
418 ADD_FAILURE();
419 return notify;
420 }
421
422 for (const auto& buffer : results.outputBuffers) {
423 CameraAidlTest::InFlightRequest::StreamBufferAndTimestamp streamBufferAndTimestamp;
424 auto outstandingBuffers = mUseHalBufManager ? mOutstandingBufferIds :
425 request->mOutstandingBufferIds;
426 auto bufferId = mUseHalBufManager ? buffer.bufferId : results.frameNumber;
427 auto outputBuffer = outstandingBuffers.empty() ? ::android::makeFromAidl(buffer.buffer) :
428 outstandingBuffers[buffer.streamId][bufferId];
429 streamBufferAndTimestamp.buffer = {buffer.streamId,
430 bufferId,
431 outputBuffer,
432 buffer.status,
433 ::android::dupFromAidl(buffer.acquireFence),
434 ::android::dupFromAidl(buffer.releaseFence)};
435 streamBufferAndTimestamp.timeStamp = systemTime();
436 request->resultOutputBuffers.push_back(streamBufferAndTimestamp);
437 }
438 // If shutter event is received notify the pending threads.
439 if (request->shutterTimestamp != 0) {
440 notify = true;
441 }
442
443 if (mUseHalBufManager) {
444 returnStreamBuffers(results.outputBuffers);
445 }
446 return notify;
447 }
448
notifyHelper(const std::vector<NotifyMsg> & msgs,const std::vector<std::pair<bool,nsecs_t>> & readoutTimestamps)449 ScopedAStatus DeviceCb::notifyHelper(
450 const std::vector<NotifyMsg>& msgs,
451 const std::vector<std::pair<bool, nsecs_t>>& readoutTimestamps) {
452 std::lock_guard<std::mutex> l(mParent->mLock);
453
454 for (size_t i = 0; i < msgs.size(); i++) {
455 const NotifyMsg& msg = msgs[i];
456 NotifyMsg::Tag msgTag = msgs[i].getTag();
457 switch (msgTag) {
458 case NotifyMsg::Tag::error:
459 if (ErrorCode::ERROR_DEVICE == msg.get<NotifyMsg::Tag::error>().errorCode) {
460 ALOGE("%s: Camera reported serious device error", __func__);
461 ADD_FAILURE();
462 } else {
463 auto itr = mParent->mInflightMap.find(
464 msg.get<NotifyMsg::Tag::error>().frameNumber);
465 if (itr == mParent->mInflightMap.end()) {
466 ALOGE("%s: Unexpected error frame number! received: %u", __func__,
467 msg.get<NotifyMsg::Tag::error>().frameNumber);
468 ADD_FAILURE();
469 break;
470 }
471
472 auto r = itr->second;
473 if (ErrorCode::ERROR_RESULT == msg.get<NotifyMsg::Tag::error>().errorCode &&
474 msg.get<NotifyMsg::Tag::error>().errorStreamId != -1) {
475 if (r->haveResultMetadata) {
476 ALOGE("%s: Camera must report physical camera result error before "
477 "the final capture result!",
478 __func__);
479 ADD_FAILURE();
480 } else {
481 for (auto& mStream : mStreams) {
482 if (mStream.id == msg.get<NotifyMsg::Tag::error>().errorStreamId) {
483 std::string physicalCameraId = mStream.physicalCameraId;
484 bool idExpected =
485 r->expectedPhysicalResults.find(physicalCameraId) !=
486 r->expectedPhysicalResults.end();
487 if (!idExpected) {
488 ALOGE("%s: ERROR_RESULT's error stream's physicalCameraId "
489 "%s must be expected",
490 __func__, physicalCameraId.c_str());
491 ADD_FAILURE();
492 } else {
493 r->expectedPhysicalResults.erase(physicalCameraId);
494 }
495 break;
496 }
497 }
498 }
499 } else {
500 r->errorCodeValid = true;
501 r->errorCode = msg.get<NotifyMsg::Tag::error>().errorCode;
502 r->errorStreamId = msg.get<NotifyMsg::Tag::error>().errorStreamId;
503 }
504 }
505 break;
506 case NotifyMsg::Tag::shutter:
507 auto itr =
508 mParent->mInflightMap.find(msg.get<NotifyMsg::Tag::shutter>().frameNumber);
509 if (itr == mParent->mInflightMap.end()) {
510 ALOGE("%s: Unexpected shutter frame number! received: %u", __func__,
511 msg.get<NotifyMsg::Tag::shutter>().frameNumber);
512 ADD_FAILURE();
513 break;
514 }
515 auto& r = itr->second;
516 r->shutterTimestamp = msg.get<NotifyMsg::Tag::shutter>().timestamp;
517 r->shutterReadoutTimestampValid = readoutTimestamps[i].first;
518 r->shutterReadoutTimestamp = readoutTimestamps[i].second;
519 break;
520 }
521 }
522
523 mParent->mResultCondition.notify_one();
524 return ScopedAStatus::ok();
525 }
526
hasOutstandingBuffersLocked()527 bool DeviceCb::hasOutstandingBuffersLocked() {
528 if (!mUseHalBufManager) {
529 return false;
530 }
531 for (const auto& outstandingBuffers : mOutstandingBufferIds) {
532 if (!outstandingBuffers.empty()) {
533 return true;
534 }
535 }
536 return false;
537 }
538