1 /*
2  * Copyright (C) 2021 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 #define LOG_TAG "VsockCameraDeviceSession"
17 #include "vsock_camera_device_session_3_4.h"
18 #include <hidl/Status.h>
19 #include <include/convert.h>
20 #include <inttypes.h>
21 #include <libyuv.h>
22 #include <log/log.h>
23 #include "vsock_camera_metadata.h"
24 
25 // Partially copied from ExternalCameraDeviceSession
26 namespace android::hardware::camera::device::V3_4::implementation {
27 
VsockCameraDeviceSession(VsockCameraMetadata camera_characteristics,std::shared_ptr<cuttlefish::VsockFrameProvider> frame_provider,const sp<ICameraDeviceCallback> & callback)28 VsockCameraDeviceSession::VsockCameraDeviceSession(
29     VsockCameraMetadata camera_characteristics,
30     std::shared_ptr<cuttlefish::VsockFrameProvider> frame_provider,
31     const sp<ICameraDeviceCallback>& callback)
32     : camera_characteristics_(camera_characteristics),
33       frame_provider_(frame_provider),
34       callback_(callback) {
35   static constexpr size_t kMsgQueueSize = 256 * 1024;
36   request_queue_ =
37       std::make_unique<MessageQueue<uint8_t, kSynchronizedReadWrite>>(
38           kMsgQueueSize, false);
39   result_queue_ =
40       std::make_shared<MessageQueue<uint8_t, kSynchronizedReadWrite>>(
41           kMsgQueueSize, false);
42   unsigned int timeout_ms = 1000 / camera_characteristics.getPreferredFps();
43   process_requests_ = true;
44   request_processor_ =
45       std::thread([this, timeout_ms] { processRequestLoop(timeout_ms); });
46 }
47 
~VsockCameraDeviceSession()48 VsockCameraDeviceSession::~VsockCameraDeviceSession() { close(); }
49 
constructDefaultRequestSettings(V3_2::RequestTemplate type,V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb)50 Return<void> VsockCameraDeviceSession::constructDefaultRequestSettings(
51     V3_2::RequestTemplate type,
52     V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
53   auto frame_rate = camera_characteristics_.getPreferredFps();
54   auto metadata = VsockCameraRequestMetadata(frame_rate, type);
55   V3_2::CameraMetadata hidl_metadata;
56   Status status = metadata.isValid() ? Status::OK : Status::ILLEGAL_ARGUMENT;
57   if (metadata.isValid()) {
58     camera_metadata_t* metadata_ptr = metadata.release();
59     hidl_metadata.setToExternal((uint8_t*)metadata_ptr,
60                                 get_camera_metadata_size(metadata_ptr));
61   }
62   _hidl_cb(status, hidl_metadata);
63   return Void();
64 }
65 
getCaptureRequestMetadataQueue(ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb)66 Return<void> VsockCameraDeviceSession::getCaptureRequestMetadataQueue(
67     ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
68   _hidl_cb(*request_queue_->getDesc());
69   return Void();
70 }
71 
getCaptureResultMetadataQueue(ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb)72 Return<void> VsockCameraDeviceSession::getCaptureResultMetadataQueue(
73     ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
74   _hidl_cb(*result_queue_->getDesc());
75   return Void();
76 }
77 
configureStreams(const V3_2::StreamConfiguration & streams,ICameraDeviceSession::configureStreams_cb _hidl_cb)78 Return<void> VsockCameraDeviceSession::configureStreams(
79     const V3_2::StreamConfiguration& streams,
80     ICameraDeviceSession::configureStreams_cb _hidl_cb) {
81   // common configureStreams operate with v3_2 config and v3_3
82   // streams so we need to "downcast" v3_3 streams to v3_2 streams
83   V3_2::HalStreamConfiguration out_v32;
84   V3_3::HalStreamConfiguration out_v33;
85 
86   Status status = configureStreams(streams, &out_v33);
87   size_t size = out_v33.streams.size();
88   out_v32.streams.resize(size);
89   for (size_t i = 0; i < size; i++) {
90     out_v32.streams[i] = out_v33.streams[i].v3_2;
91   }
92   _hidl_cb(status, out_v32);
93   return Void();
94 }
95 
configureStreams_3_3(const V3_2::StreamConfiguration & streams,ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb)96 Return<void> VsockCameraDeviceSession::configureStreams_3_3(
97     const V3_2::StreamConfiguration& streams,
98     ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) {
99   V3_3::HalStreamConfiguration out_v33;
100   Status status = configureStreams(streams, &out_v33);
101   _hidl_cb(status, out_v33);
102   return Void();
103 }
104 
configureStreams_3_4(const V3_4::StreamConfiguration & requestedConfiguration,ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)105 Return<void> VsockCameraDeviceSession::configureStreams_3_4(
106     const V3_4::StreamConfiguration& requestedConfiguration,
107     ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
108   // common configureStreams operate with v3_2 config and v3_3
109   // streams so we need to "downcast" v3_4 config to v3_2 and
110   // "upcast" v3_3 streams to v3_4 streams
111   V3_2::StreamConfiguration config_v32;
112   V3_3::HalStreamConfiguration out_v33;
113   V3_4::HalStreamConfiguration out_v34;
114 
115   config_v32.operationMode = requestedConfiguration.operationMode;
116   config_v32.streams.resize(requestedConfiguration.streams.size());
117   for (size_t i = 0; i < config_v32.streams.size(); i++) {
118     config_v32.streams[i] = requestedConfiguration.streams[i].v3_2;
119   }
120   max_blob_size_ = getBlobSize(requestedConfiguration);
121   Status status = configureStreams(config_v32, &out_v33);
122 
123   out_v34.streams.resize(out_v33.streams.size());
124   for (size_t i = 0; i < out_v34.streams.size(); i++) {
125     out_v34.streams[i].v3_3 = out_v33.streams[i];
126   }
127   _hidl_cb(status, out_v34);
128   return Void();
129 }
130 
processCaptureRequest(const hidl_vec<CaptureRequest> & requests,const hidl_vec<BufferCache> & cachesToRemove,ICameraDeviceSession::processCaptureRequest_cb _hidl_cb)131 Return<void> VsockCameraDeviceSession::processCaptureRequest(
132     const hidl_vec<CaptureRequest>& requests,
133     const hidl_vec<BufferCache>& cachesToRemove,
134     ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
135   updateBufferCaches(cachesToRemove);
136 
137   uint32_t count;
138   Status s = Status::OK;
139   for (count = 0; count < requests.size(); count++) {
140     s = processOneCaptureRequest(requests[count]);
141     if (s != Status::OK) {
142       break;
143     }
144   }
145 
146   _hidl_cb(s, count);
147   return Void();
148 }
149 
processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest> & requests,const hidl_vec<V3_2::BufferCache> & cachesToRemove,ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb)150 Return<void> VsockCameraDeviceSession::processCaptureRequest_3_4(
151     const hidl_vec<V3_4::CaptureRequest>& requests,
152     const hidl_vec<V3_2::BufferCache>& cachesToRemove,
153     ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
154   updateBufferCaches(cachesToRemove);
155 
156   uint32_t count;
157   Status s = Status::OK;
158   for (count = 0; count < requests.size(); count++) {
159     s = processOneCaptureRequest(requests[count].v3_2);
160     if (s != Status::OK) {
161       break;
162     }
163   }
164 
165   _hidl_cb(s, count);
166   return Void();
167 }
168 
flush()169 Return<Status> VsockCameraDeviceSession::flush() {
170   auto timeout = std::chrono::seconds(1);
171   std::unique_lock<std::mutex> lock(request_mutex_);
172   flushing_requests_ = true;
173   auto is_empty = [this] { return pending_requests_.empty(); };
174   if (!queue_empty_.wait_for(lock, timeout, is_empty)) {
175     ALOGE("Flush timeout - %zu pending requests", pending_requests_.size());
176   }
177   flushing_requests_ = false;
178   return Status::OK;
179 }
180 
close()181 Return<void> VsockCameraDeviceSession::close() {
182   process_requests_ = false;
183   if (request_processor_.joinable()) {
184     request_processor_.join();
185   }
186   frame_provider_->stop();
187   buffer_cache_.clear();
188   ALOGI("%s", __FUNCTION__);
189   return Void();
190 }
191 
192 using ::android::hardware::graphics::common::V1_0::BufferUsage;
193 using ::android::hardware::graphics::common::V1_0::PixelFormat;
configureStreams(const V3_2::StreamConfiguration & config,V3_3::HalStreamConfiguration * out)194 Status VsockCameraDeviceSession::configureStreams(
195     const V3_2::StreamConfiguration& config,
196     V3_3::HalStreamConfiguration* out) {
197   Status status = isStreamConfigurationSupported(config);
198   if (status != Status::OK) {
199     return status;
200   }
201   updateStreamInfo(config);
202   out->streams.resize(config.streams.size());
203   for (size_t i = 0; i < config.streams.size(); i++) {
204     out->streams[i].overrideDataSpace = config.streams[i].dataSpace;
205     out->streams[i].v3_2.id = config.streams[i].id;
206     out->streams[i].v3_2.producerUsage =
207         config.streams[i].usage | BufferUsage::CPU_WRITE_OFTEN;
208     out->streams[i].v3_2.consumerUsage = 0;
209     out->streams[i].v3_2.maxBuffers = 2;
210     out->streams[i].v3_2.overrideFormat =
211         config.streams[i].format == PixelFormat::IMPLEMENTATION_DEFINED
212             ? PixelFormat::YCBCR_420_888
213             : config.streams[i].format;
214   }
215   return Status::OK;
216 }
217 
218 using ::android::hardware::camera::device::V3_2::StreamRotation;
219 using ::android::hardware::camera::device::V3_2::StreamType;
isStreamConfigurationSupported(const V3_2::StreamConfiguration & config)220 Status VsockCameraDeviceSession::isStreamConfigurationSupported(
221     const V3_2::StreamConfiguration& config) {
222   camera_metadata_entry device_supported_streams = camera_characteristics_.find(
223       ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
224   int32_t stall_stream_count = 0;
225   int32_t stream_count = 0;
226   for (const auto& stream : config.streams) {
227     if (stream.rotation != StreamRotation::ROTATION_0) {
228       ALOGE("Unsupported rotation enum value %d", stream.rotation);
229       return Status::ILLEGAL_ARGUMENT;
230     }
231     if (stream.streamType == StreamType::INPUT) {
232       ALOGE("Input stream not supported");
233       return Status::ILLEGAL_ARGUMENT;
234     }
235     bool is_supported = false;
236     // check pixel format and dimensions against camera metadata
237     for (int i = 0; i + 4 <= device_supported_streams.count; i += 4) {
238       auto format =
239           static_cast<PixelFormat>(device_supported_streams.data.i32[i]);
240       int32_t width = device_supported_streams.data.i32[i + 1];
241       int32_t height = device_supported_streams.data.i32[i + 2];
242       if (stream.format == format && stream.width == width &&
243           stream.height == height) {
244         is_supported = true;
245         break;
246       }
247     }
248     if (!is_supported) {
249       ALOGE("Unsupported format %d (%dx%d)", stream.format, stream.width,
250             stream.height);
251       return Status::ILLEGAL_ARGUMENT;
252     }
253     if (stream.format == PixelFormat::BLOB) {
254       stall_stream_count++;
255     } else {
256       stream_count++;
257     }
258   }
259   camera_metadata_entry device_stream_counts =
260       camera_characteristics_.find(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS);
261   static constexpr auto stream_index = 1;
262   auto expected_stream_count = device_stream_counts.count > stream_index
263                                    ? device_stream_counts.data.i32[stream_index]
264                                    : 0;
265   if (stream_count > expected_stream_count) {
266     ALOGE("Too many processed streams (expect <= %d, got %d)",
267           expected_stream_count, stream_count);
268     return Status::ILLEGAL_ARGUMENT;
269   }
270   static constexpr auto stall_stream_index = 2;
271   expected_stream_count =
272       device_stream_counts.count > stall_stream_index
273           ? device_stream_counts.data.i32[stall_stream_index]
274           : 0;
275   if (stall_stream_count > expected_stream_count) {
276     ALOGE("Too many stall streams (expect <= %d, got %d)",
277           expected_stream_count, stall_stream_count);
278     return Status::ILLEGAL_ARGUMENT;
279   }
280   return Status::OK;
281 }
282 
getBlobSize(const V3_4::StreamConfiguration & requestedConfiguration)283 unsigned int VsockCameraDeviceSession::getBlobSize(
284     const V3_4::StreamConfiguration& requestedConfiguration) {
285   camera_metadata_entry jpeg_entry =
286       camera_characteristics_.find(ANDROID_JPEG_MAX_SIZE);
287   unsigned int blob_size = jpeg_entry.count > 0 ? jpeg_entry.data.i32[0] : 0;
288   for (auto& stream : requestedConfiguration.streams) {
289     if (stream.v3_2.format == PixelFormat::BLOB) {
290       if (stream.bufferSize < blob_size) {
291         blob_size = stream.bufferSize;
292       }
293     }
294   }
295   return blob_size;
296 }
297 
updateBufferCaches(const hidl_vec<BufferCache> & to_remove)298 void VsockCameraDeviceSession::updateBufferCaches(
299     const hidl_vec<BufferCache>& to_remove) {
300   for (auto& cache : to_remove) {
301     buffer_cache_.remove(cache.bufferId);
302   }
303 }
304 
updateStreamInfo(const V3_2::StreamConfiguration & config)305 void VsockCameraDeviceSession::updateStreamInfo(
306     const V3_2::StreamConfiguration& config) {
307   std::set<int32_t> stream_ids;
308   for (const auto& stream : config.streams) {
309     stream_cache_[stream.id] = stream;
310     stream_ids.emplace(stream.id);
311   }
312   buffer_cache_.removeStreamsExcept(stream_ids);
313 }
314 
processOneCaptureRequest(const CaptureRequest & request)315 Status VsockCameraDeviceSession::processOneCaptureRequest(
316     const CaptureRequest& request) {
317   const camera_metadata_t* request_settings = nullptr;
318   V3_2::CameraMetadata hidl_settings;
319   if (request.fmqSettingsSize > 0) {
320     if (!getRequestSettingsFmq(request.fmqSettingsSize, hidl_settings)) {
321       ALOGE("%s: Could not read capture request settings from fmq!",
322             __FUNCTION__);
323       return Status::ILLEGAL_ARGUMENT;
324     } else if (!V3_2::implementation::convertFromHidl(hidl_settings,
325                                                       &request_settings)) {
326       ALOGE("%s: fmq request settings metadata is corrupt!", __FUNCTION__);
327       return Status::ILLEGAL_ARGUMENT;
328     }
329   } else if (!V3_2::implementation::convertFromHidl(request.settings,
330                                                     &request_settings)) {
331     ALOGE("%s: request settings metadata is corrupt!", __FUNCTION__);
332     return Status::ILLEGAL_ARGUMENT;
333   }
334   if (request_settings != nullptr) {
335     // Update request settings. This must happen on first request
336     std::lock_guard<std::mutex> lock(settings_mutex_);
337     latest_request_settings_ = request_settings;
338   } else if (latest_request_settings_.isEmpty()) {
339     ALOGE("%s: Undefined capture request settings!", __FUNCTION__);
340     return Status::ILLEGAL_ARGUMENT;
341   }
342 
343   std::vector<uint64_t> buffer_ids;
344   buffer_ids.reserve(request.outputBuffers.size());
345   for (size_t i = 0; i < request.outputBuffers.size(); i++) {
346     buffer_cache_.update(request.outputBuffers[i]);
347     buffer_ids.emplace_back(request.outputBuffers[i].bufferId);
348   }
349   std::lock_guard<std::mutex> lock(settings_mutex_);
350   ReadVsockRequest request_to_process = {
351       .buffer_ids = buffer_ids,
352       .frame_number = request.frameNumber,
353       .timestamp = 0,
354       .settings = latest_request_settings_,
355       .buffer_count = static_cast<uint32_t>(buffer_ids.size())};
356   putRequestToQueue(request_to_process);
357   return Status::OK;
358 }
359 
getRequestSettingsFmq(uint64_t size,V3_2::CameraMetadata & hidl_settings)360 bool VsockCameraDeviceSession::getRequestSettingsFmq(
361     uint64_t size, V3_2::CameraMetadata& hidl_settings) {
362   hidl_settings.resize(size);
363   return request_queue_->read(hidl_settings.data(), size);
364 }
365 
getRequestFromQueue(ReadVsockRequest & req,unsigned int timeout_ms)366 bool VsockCameraDeviceSession::getRequestFromQueue(ReadVsockRequest& req,
367                                                    unsigned int timeout_ms) {
368   auto timeout = std::chrono::milliseconds(timeout_ms);
369   std::unique_lock<std::mutex> lock(request_mutex_);
370   auto not_empty = [this] { return !pending_requests_.empty(); };
371   if (request_available_.wait_for(lock, timeout, not_empty)) {
372     req = pending_requests_.top();
373     pending_requests_.pop();
374     return true;
375   }
376   queue_empty_.notify_one();
377   return false;
378 }
379 
putRequestToQueue(const ReadVsockRequest & request)380 void VsockCameraDeviceSession::putRequestToQueue(
381     const ReadVsockRequest& request) {
382   std::lock_guard<std::mutex> lock(request_mutex_);
383   pending_requests_.push(request);
384   request_available_.notify_one();
385 }
386 
fillCaptureResult(common::V1_0::helper::CameraMetadata & md,nsecs_t timestamp)387 void VsockCameraDeviceSession::fillCaptureResult(
388     common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp) {
389   const uint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;
390   md.update(ANDROID_CONTROL_AF_STATE, &af_state, 1);
391 
392   const uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
393   md.update(ANDROID_CONTROL_AE_STATE, &aeState, 1);
394 
395   const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
396   md.update(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
397 
398   const uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED;
399   md.update(ANDROID_CONTROL_AWB_STATE, &awbState, 1);
400 
401   const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
402   md.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
403 
404   const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
405   md.update(ANDROID_FLASH_STATE, &flashState, 1);
406 
407   const uint8_t requestPipelineMaxDepth = 4;
408   md.update(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
409 
410   camera_metadata_entry active_array_size =
411       camera_characteristics_.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
412   md.update(ANDROID_SCALER_CROP_REGION, active_array_size.data.i32, 4);
413 
414   md.update(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
415 
416   const uint8_t lensShadingMapMode =
417       ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
418   md.update(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lensShadingMapMode, 1);
419 
420   const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
421   md.update(ANDROID_STATISTICS_SCENE_FLICKER, &sceneFlicker, 1);
422 }
423 
424 using ::android::hardware::camera::device::V3_2::MsgType;
425 using ::android::hardware::camera::device::V3_2::NotifyMsg;
notifyShutter(uint32_t frame_number,nsecs_t timestamp)426 void VsockCameraDeviceSession::notifyShutter(uint32_t frame_number,
427                                              nsecs_t timestamp) {
428   NotifyMsg msg;
429   msg.type = MsgType::SHUTTER;
430   msg.msg.shutter.frameNumber = frame_number;
431   msg.msg.shutter.timestamp = timestamp;
432   callback_->notify({msg});
433 }
434 
notifyError(uint32_t frame_number,int32_t stream_id,ErrorCode code)435 void VsockCameraDeviceSession::notifyError(uint32_t frame_number,
436                                            int32_t stream_id, ErrorCode code) {
437   NotifyMsg msg;
438   msg.type = MsgType::ERROR;
439   msg.msg.error.frameNumber = frame_number;
440   msg.msg.error.errorStreamId = stream_id;
441   msg.msg.error.errorCode = code;
442   callback_->notify({msg});
443 }
444 
tryWriteFmqResult(V3_2::CaptureResult & result)445 void VsockCameraDeviceSession::tryWriteFmqResult(V3_2::CaptureResult& result) {
446   result.fmqResultSize = 0;
447   if (result_queue_->availableToWrite() == 0 || result.result.size() == 0) {
448     return;
449   }
450   if (result_queue_->write(result.result.data(), result.result.size())) {
451     result.fmqResultSize = result.result.size();
452     result.result.resize(0);
453   }
454 }
455 
456 using ::android::hardware::camera::device::V3_2::BufferStatus;
457 using ::android::hardware::graphics::common::V1_0::PixelFormat;
processRequestLoop(unsigned int wait_timeout_ms)458 void VsockCameraDeviceSession::processRequestLoop(
459     unsigned int wait_timeout_ms) {
460   while (process_requests_.load()) {
461     ReadVsockRequest request;
462     if (!getRequestFromQueue(request, wait_timeout_ms)) {
463       continue;
464     }
465     if (!frame_provider_->isRunning()) {
466       notifyError(request.frame_number, -1, ErrorCode::ERROR_DEVICE);
467       break;
468     }
469     frame_provider_->waitYUVFrame(wait_timeout_ms);
470     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
471     if (request.timestamp == 0) {
472       request.timestamp = now;
473       notifyShutter(request.frame_number, request.timestamp);
474     }
475     std::vector<ReleaseFence> release_fences;
476     std::vector<StreamBuffer> result_buffers;
477     std::vector<uint64_t> pending_buffers;
478     bool request_ok = true;
479     for (auto buffer_id : request.buffer_ids) {
480       auto buffer = buffer_cache_.get(buffer_id);
481       auto stream_id = buffer ? buffer->streamId() : -1;
482       if (!buffer || stream_cache_.count(stream_id) == 0) {
483         ALOGE("%s: Invalid buffer", __FUNCTION__);
484         notifyError(request.frame_number, -1, ErrorCode::ERROR_REQUEST);
485         request_ok = false;
486         break;
487       }
488       bool has_result = false;
489       auto stream = stream_cache_[stream_id];
490       if (flushing_requests_.load()) {
491         has_result = false;
492         release_fences.emplace_back(buffer->acquireFence());
493       } else if (stream.format == PixelFormat::YCBCR_420_888 ||
494                  stream.format == PixelFormat::IMPLEMENTATION_DEFINED) {
495         auto dst_yuv =
496             buffer->acquireAsYUV(stream.width, stream.height, wait_timeout_ms);
497         has_result =
498             frame_provider_->copyYUVFrame(stream.width, stream.height, dst_yuv);
499         release_fences.emplace_back(buffer->release());
500       } else if (stream.format == PixelFormat::BLOB) {
501         auto time_elapsed = now - request.timestamp;
502         if (time_elapsed == 0) {
503           frame_provider_->requestJpeg();
504           pending_buffers.push_back(buffer_id);
505           continue;
506         } else if (frame_provider_->jpegPending()) {
507           static constexpr auto kMaxWaitNs = 2000000000L;
508           if (time_elapsed < kMaxWaitNs) {
509             pending_buffers.push_back(buffer_id);
510             continue;
511           }
512           ALOGE("%s: Blob request timed out after %" PRId64 "ms", __FUNCTION__,
513                 ns2ms(time_elapsed));
514           frame_provider_->cancelJpegRequest();
515           has_result = false;
516           release_fences.emplace_back(buffer->acquireFence());
517           notifyError(request.frame_number, buffer->streamId(),
518                       ErrorCode::ERROR_BUFFER);
519         } else {
520           ALOGI("%s: Blob ready - capture duration=%" PRId64 "ms", __FUNCTION__,
521                 ns2ms(time_elapsed));
522           auto dst_blob =
523               buffer->acquireAsBlob(max_blob_size_, wait_timeout_ms);
524           has_result = frame_provider_->copyJpegData(max_blob_size_, dst_blob);
525           release_fences.emplace_back(buffer->release());
526         }
527       } else {
528         ALOGE("%s: Format %d not supported", __FUNCTION__, stream.format);
529         has_result = false;
530         release_fences.emplace_back(buffer->acquireFence());
531         notifyError(request.frame_number, buffer->streamId(),
532                     ErrorCode::ERROR_BUFFER);
533       }
534       result_buffers.push_back(
535           {.streamId = buffer->streamId(),
536            .bufferId = buffer->bufferId(),
537            .buffer = nullptr,
538            .status = has_result ? BufferStatus::OK : BufferStatus::ERROR,
539            .releaseFence = release_fences.back().handle()});
540     }
541     if (!request_ok) {
542       continue;
543     }
544 
545     V3_2::CaptureResult result;
546     bool results_filled = request.settings.exists(ANDROID_SENSOR_TIMESTAMP);
547     if (!results_filled) {
548       fillCaptureResult(request.settings, request.timestamp);
549       const camera_metadata_t* metadata = request.settings.getAndLock();
550       V3_2::implementation::convertToHidl(metadata, &result.result);
551       request.settings.unlock(metadata);
552       tryWriteFmqResult(result);
553     }
554     if (!result_buffers.empty() || !results_filled) {
555       result.frameNumber = request.frame_number;
556       result.partialResult = !results_filled ? 1 : 0;
557       result.inputBuffer.streamId = -1;
558       result.outputBuffers = result_buffers;
559       std::vector<V3_2::CaptureResult> results{result};
560       auto status = callback_->processCaptureResult(results);
561       release_fences.clear();
562       if (!status.isOk()) {
563         ALOGE("%s: processCaptureResult error: %s", __FUNCTION__,
564               status.description().c_str());
565       }
566     }
567     if (!pending_buffers.empty()) {
568       // some buffers still pending
569       request.buffer_ids = pending_buffers;
570       putRequestToQueue(request);
571     }
572   }
573 }
574 
575 }  // namespace android::hardware::camera::device::V3_4::implementation
576