1 /*
2  * Copyright (C) 2023 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 #define FAILURE_DEBUG_PREFIX "CameraDeviceSession"
18 
19 #include <inttypes.h>
20 
21 #include <chrono>
22 #include <memory>
23 
24 #include <log/log.h>
25 #include <aidlcommonsupport/NativeHandle.h>
26 #include <utils/ThreadDefs.h>
27 
28 #include <aidl/android/hardware/camera/device/ErrorCode.h>
29 #include <aidl/android/hardware/graphics/common/Dataspace.h>
30 
31 #include "debug.h"
32 #include "CameraDeviceSession.h"
33 #include "CameraDevice.h"
34 #include "metadata_utils.h"
35 
36 #include <system/camera_metadata.h>
37 
38 namespace android {
39 namespace hardware {
40 namespace camera {
41 namespace provider {
42 namespace implementation {
43 
44 using aidl::android::hardware::camera::common::Status;
45 using aidl::android::hardware::camera::device::CaptureResult;
46 using aidl::android::hardware::camera::device::ErrorCode;
47 using aidl::android::hardware::camera::device::StreamRotation;
48 using aidl::android::hardware::camera::device::StreamType;
49 
50 using aidl::android::hardware::graphics::common::Dataspace;
51 
52 namespace {
53 constexpr char kClass[] = "CameraDeviceSession";
54 
55 constexpr int64_t kOneSecondNs = 1000000000;
56 constexpr size_t kMsgQueueSize = 256 * 1024;
57 
timespecAddNanos(const struct timespec t,const int64_t addNs)58 struct timespec timespecAddNanos(const struct timespec t, const int64_t addNs) {
59     const lldiv_t r = lldiv(t.tv_nsec + addNs, kOneSecondNs);
60 
61     struct timespec tm;
62     tm.tv_sec = t.tv_sec + r.quot;
63     tm.tv_nsec = r.rem;
64 
65     return tm;
66 }
67 
timespec2nanos(const struct timespec t)68 int64_t timespec2nanos(const struct timespec t) {
69     return kOneSecondNs * t.tv_sec + t.tv_nsec;
70 }
71 
pixelFormatToStr(const PixelFormat fmt,char * buf,int bufSz)72 const char* pixelFormatToStr(const PixelFormat fmt, char* buf, int bufSz) {
73     switch (fmt) {
74     case PixelFormat::UNSPECIFIED: return "UNSPECIFIED";
75     case PixelFormat::IMPLEMENTATION_DEFINED: return "IMPLEMENTATION_DEFINED";
76     case PixelFormat::YCBCR_420_888: return "YCBCR_420_888";
77     case PixelFormat::RGBA_8888: return "RGBA_8888";
78     case PixelFormat::BLOB: return "BLOB";
79     default:
80         snprintf(buf, bufSz, "0x%x", static_cast<uint32_t>(fmt));
81         return buf;
82     }
83 }
84 
notifyError(ICameraDeviceCallback * cb,const int32_t frameNumber,const int32_t errorStreamId,const ErrorCode err)85 void notifyError(ICameraDeviceCallback* cb,
86                  const int32_t frameNumber,
87                  const int32_t errorStreamId,
88                  const ErrorCode err) {
89     using aidl::android::hardware::camera::device::NotifyMsg;
90     using aidl::android::hardware::camera::device::ErrorMsg;
91     using NotifyMsgTag = NotifyMsg::Tag;
92 
93     NotifyMsg msg;
94 
95     {
96         ErrorMsg errorMsg;
97         errorMsg.frameNumber = frameNumber;
98         errorMsg.errorStreamId = errorStreamId;
99         errorMsg.errorCode = err;
100         msg.set<NotifyMsgTag::error>(errorMsg);
101     }
102 
103     cb->notify({msg});
104 }
105 
notifyShutter(ICameraDeviceCallback * cb,const int32_t frameNumber,const int64_t shutterTimestamp,const int64_t readoutTimestamp)106 void notifyShutter(ICameraDeviceCallback* cb,
107                    const int32_t frameNumber,
108                    const int64_t shutterTimestamp,
109                    const int64_t readoutTimestamp) {
110     using aidl::android::hardware::camera::device::NotifyMsg;
111     using aidl::android::hardware::camera::device::ShutterMsg;
112     using NotifyMsgTag = NotifyMsg::Tag;
113 
114     NotifyMsg msg;
115 
116     {
117         ShutterMsg shutterMsg;
118         shutterMsg.frameNumber = frameNumber;
119         shutterMsg.timestamp = shutterTimestamp;
120         shutterMsg.readoutTimestamp = readoutTimestamp;
121         msg.set<NotifyMsgTag::shutter>(shutterMsg);
122     }
123 
124     cb->notify({msg});
125 }
126 
makeCaptureResult(const int frameNumber,CameraMetadata metadata,std::vector<StreamBuffer> outputBuffers)127 CaptureResult makeCaptureResult(const int frameNumber,
128                                 CameraMetadata metadata,
129                                 std::vector<StreamBuffer> outputBuffers) {
130     CaptureResult cr;
131     cr.frameNumber = frameNumber;
132     cr.result = std::move(metadata);
133     cr.outputBuffers = std::move(outputBuffers);
134     cr.inputBuffer.streamId = -1;
135     cr.inputBuffer.bufferId = 0;
136     cr.partialResult = cr.result.metadata.empty() ? 0 : 1;
137     return cr;
138 }
139 }  // namespace
140 
CameraDeviceSession(std::shared_ptr<CameraDevice> parent,std::shared_ptr<ICameraDeviceCallback> cb,hw::HwCamera & hwCamera)141 CameraDeviceSession::CameraDeviceSession(
142         std::shared_ptr<CameraDevice> parent,
143         std::shared_ptr<ICameraDeviceCallback> cb,
144         hw::HwCamera& hwCamera)
145          : mParent(std::move(parent))
146          , mCb(std::move(cb))
147          , mHwCamera(hwCamera)
148          , mRequestQueue(kMsgQueueSize, false)
149          , mResultQueue(kMsgQueueSize, false) {
150     LOG_ALWAYS_FATAL_IF(!mRequestQueue.isValid());
151     LOG_ALWAYS_FATAL_IF(!mResultQueue.isValid());
152     mCaptureThread = std::thread(&CameraDeviceSession::captureThreadLoop, this);
153     mDelayedCaptureThread = std::thread(&CameraDeviceSession::delayedCaptureThreadLoop, this);
154 }
155 
~CameraDeviceSession()156 CameraDeviceSession::~CameraDeviceSession() {
157     closeImpl();
158 
159     mCaptureRequests.cancel();
160     mDelayedCaptureResults.cancel();
161     mCaptureThread.join();
162     mDelayedCaptureThread.join();
163 }
164 
close()165 ScopedAStatus CameraDeviceSession::close() {
166     closeImpl();
167     return ScopedAStatus::ok();
168 }
169 
configureStreams(const StreamConfiguration & cfg,std::vector<HalStream> * halStreamsOut)170 ScopedAStatus CameraDeviceSession::configureStreams(
171         const StreamConfiguration& cfg,
172         std::vector<HalStream>* halStreamsOut) {
173     ALOGD("%s:%s:%d cfg={ "
174           ".streams.size=%zu, .operationMode=%u, .cfg.sessionParams.size()=%zu, "
175           " .streamConfigCounter=%d, .multiResolutionInputImage=%s }",
176           kClass, __func__, __LINE__,
177           cfg.streams.size(), static_cast<uint32_t>(cfg.operationMode),
178           cfg.sessionParams.metadata.size(), cfg.streamConfigCounter,
179           (cfg.multiResolutionInputImage ? "true" : "false"));
180 
181     for (const auto& s : cfg.streams) {
182         const uint32_t dataspaceBits = static_cast<uint32_t>(s.dataSpace);
183         const uint32_t dataspaceLow = dataspaceBits & 0xFFFF;
184         const uint32_t dataspaceS =
185             (dataspaceBits & static_cast<uint32_t>(Dataspace::STANDARD_MASK)) >>
186             static_cast<uint32_t>(Dataspace::STANDARD_SHIFT);
187         const uint32_t dataspaceT =
188             (dataspaceBits & static_cast<uint32_t>(Dataspace::TRANSFER_MASK)) >>
189             static_cast<uint32_t>(Dataspace::TRANSFER_SHIFT);
190         const uint32_t dataspaceR =
191             (dataspaceBits & static_cast<uint32_t>(Dataspace::RANGE_MASK)) >>
192             static_cast<uint32_t>(Dataspace::RANGE_SHIFT);
193 
194         char pixelFormatStrBuf[16];
195 
196         ALOGD("%s:%s:%d stream={ .id=%d, "
197               ".streamType=%u, .width=%d, .height=%d, .format=%s, .usage=0x%" PRIx64 ", "
198               ".dataSpace={ .low=0x%x, .s=%u, .t=%u, .r=%u }, .rotation=%u, .physicalCameraId='%s', .bufferSize=%d, "
199               ".groupId=%d, .dynamicRangeProfile=0x%x }", kClass, __func__, __LINE__,
200               s.id, static_cast<unsigned>(s.streamType), s.width, s.height,
201               pixelFormatToStr(s.format, pixelFormatStrBuf, sizeof(pixelFormatStrBuf)),
202               static_cast<uint64_t>(s.usage),
203               dataspaceLow, dataspaceS, dataspaceT, dataspaceR,
204               static_cast<unsigned>(s.rotation),
205               s.physicalCameraId.c_str(), s.bufferSize, s.groupId,
206               static_cast<unsigned>(s.dynamicRangeProfile)
207         );
208     }
209 
210     auto [status, halStreams] = configureStreamsStatic(cfg, mHwCamera);
211     if (status != Status::OK) {
212         return toScopedAStatus(status);
213     }
214 
215     const size_t nStreams = cfg.streams.size();
216     LOG_ALWAYS_FATAL_IF(halStreams.size() != nStreams);
217 
218     if (mHwCamera.configure(cfg.sessionParams, nStreams,
219                             cfg.streams.data(), halStreams.data())) {
220         mStreamBufferCache.clearStreamInfo();
221         *halStreamsOut = std::move(halStreams);
222         return ScopedAStatus::ok();
223     } else {
224         return toScopedAStatus(FAILURE(Status::INTERNAL_ERROR));
225     }
226 }
227 
constructDefaultRequestSettings(const RequestTemplate tpl,CameraMetadata * metadata)228 ScopedAStatus CameraDeviceSession::constructDefaultRequestSettings(
229         const RequestTemplate tpl,
230         CameraMetadata* metadata) {
231     auto maybeMetadata = serializeCameraMetadataMap(
232         mParent->constructDefaultRequestSettings(tpl));
233 
234     if (maybeMetadata) {
235         *metadata = std::move(maybeMetadata.value());
236         return ScopedAStatus::ok();
237     } else {
238         return toScopedAStatus(Status::INTERNAL_ERROR);
239     }
240 }
241 
flush()242 ScopedAStatus CameraDeviceSession::flush() {
243     flushImpl(std::chrono::steady_clock::now());
244     return ScopedAStatus::ok();
245 }
246 
getCaptureRequestMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * desc)247 ScopedAStatus CameraDeviceSession::getCaptureRequestMetadataQueue(
248         MQDescriptor<int8_t, SynchronizedReadWrite>* desc) {
249     *desc = mRequestQueue.dupeDesc();
250     return ScopedAStatus::ok();
251 }
252 
getCaptureResultMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * desc)253 ScopedAStatus CameraDeviceSession::getCaptureResultMetadataQueue(
254         MQDescriptor<int8_t, SynchronizedReadWrite>* desc) {
255     *desc = mResultQueue.dupeDesc();
256     return ScopedAStatus::ok();
257 }
258 
isReconfigurationRequired(const CameraMetadata &,const CameraMetadata &,bool * resultOut)259 ScopedAStatus CameraDeviceSession::isReconfigurationRequired(
260         const CameraMetadata& /*oldParams*/,
261         const CameraMetadata& /*newParams*/,
262         bool* resultOut) {
263     *resultOut = false;
264     return ScopedAStatus::ok();
265 }
266 
processCaptureRequest(const std::vector<CaptureRequest> & requests,const std::vector<BufferCache> & cachesToRemove,int32_t * countOut)267 ScopedAStatus CameraDeviceSession::processCaptureRequest(
268         const std::vector<CaptureRequest>& requests,
269         const std::vector<BufferCache>& cachesToRemove,
270         int32_t* countOut) {
271     for (const BufferCache& bc : cachesToRemove) {
272         mStreamBufferCache.remove(bc.bufferId);
273     }
274 
275     int count = 0;
276     for (const CaptureRequest& r : requests) {
277         const Status s = processOneCaptureRequest(r);
278         if (s == Status::OK) {
279             ++count;
280         } else {
281             *countOut = count;
282             return toScopedAStatus(s);
283         }
284     }
285 
286     *countOut = count;
287     return ScopedAStatus::ok();
288 }
289 
signalStreamFlush(const std::vector<int32_t> &,const int32_t)290 ScopedAStatus CameraDeviceSession::signalStreamFlush(
291         const std::vector<int32_t>& /*streamIds*/,
292         const int32_t /*streamConfigCounter*/) {
293     return toScopedAStatus(FAILURE(Status::OPERATION_NOT_SUPPORTED));
294 }
295 
switchToOffline(const std::vector<int32_t> &,CameraOfflineSessionInfo *,std::shared_ptr<ICameraOfflineSession> *)296 ScopedAStatus CameraDeviceSession::switchToOffline(
297         const std::vector<int32_t>& /*streamsToKeep*/,
298         CameraOfflineSessionInfo* /*offlineSessionInfo*/,
299         std::shared_ptr<ICameraOfflineSession>* /*session*/) {
300     return toScopedAStatus(FAILURE(Status::OPERATION_NOT_SUPPORTED));
301 }
302 
repeatingRequestEnd(const int32_t,const std::vector<int32_t> &)303 ScopedAStatus CameraDeviceSession::repeatingRequestEnd(
304         const int32_t /*frameNumber*/,
305         const std::vector<int32_t>& /*streamIds*/) {
306     return ScopedAStatus::ok();
307 }
308 
isStreamCombinationSupported(const StreamConfiguration & cfg,hw::HwCamera & hwCamera)309 bool CameraDeviceSession::isStreamCombinationSupported(const StreamConfiguration& cfg,
310                                                        hw::HwCamera& hwCamera) {
311     const auto [status, unused] = configureStreamsStatic(cfg, hwCamera);
312     return status == Status::OK;
313 }
314 
closeImpl()315 void CameraDeviceSession::closeImpl() {
316     flushImpl(std::chrono::steady_clock::now());
317     mHwCamera.close();
318 }
319 
flushImpl(const std::chrono::steady_clock::time_point start)320 void CameraDeviceSession::flushImpl(const std::chrono::steady_clock::time_point start) {
321     mFlushing = true;
322     waitFlushingDone(start);
323     mFlushing = false;
324 }
325 
waitFlushingDone(const std::chrono::steady_clock::time_point start)326 int CameraDeviceSession::waitFlushingDone(const std::chrono::steady_clock::time_point start) {
327     std::unique_lock<std::mutex> lock(mNumBuffersInFlightMtx);
328     if (mNumBuffersInFlight == 0) {
329         return 0;
330     }
331 
332     using namespace std::chrono_literals;
333     constexpr int kRecommendedDeadlineMs = 100;
334     constexpr int kFatalDeadlineMs = 1000;
335     const auto fatalDeadline = start + (1ms * kFatalDeadlineMs);
336 
337     const auto checkIfNoBuffersInFlight = [this](){ return mNumBuffersInFlight == 0; };
338 
339     if (mNoBuffersInFlight.wait_until(lock, fatalDeadline, checkIfNoBuffersInFlight)) {
340         const int waitedForMs = (std::chrono::steady_clock::now() - start) / 1ms;
341 
342         if (waitedForMs > kRecommendedDeadlineMs) {
343             ALOGW("%s:%s:%d: flushing took %dms, Android "
344                   "recommends %dms latency and requires no more than %dms",
345                   kClass, __func__, __LINE__, waitedForMs, kRecommendedDeadlineMs,
346                   kFatalDeadlineMs);
347         }
348 
349         return waitedForMs;
350     } else {
351         LOG_ALWAYS_FATAL("%s:%s:%d: %zu buffers are still in "
352                          "flight after %dms of waiting, some buffers might have "
353                          "leaked", kClass, __func__, __LINE__, mNumBuffersInFlight,
354                          kFatalDeadlineMs);
355     }
356 }
357 
358 std::pair<Status, std::vector<HalStream>>
configureStreamsStatic(const StreamConfiguration & cfg,hw::HwCamera & hwCamera)359 CameraDeviceSession::configureStreamsStatic(const StreamConfiguration& cfg,
360                                             hw::HwCamera& hwCamera) {
361     if (cfg.multiResolutionInputImage) {
362         return {FAILURE(Status::OPERATION_NOT_SUPPORTED), {}};
363     }
364 
365     const size_t streamsSize = cfg.streams.size();
366     if (!streamsSize) {
367         return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
368     }
369 
370     std::vector<HalStream> halStreams;
371     halStreams.reserve(streamsSize);
372 
373     for (const auto& s : cfg.streams) {
374         if (s.streamType == StreamType::INPUT) {
375             return {FAILURE(Status::OPERATION_NOT_SUPPORTED), {}};
376         }
377 
378         if (s.width <= 0) {
379             return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
380         }
381 
382         if (s.height <= 0) {
383             return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
384         }
385 
386         if (s.rotation != StreamRotation::ROTATION_0) {
387             return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
388         }
389 
390         if (s.bufferSize < 0) {
391             return {FAILURE(Status::ILLEGAL_ARGUMENT), {}};
392         }
393 
394         HalStream hs;
395         std::tie(hs.overrideFormat, hs.producerUsage,
396                  hs.overrideDataSpace, hs.maxBuffers) =
397             hwCamera.overrideStreamParams(s.format, s.usage, s.dataSpace);
398 
399         if (hs.maxBuffers <= 0) {
400             switch (hs.maxBuffers) {
401             case hw::HwCamera::kErrorBadFormat:
402                 ALOGE("%s:%s:%d unexpected format=0x%" PRIx32,
403                       kClass, __func__, __LINE__, static_cast<uint32_t>(s.format));
404                 return {Status::ILLEGAL_ARGUMENT, {}};
405 
406             case hw::HwCamera::kErrorBadUsage:
407                 ALOGE("%s:%s:%d unexpected usage=0x%" PRIx64
408                       " for format=0x%" PRIx32 " and dataSpace=0x%" PRIx32,
409                       kClass, __func__, __LINE__, static_cast<uint64_t>(s.usage),
410                       static_cast<uint32_t>(s.format),
411                       static_cast<uint32_t>(s.dataSpace));
412                 return {Status::ILLEGAL_ARGUMENT, {}};
413 
414             case hw::HwCamera::kErrorBadDataspace:
415                 ALOGE("%s:%s:%d unexpected dataSpace=0x%" PRIx32
416                       " for format=0x%" PRIx32 " and usage=0x%" PRIx64,
417                       kClass, __func__, __LINE__, static_cast<uint32_t>(s.dataSpace),
418                       static_cast<uint32_t>(s.format),
419                       static_cast<uint64_t>(s.usage));
420                 return {Status::ILLEGAL_ARGUMENT, {}};
421 
422             default:
423                 ALOGE("%s:%s:%d something is not right for format=0x%" PRIx32
424                       " usage=0x%" PRIx64 " and dataSpace=0x%" PRIx32,
425                       kClass, __func__, __LINE__, static_cast<uint32_t>(s.format),
426                       static_cast<uint64_t>(s.usage),
427                       static_cast<uint32_t>(s.dataSpace));
428                 return {Status::ILLEGAL_ARGUMENT, {}};
429             }
430         }
431 
432         hs.id = s.id;
433         hs.consumerUsage = static_cast<BufferUsage>(0);
434         hs.physicalCameraId = s.physicalCameraId;
435         hs.supportOffline = false;
436 
437         halStreams.push_back(std::move(hs));
438     }
439 
440     return {Status::OK, std::move(halStreams)};
441 }
442 
processOneCaptureRequest(const CaptureRequest & request)443 Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
444     // If inputBuffer is valid, the request is for reprocessing
445     if (!isAidlNativeHandleEmpty(request.inputBuffer.buffer)) {
446         return FAILURE(Status::OPERATION_NOT_SUPPORTED);
447     }
448 
449     if (request.inputWidth || request.inputHeight) {
450         return FAILURE(Status::OPERATION_NOT_SUPPORTED);
451     }
452 
453     if (!request.physicalCameraSettings.empty()) {
454         return FAILURE(Status::OPERATION_NOT_SUPPORTED);
455     }
456 
457     const size_t outputBuffersSize = request.outputBuffers.size();
458 
459     if (outputBuffersSize == 0) {
460         return FAILURE(Status::ILLEGAL_ARGUMENT);
461     }
462 
463     HwCaptureRequest hwReq;
464 
465     if (request.fmqSettingsSize < 0) {
466         return FAILURE(Status::ILLEGAL_ARGUMENT);
467     } else if (request.fmqSettingsSize > 0) {
468         CameraMetadata tmp;
469         tmp.metadata.resize(request.fmqSettingsSize);
470 
471         if (mRequestQueue.read(
472                 reinterpret_cast<int8_t*>(tmp.metadata.data()),
473                 request.fmqSettingsSize)) {
474             hwReq.metadataUpdate = std::move(tmp);
475         } else {
476             return FAILURE(Status::INTERNAL_ERROR);
477         }
478     } else if (!request.settings.metadata.empty()) {
479         hwReq.metadataUpdate = request.settings;
480     }
481 
482     hwReq.buffers.resize(outputBuffersSize);
483     for (size_t i = 0; i < outputBuffersSize; ++i) {
484         hwReq.buffers[i] = mStreamBufferCache.update(request.outputBuffers[i]);
485     }
486 
487     {
488         std::lock_guard<std::mutex> guard(mNumBuffersInFlightMtx);
489         mNumBuffersInFlight += outputBuffersSize;
490     }
491 
492     hwReq.frameNumber = request.frameNumber;
493 
494     if (mCaptureRequests.put(&hwReq)) {
495         return Status::OK;
496     } else {
497         disposeCaptureRequest(std::move(hwReq));
498         return FAILURE(Status::INTERNAL_ERROR);
499     }
500 }
501 
captureThreadLoop()502 void CameraDeviceSession::captureThreadLoop() {
503     setThreadPriority(SP_FOREGROUND, ANDROID_PRIORITY_VIDEO);
504 
505     struct timespec nextFrameT;
506     clock_gettime(CLOCK_MONOTONIC, &nextFrameT);
507     while (true) {
508         std::optional<HwCaptureRequest> maybeReq = mCaptureRequests.get();
509         if (maybeReq.has_value()) {
510             HwCaptureRequest& req = maybeReq.value();
511             if (mFlushing) {
512                 disposeCaptureRequest(std::move(req));
513             } else {
514                 nextFrameT = captureOneFrame(nextFrameT, std::move(req));
515             }
516         } else {
517             break;
518         }
519     }
520 }
521 
captureOneFrame(struct timespec nextFrameT,HwCaptureRequest req)522 struct timespec CameraDeviceSession::captureOneFrame(struct timespec nextFrameT,
523                                                      HwCaptureRequest req) {
524     struct timespec now;
525     clock_gettime(CLOCK_MONOTONIC, &now);
526     if (std::make_pair(now.tv_sec, now.tv_nsec) <
527             std::make_pair(nextFrameT.tv_sec, nextFrameT.tv_nsec)) {
528         clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &nextFrameT, nullptr);
529     } else {
530         nextFrameT = now;
531     }
532 
533     const int32_t frameNumber = req.frameNumber;
534 
535     auto [frameDurationNs, exposureDurationNs, metadata,
536           outputBuffers, delayedOutputBuffers] =
537         mHwCamera.processCaptureRequest(std::move(req.metadataUpdate),
538                                         {req.buffers.begin(), req.buffers.end()});
539 
540     for (hw::DelayedStreamBuffer& dsb : delayedOutputBuffers) {
541         DelayedCaptureResult dcr;
542         dcr.delayedBuffer = std::move(dsb);
543         dcr.frameNumber = frameNumber;
544         if (!mDelayedCaptureResults.put(&dcr)) {
545             // `delayedBuffer(false)` only releases the buffer (fast).
546             outputBuffers.push_back(dcr.delayedBuffer(false));
547         }
548     }
549 
550     const int64_t shutterTimestampNs = timespec2nanos(nextFrameT);
551     notifyShutter(&*mCb, frameNumber, shutterTimestampNs, shutterTimestampNs + exposureDurationNs);
552     metadataSetShutterTimestamp(&metadata, shutterTimestampNs);
553     consumeCaptureResult(makeCaptureResult(frameNumber,
554         std::move(metadata), std::move(outputBuffers)));
555 
556     if (frameDurationNs > 0) {
557         nextFrameT = timespecAddNanos(nextFrameT, frameDurationNs);
558     } else {
559         notifyError(&*mCb, frameNumber, -1, ErrorCode::ERROR_DEVICE);
560     }
561 
562     return nextFrameT;
563 }
564 
delayedCaptureThreadLoop()565 void CameraDeviceSession::delayedCaptureThreadLoop() {
566     while (true) {
567         std::optional<DelayedCaptureResult> maybeDCR = mDelayedCaptureResults.get();
568         if (maybeDCR.has_value()) {
569             const DelayedCaptureResult& dcr = maybeDCR.value();
570 
571             // `dcr.delayedBuffer(true)` is expected to be slow, so we do not
572             // produce too much IPC traffic here. This also returns buffes to
573             // the framework earlier to reuse in capture requests.
574             std::vector<StreamBuffer> outputBuffers(1);
575             outputBuffers.front() = dcr.delayedBuffer(!mFlushing);
576             consumeCaptureResult(makeCaptureResult(dcr.frameNumber,
577                 {}, std::move(outputBuffers)));
578         } else {
579             break;
580         }
581     }
582 }
583 
disposeCaptureRequest(HwCaptureRequest req)584 void CameraDeviceSession::disposeCaptureRequest(HwCaptureRequest req) {
585     notifyError(&*mCb, req.frameNumber, -1, ErrorCode::ERROR_REQUEST);
586 
587     const size_t reqBuffersSize = req.buffers.size();
588 
589     {
590         std::vector<StreamBuffer> outputBuffers(reqBuffersSize);
591 
592         for (size_t i = 0; i < reqBuffersSize; ++i) {
593             CachedStreamBuffer* csb = req.buffers[i];
594             LOG_ALWAYS_FATAL_IF(!csb);  // otherwise mNumBuffersInFlight will be hard
595             outputBuffers[i] = csb->finish(false);
596         }
597 
598         std::vector<CaptureResult> crs(1);
599         crs.front() = makeCaptureResult(req.frameNumber, {},
600                                         std::move(outputBuffers));
601 
602         std::lock_guard<std::mutex> guard(mResultQueueMutex);
603         mCb->processCaptureResult(std::move(crs));
604     }
605 
606     notifyBuffersReturned(reqBuffersSize);
607 }
608 
consumeCaptureResult(CaptureResult cr)609 void CameraDeviceSession::consumeCaptureResult(CaptureResult cr) {
610     const size_t numBuffers = cr.outputBuffers.size();
611 
612     {
613         std::lock_guard<std::mutex> guard(mResultQueueMutex);
614         const size_t metadataSize = cr.result.metadata.size();
615         if ((metadataSize > 0) && mResultQueue.write(
616                 reinterpret_cast<int8_t*>(cr.result.metadata.data()),
617                 metadataSize)) {
618             cr.fmqResultSize = metadataSize;
619             cr.result.metadata.clear();
620         }
621 
622         std::vector<CaptureResult> crs(1);
623         crs.front() = std::move(cr);
624         mCb->processCaptureResult(std::move(crs));
625     }
626 
627     notifyBuffersReturned(numBuffers);
628 }
629 
notifyBuffersReturned(const size_t numBuffersToReturn)630 void CameraDeviceSession::notifyBuffersReturned(const size_t numBuffersToReturn) {
631     std::lock_guard<std::mutex> guard(mNumBuffersInFlightMtx);
632     LOG_ALWAYS_FATAL_IF(mNumBuffersInFlight < numBuffersToReturn,
633                         "mNumBuffersInFlight=%zu numBuffersToReturn=%zu",
634                         mNumBuffersInFlight, numBuffersToReturn);
635 
636     mNumBuffersInFlight -= numBuffersToReturn;
637 
638     if (mNumBuffersInFlight == 0) {
639         mNoBuffersInFlight.notify_all();
640     }
641 }
642 
643 }  // namespace implementation
644 }  // namespace provider
645 }  // namespace camera
646 }  // namespace hardware
647 }  // namespace android
648