1 /*
2  * Copyright (C) 2019 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 LOG_NDEBUG 0
18 #define LOG_TAG "GCH_RgbirdCaptureSession"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <cutils/properties.h>
21 #include <log/log.h>
22 #include <utils/Trace.h>
23 
24 #include <inttypes.h>
25 #include <set>
26 
27 #include "basic_result_processor.h"
28 #include "depth_process_block.h"
29 #include "hal_utils.h"
30 #include "hdrplus_process_block.h"
31 #include "hdrplus_request_processor.h"
32 #include "hdrplus_result_processor.h"
33 #include "multicam_realtime_process_block.h"
34 #include "rgbird_capture_session.h"
35 #include "rgbird_depth_result_processor.h"
36 #include "rgbird_result_request_processor.h"
37 #include "rgbird_rt_request_processor.h"
38 
39 namespace android {
40 namespace google_camera_hal {
41 
IsStreamConfigurationSupported(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration &)42 bool RgbirdCaptureSession::IsStreamConfigurationSupported(
43     CameraDeviceSessionHwl* device_session_hwl,
44     const StreamConfiguration& /*stream_config*/) {
45   ATRACE_CALL();
46   if (device_session_hwl == nullptr) {
47     ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
48     return false;
49   }
50 
51   std::vector<uint32_t> physical_camera_ids =
52       device_session_hwl->GetPhysicalCameraIds();
53   if (physical_camera_ids.size() != 3) {
54     ALOGD("%s: RgbirdCaptureSession doesn't support %zu physical cameras",
55           __FUNCTION__, physical_camera_ids.size());
56     return false;
57   }
58 
59   // Check if this is a logical camera containing two IR cameras.
60   uint32_t num_ir_camera = 0;
61   for (auto id : physical_camera_ids) {
62     std::unique_ptr<HalCameraMetadata> characteristics;
63     status_t res = device_session_hwl->GetPhysicalCameraCharacteristics(
64         id, &characteristics);
65 
66     if (res != OK) {
67       ALOGE("%s: Cannot get physical camera characteristics for camera %u",
68             __FUNCTION__, id);
69       return false;
70     }
71 
72     // TODO(b/129088371): Work around b/129088371 because current IR camera's
73     // CFA is MONO instead of NIR.
74     if (hal_utils::IsIrCamera(characteristics.get()) ||
75         hal_utils::IsMonoCamera(characteristics.get())) {
76       num_ir_camera++;
77     }
78   }
79 
80   if (num_ir_camera != 2) {
81     ALOGD("%s: RgbirdCaptureSession only supports 2 ir cameras", __FUNCTION__);
82     return false;
83   }
84 
85   ALOGD("%s: RgbirdCaptureSession supports the stream config", __FUNCTION__);
86   return true;
87 }
88 
Create(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,HwlSessionCallback session_callback,std::vector<HalStream> * hal_configured_streams,CameraBufferAllocatorHwl *)89 std::unique_ptr<CaptureSession> RgbirdCaptureSession::Create(
90     CameraDeviceSessionHwl* device_session_hwl,
91     const StreamConfiguration& stream_config,
92     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
93     HwlSessionCallback session_callback,
94     std::vector<HalStream>* hal_configured_streams,
95     CameraBufferAllocatorHwl* /*camera_allocator_hwl*/) {
96   ATRACE_CALL();
97   auto session =
98       std::unique_ptr<RgbirdCaptureSession>(new RgbirdCaptureSession());
99   if (session == nullptr) {
100     ALOGE("%s: Creating RgbirdCaptureSession failed.", __FUNCTION__);
101     return nullptr;
102   }
103 
104   status_t res = session->Initialize(
105       device_session_hwl, stream_config, process_capture_result, notify,
106       session_callback.request_stream_buffers, hal_configured_streams);
107   if (res != OK) {
108     ALOGE("%s: Initializing RgbirdCaptureSession failed: %s (%d).",
109           __FUNCTION__, strerror(-res), res);
110     return nullptr;
111   }
112 
113   return session;
114 }
115 
~RgbirdCaptureSession()116 RgbirdCaptureSession::~RgbirdCaptureSession() {
117   if (device_session_hwl_ != nullptr) {
118     device_session_hwl_->DestroyPipelines();
119   }
120 
121   rt_request_processor_ = nullptr;
122   hdrplus_request_processor_ = nullptr;
123   result_dispatcher_ = nullptr;
124 }
125 
AreAllStreamsConfigured(const StreamConfiguration & stream_config,const StreamConfiguration & process_block_stream_config) const126 bool RgbirdCaptureSession::AreAllStreamsConfigured(
127     const StreamConfiguration& stream_config,
128     const StreamConfiguration& process_block_stream_config) const {
129   ATRACE_CALL();
130   // Check all streams are configured.
131   if (stream_config.streams.size() > process_block_stream_config.streams.size()) {
132     ALOGE("%s: stream_config has %zu streams but only configured %zu streams",
133           __FUNCTION__, stream_config.streams.size(),
134           process_block_stream_config.streams.size());
135     return false;
136   }
137 
138   for (auto& stream : stream_config.streams) {
139     bool found = false;
140     for (auto& configured_stream : process_block_stream_config.streams) {
141       if (stream.id == configured_stream.id) {
142         found = true;
143         break;
144       }
145     }
146 
147     if (!found) {
148       ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__,
149             stream.id);
150       return false;
151     }
152   }
153 
154   return true;
155 }
156 
ConfigureStreams(const StreamConfiguration & stream_config,RequestProcessor * request_processor,ProcessBlock * process_block,StreamConfiguration * process_block_stream_config)157 status_t RgbirdCaptureSession::ConfigureStreams(
158     const StreamConfiguration& stream_config,
159     RequestProcessor* request_processor, ProcessBlock* process_block,
160     StreamConfiguration* process_block_stream_config) {
161   ATRACE_CALL();
162   if (request_processor == nullptr || process_block == nullptr ||
163       process_block_stream_config == nullptr) {
164     ALOGE(
165         "%s: request_processor(%p) or process_block(%p) or "
166         "process_block_stream_config(%p) is nullptr",
167         __FUNCTION__, request_processor, process_block,
168         process_block_stream_config);
169     return BAD_VALUE;
170   }
171 
172   status_t res = request_processor->ConfigureStreams(
173       internal_stream_manager_.get(), stream_config,
174       process_block_stream_config);
175   if (res != OK) {
176     ALOGE("%s: Configuring stream for RequestProcessor failed: %s(%d)",
177           __FUNCTION__, strerror(-res), res);
178     return res;
179   }
180 
181   res = process_block->ConfigureStreams(*process_block_stream_config,
182                                         stream_config);
183   if (res != OK) {
184     ALOGE("%s: Configuring streams for ProcessBlock failed: %s(%d)",
185           __FUNCTION__, strerror(-res), res);
186     return res;
187   }
188 
189   return OK;
190 }
191 
SetDepthInternalStreamId(const StreamConfiguration & process_block_stream_config,const StreamConfiguration & stream_config)192 status_t RgbirdCaptureSession::SetDepthInternalStreamId(
193     const StreamConfiguration& process_block_stream_config,
194     const StreamConfiguration& stream_config) {
195   // Assuming there is at most one internal YUV stream configured when this
196   // function is called(i.e. when depth stream is configured).
197   for (auto& configured_stream : process_block_stream_config.streams) {
198     if (configured_stream.format == HAL_PIXEL_FORMAT_YCBCR_420_888) {
199       bool matching_found = false;
200       for (auto& framework_stream : stream_config.streams) {
201         if (configured_stream.id == framework_stream.id) {
202           matching_found = true;
203           break;
204         }
205       }
206       if (!matching_found) {
207         rgb_internal_yuv_stream_id_ = configured_stream.id;
208       }
209     } else if (configured_stream.format == HAL_PIXEL_FORMAT_Y8) {
210       if (configured_stream.physical_camera_id == ir1_camera_id_) {
211         ir1_internal_raw_stream_id_ = configured_stream.id;
212       } else if (configured_stream.physical_camera_id == ir2_camera_id_) {
213         ir2_internal_raw_stream_id_ = configured_stream.id;
214       } else {
215         ALOGV("%s: Y8 stream found from non-IR sensors.", __FUNCTION__);
216       }
217     }
218   }
219 
220   if (rgb_internal_yuv_stream_id_ == kInvalidStreamId ||
221       ir1_internal_raw_stream_id_ == kInvalidStreamId ||
222       ir2_internal_raw_stream_id_ == kInvalidStreamId) {
223     ALOGE(
224         "%s: Internal YUV or IR stream not found in "
225         "process_block_stream_config.",
226         __FUNCTION__);
227     return UNKNOWN_ERROR;
228   }
229 
230   return OK;
231 }
232 
ConfigureHdrplusRawStreamId(const StreamConfiguration & process_block_stream_config)233 status_t RgbirdCaptureSession::ConfigureHdrplusRawStreamId(
234     const StreamConfiguration& process_block_stream_config) {
235   ATRACE_CALL();
236   std::unique_ptr<HalCameraMetadata> characteristics;
237   status_t res = device_session_hwl_->GetCameraCharacteristics(&characteristics);
238   if (res != OK) {
239     ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
240     return BAD_VALUE;
241   }
242 
243   uint32_t active_array_width, active_array_height;
244   camera_metadata_ro_entry entry;
245   res = characteristics->Get(
246       ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &entry);
247   if (res == OK) {
248     active_array_width = entry.data.i32[2];
249     active_array_height = entry.data.i32[3];
250     ALOGI("%s Active size (%d x %d).", __FUNCTION__, active_array_width,
251           active_array_height);
252   } else {
253     ALOGE("%s Get active size failed: %s (%d).", __FUNCTION__, strerror(-res),
254           res);
255     return UNKNOWN_ERROR;
256   }
257 
258   for (auto& configured_stream : process_block_stream_config.streams) {
259     if (configured_stream.format == kHdrplusRawFormat &&
260         configured_stream.width == active_array_width &&
261         configured_stream.height == active_array_height) {
262       rgb_raw_stream_id_ = configured_stream.id;
263       break;
264     }
265   }
266 
267   if (rgb_raw_stream_id_ == -1) {
268     ALOGE("%s: Configuring stream fail due to wrong raw_stream_id",
269           __FUNCTION__);
270     return UNKNOWN_ERROR;
271   }
272 
273   return OK;
274 }
275 
AllocateInternalBuffers(const StreamConfiguration & framework_stream_config,std::vector<HalStream> * hal_configured_streams,ProcessBlock * hdrplus_process_block)276 status_t RgbirdCaptureSession::AllocateInternalBuffers(
277     const StreamConfiguration& framework_stream_config,
278     std::vector<HalStream>* hal_configured_streams,
279     ProcessBlock* hdrplus_process_block) {
280   ATRACE_CALL();
281   status_t res = OK;
282 
283   std::set<int32_t> framework_stream_id_set;
284   for (auto& stream : framework_stream_config.streams) {
285     framework_stream_id_set.insert(stream.id);
286   }
287 
288   for (uint32_t i = 0; i < hal_configured_streams->size(); i++) {
289     HalStream& hal_stream = hal_configured_streams->at(i);
290 
291     if (framework_stream_id_set.find(hal_stream.id) ==
292         framework_stream_id_set.end()) {
293       // hdrplus rgb raw stream buffers is allocated separately
294       if (hal_stream.id == rgb_raw_stream_id_) {
295         continue;
296       }
297 
298       uint32_t additional_num_buffers =
299           (hal_stream.max_buffers >= kDefaultInternalBufferCount)
300               ? 0
301               : (kDefaultInternalBufferCount - hal_stream.max_buffers);
302       res = internal_stream_manager_->AllocateBuffers(
303           hal_stream, hal_stream.max_buffers + additional_num_buffers);
304       if (res != OK) {
305         ALOGE("%s: Failed to allocate buffer for internal stream %d: %s(%d)",
306               __FUNCTION__, hal_stream.id, strerror(-res), res);
307         return res;
308       } else {
309         ALOGI("%s: Allocating %d internal buffers for stream %d", __FUNCTION__,
310               additional_num_buffers + hal_stream.max_buffers, hal_stream.id);
311       }
312     }
313   }
314 
315   if (is_hdrplus_supported_) {
316     std::vector<HalStream> hdrplus_hal_configured_streams;
317     res = hdrplus_process_block->GetConfiguredHalStreams(
318         &hdrplus_hal_configured_streams);
319     if (res != OK) {
320       ALOGE("%s: Getting HDR+ HAL streams failed: %s(%d)", __FUNCTION__,
321             strerror(-res), res);
322       return res;
323     }
324 
325     res = ConfigureHdrplusUsageAndBuffers(hal_configured_streams,
326                                           &hdrplus_hal_configured_streams);
327     if (res != OK) {
328       ALOGE("%s: ConfigureHdrplusUsageAndBuffer failed: %s(%d)", __FUNCTION__,
329             strerror(-res), res);
330       return res;
331     }
332   }
333   return res;
334 }
335 
PurgeHalConfiguredStream(const StreamConfiguration & stream_config,std::vector<HalStream> * hal_configured_streams)336 status_t RgbirdCaptureSession::PurgeHalConfiguredStream(
337     const StreamConfiguration& stream_config,
338     std::vector<HalStream>* hal_configured_streams) {
339   if (hal_configured_streams == nullptr) {
340     ALOGE("%s: HAL configured stream list is null.", __FUNCTION__);
341     return BAD_VALUE;
342   }
343 
344   std::set<int32_t> framework_stream_id_set;
345   for (auto& stream : stream_config.streams) {
346     framework_stream_id_set.insert(stream.id);
347   }
348 
349   std::vector<HalStream> configured_streams;
350   for (auto& hal_stream : *hal_configured_streams) {
351     if (framework_stream_id_set.find(hal_stream.id) !=
352         framework_stream_id_set.end()) {
353       configured_streams.push_back(hal_stream);
354     }
355   }
356   *hal_configured_streams = configured_streams;
357   return OK;
358 }
359 
NeedDepthProcessBlock() const360 bool RgbirdCaptureSession::NeedDepthProcessBlock() const {
361   // TODO(b/128633958): remove force flag after FLL syncing is verified
362   return force_internal_stream_ || has_depth_stream_;
363 }
364 
CreateDepthChainSegment(std::unique_ptr<DepthProcessBlock> * depth_process_block,std::unique_ptr<RgbirdDepthResultProcessor> * depth_result_processor,RgbirdResultRequestProcessor * rt_result_processor,const StreamConfiguration & stream_config,const StreamConfiguration & overall_config,StreamConfiguration * depth_block_stream_config)365 status_t RgbirdCaptureSession::CreateDepthChainSegment(
366     std::unique_ptr<DepthProcessBlock>* depth_process_block,
367     std::unique_ptr<RgbirdDepthResultProcessor>* depth_result_processor,
368     RgbirdResultRequestProcessor* rt_result_processor,
369     const StreamConfiguration& stream_config,
370     const StreamConfiguration& overall_config,
371     StreamConfiguration* depth_block_stream_config) {
372   ATRACE_CALL();
373   DepthProcessBlock::DepthProcessBlockCreateData data = {
374       .rgb_internal_yuv_stream_id = rgb_internal_yuv_stream_id_,
375       .ir1_internal_raw_stream_id = ir1_internal_raw_stream_id_,
376       .ir2_internal_raw_stream_id = ir2_internal_raw_stream_id_};
377   auto process_block = DepthProcessBlock::Create(device_session_hwl_,
378                                                  request_stream_buffers_, data);
379   if (process_block == nullptr) {
380     ALOGE("%s: Creating DepthProcessBlock failed.", __FUNCTION__);
381     return UNKNOWN_ERROR;
382   }
383 
384   auto result_processor =
385       RgbirdDepthResultProcessor::Create(internal_stream_manager_.get());
386   if (result_processor == nullptr) {
387     ALOGE("%s: Creating RgbirdDepthResultProcessor", __FUNCTION__);
388     return UNKNOWN_ERROR;
389   }
390 
391   status_t res = rt_result_processor->ConfigureStreams(
392       internal_stream_manager_.get(), stream_config, depth_block_stream_config);
393   if (res != OK) {
394     ALOGE("%s: Configuring streams for ResultRequestProcessor failed: %s(%d)",
395           __FUNCTION__, strerror(-res), res);
396     return res;
397   }
398 
399   res = process_block->ConfigureStreams(*depth_block_stream_config,
400                                         overall_config);
401   if (res != OK) {
402     ALOGE("%s: Configuring streams for DepthProcessBlock failed: %s(%d)",
403           __FUNCTION__, strerror(-res), res);
404     return res;
405   }
406 
407   *depth_process_block = std::move(process_block);
408   *depth_result_processor = std::move(result_processor);
409 
410   return OK;
411 }
412 
SetupDepthChainSegment(const StreamConfiguration & stream_config,RgbirdResultRequestProcessor * realtime_result_processor,std::unique_ptr<ProcessBlock> * depth_process_block,std::unique_ptr<ResultProcessor> * depth_result_processor,StreamConfiguration * rt_process_block_stream_config)413 status_t RgbirdCaptureSession::SetupDepthChainSegment(
414     const StreamConfiguration& stream_config,
415     RgbirdResultRequestProcessor* realtime_result_processor,
416     std::unique_ptr<ProcessBlock>* depth_process_block,
417     std::unique_ptr<ResultProcessor>* depth_result_processor,
418     StreamConfiguration* rt_process_block_stream_config) {
419   ATRACE_CALL();
420   // Create the depth segment of realtime process chain if need depth processing
421   std::unique_ptr<DepthProcessBlock> d_process_block;
422   std::unique_ptr<RgbirdDepthResultProcessor> d_result_processor;
423   if (NeedDepthProcessBlock()) {
424     StreamConfiguration depth_chain_segment_stream_config;
425     status_t res =
426         MakeDepthStreamConfig(*rt_process_block_stream_config, stream_config,
427                               &depth_chain_segment_stream_config);
428     if (res != OK) {
429       ALOGE(
430           "%s: Making depth chain segment stream configuration failed: "
431           "%s(%d).",
432           __FUNCTION__, strerror(-res), res);
433       return res;
434     }
435 
436     StreamConfiguration depth_block_stream_config;
437     res = CreateDepthChainSegment(&d_process_block, &d_result_processor,
438                                   realtime_result_processor,
439                                   depth_chain_segment_stream_config,
440                                   stream_config, &depth_block_stream_config);
441     if (res != OK) {
442       ALOGE("%s: Creating depth chain segment failed: %s(%d).", __FUNCTION__,
443             strerror(-res), res);
444       return res;
445     }
446 
447     // process_block_stream_config may contain internal streams(some may be
448     // duplicated as both input and output for bridging the rt and depth
449     // segments of the realtime process chain.)
450     rt_process_block_stream_config->streams.insert(
451         rt_process_block_stream_config->streams.end(),
452         depth_block_stream_config.streams.begin(),
453         depth_block_stream_config.streams.end());
454 
455     *depth_process_block = std::move(d_process_block);
456     *depth_result_processor = std::move(d_result_processor);
457   }
458 
459   return OK;
460 }
461 
MakeDepthStreamConfig(const StreamConfiguration & rt_process_block_stream_config,const StreamConfiguration & stream_config,StreamConfiguration * depth_stream_config)462 status_t RgbirdCaptureSession::MakeDepthStreamConfig(
463     const StreamConfiguration& rt_process_block_stream_config,
464     const StreamConfiguration& stream_config,
465     StreamConfiguration* depth_stream_config) {
466   ATRACE_CALL();
467   if (depth_stream_config == nullptr) {
468     ALOGE("%s: depth_stream_config is nullptr", __FUNCTION__);
469     return BAD_VALUE;
470   }
471 
472   if (!NeedDepthProcessBlock()) {
473     ALOGE("%s: No need to create depth process chain segment stream config.",
474           __FUNCTION__);
475     return BAD_VALUE;
476   }
477 
478   // Assuming all internal streams must be for depth process block as input,
479   // if depth stream is configured by framework.
480   depth_stream_config->operation_mode = stream_config.operation_mode;
481   depth_stream_config->session_params =
482       HalCameraMetadata::Clone(stream_config.session_params.get());
483   depth_stream_config->stream_config_counter =
484       stream_config.stream_config_counter;
485   depth_stream_config->streams = stream_config.streams;
486   for (auto& stream : rt_process_block_stream_config.streams) {
487     bool is_internal_stream = true;
488     for (auto& framework_stream : stream_config.streams) {
489       if (stream.id == framework_stream.id) {
490         is_internal_stream = false;
491         break;
492       }
493     }
494 
495     // Change all internal streams to input streams and keep others untouched
496     if (is_internal_stream) {
497       Stream input_stream = stream;
498       input_stream.stream_type = StreamType::kInput;
499       depth_stream_config->streams.push_back(input_stream);
500     }
501   }
502 
503   return OK;
504 }
505 
SetupRealtimeProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::unique_ptr<ProcessBlock> * realtime_process_block,std::unique_ptr<RgbirdResultRequestProcessor> * realtime_result_processor,std::unique_ptr<ProcessBlock> * depth_process_block,std::unique_ptr<ResultProcessor> * depth_result_processor)506 status_t RgbirdCaptureSession::SetupRealtimeProcessChain(
507     const StreamConfiguration& stream_config,
508     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
509     std::unique_ptr<ProcessBlock>* realtime_process_block,
510     std::unique_ptr<RgbirdResultRequestProcessor>* realtime_result_processor,
511     std::unique_ptr<ProcessBlock>* depth_process_block,
512     std::unique_ptr<ResultProcessor>* depth_result_processor) {
513   ATRACE_CALL();
514   if (realtime_process_block == nullptr ||
515       realtime_result_processor == nullptr) {
516     ALOGE("%s: realtime_process_block(%p) or realtime_result_processor(%p) or ",
517           __FUNCTION__, realtime_process_block, realtime_result_processor);
518     return BAD_VALUE;
519   }
520 
521   auto rt_process_block = MultiCameraRtProcessBlock::Create(device_session_hwl_);
522   if (rt_process_block == nullptr) {
523     ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__);
524     return UNKNOWN_ERROR;
525   }
526 
527   // TODO(b/128632740): Create and connect depth process block.
528   rt_request_processor_ = RgbirdRtRequestProcessor::Create(
529       device_session_hwl_, is_hdrplus_supported_);
530   if (rt_request_processor_ == nullptr) {
531     ALOGE("%s: Creating RealtimeZslsRequestProcessor failed.", __FUNCTION__);
532     return UNKNOWN_ERROR;
533   }
534 
535   StreamConfiguration process_block_stream_config;
536   status_t res =
537       ConfigureStreams(stream_config, rt_request_processor_.get(),
538                        rt_process_block.get(), &process_block_stream_config);
539   if (res != OK) {
540     ALOGE("%s: Configuring stream failed: %s(%d)", __FUNCTION__, strerror(-res),
541           res);
542     return res;
543   }
544 
545   if (is_hdrplus_supported_) {
546     res = ConfigureHdrplusRawStreamId(process_block_stream_config);
547     if (res != OK) {
548       ALOGE("%s: ConfigureHdrplusRawStreamId failed: %s(%d)", __FUNCTION__,
549             strerror(-res), res);
550       return res;
551     }
552   }
553 
554   if (has_depth_stream_) {
555     res = SetDepthInternalStreamId(process_block_stream_config, stream_config);
556     if (res != OK) {
557       ALOGE("%s: ConfigureDepthOnlyRawStreamId failed: %s(%d)", __FUNCTION__,
558             strerror(-res), res);
559       return res;
560     }
561   }
562 
563   // Create realtime result processor.
564   RgbirdResultRequestProcessor::RgbirdResultRequestProcessorCreateData data = {
565       .rgb_camera_id = rgb_camera_id_,
566       .ir1_camera_id = ir1_camera_id_,
567       .ir2_camera_id = ir2_camera_id_,
568       .rgb_raw_stream_id = rgb_raw_stream_id_,
569       .is_hdrplus_supported = is_hdrplus_supported_,
570       .rgb_internal_yuv_stream_id = rgb_internal_yuv_stream_id_};
571   auto rt_result_processor = RgbirdResultRequestProcessor::Create(data);
572   if (rt_result_processor == nullptr) {
573     ALOGE("%s: Creating RgbirdResultRequestProcessor failed.", __FUNCTION__);
574     return UNKNOWN_ERROR;
575   }
576   rt_result_processor->SetResultCallback(process_capture_result, notify);
577 
578   if (is_hdrplus_supported_) {
579     res = rt_result_processor->ConfigureStreams(internal_stream_manager_.get(),
580                                                 stream_config,
581                                                 &process_block_stream_config);
582     if (res != OK) {
583       ALOGE("%s: Configuring streams for ResultRequestProcessor failed: %s(%d)",
584             __FUNCTION__, strerror(-res), res);
585       return res;
586     }
587   }
588 
589   res = SetupDepthChainSegment(stream_config, rt_result_processor.get(),
590                                depth_process_block, depth_result_processor,
591                                &process_block_stream_config);
592   if (res != OK) {
593     ALOGE("%s: Failed to setup depth chain segment.", __FUNCTION__);
594     return UNKNOWN_ERROR;
595   }
596 
597   // TODO(b/128632740): Remove force internal flag after depth block is in place
598   //                    and the FLL sync is verified.
599   //                    This should be done after depth process block stream
600   //                    configuration.
601   if (!AreAllStreamsConfigured(stream_config, process_block_stream_config) &&
602       !force_internal_stream_) {
603     // TODO(b/127322570): Handle the case where RT request processor configures
604     // internal streams for depth.
605     ALOGE("%s: Not all streams are configured.", __FUNCTION__);
606     return INVALID_OPERATION;
607   }
608 
609   *realtime_process_block = std::move(rt_process_block);
610   *realtime_result_processor = std::move(rt_result_processor);
611 
612   return OK;
613 }
614 
SetupHdrplusProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::unique_ptr<ProcessBlock> * hdrplus_process_block,std::unique_ptr<ResultProcessor> * hdrplus_result_processor)615 status_t RgbirdCaptureSession::SetupHdrplusProcessChain(
616     const StreamConfiguration& stream_config,
617     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
618     std::unique_ptr<ProcessBlock>* hdrplus_process_block,
619     std::unique_ptr<ResultProcessor>* hdrplus_result_processor) {
620   ATRACE_CALL();
621   if (hdrplus_process_block == nullptr || hdrplus_result_processor == nullptr) {
622     ALOGE(
623         "%s: hdrplus_process_block(%p) or hdrplus_result_processor(%p) is "
624         "nullptr",
625         __FUNCTION__, hdrplus_process_block, hdrplus_result_processor);
626     return BAD_VALUE;
627   }
628 
629   // Create hdrplus process block.
630   std::vector<uint32_t> physical_camera_ids =
631       device_session_hwl_->GetPhysicalCameraIds();
632   // TODO: Check the static metadata and determine which one is rgb camera
633   auto process_block =
634       HdrplusProcessBlock::Create(device_session_hwl_, physical_camera_ids[0]);
635   if (process_block == nullptr) {
636     ALOGE("%s: Creating HdrplusProcessBlock failed.", __FUNCTION__);
637     return UNKNOWN_ERROR;
638   }
639 
640   // Create hdrplus request processor.
641   hdrplus_request_processor_ = HdrplusRequestProcessor::Create(
642       device_session_hwl_, rgb_raw_stream_id_, physical_camera_ids[0]);
643   if (hdrplus_request_processor_ == nullptr) {
644     ALOGE("%s: Creating HdrplusRequestProcessor failed.", __FUNCTION__);
645     return UNKNOWN_ERROR;
646   }
647 
648   // Create hdrplus result processor.
649   auto result_processor = HdrplusResultProcessor::Create(
650       internal_stream_manager_.get(), rgb_raw_stream_id_);
651   if (result_processor == nullptr) {
652     ALOGE("%s: Creating HdrplusResultProcessor failed.", __FUNCTION__);
653     return UNKNOWN_ERROR;
654   }
655   result_processor->SetResultCallback(process_capture_result, notify);
656 
657   StreamConfiguration process_block_stream_config;
658   status_t res =
659       ConfigureStreams(stream_config, hdrplus_request_processor_.get(),
660                        process_block.get(), &process_block_stream_config);
661   if (res != OK) {
662     ALOGE("%s: Configuring hdrplus stream failed: %s(%d)", __FUNCTION__,
663           strerror(-res), res);
664     return res;
665   }
666 
667   *hdrplus_process_block = std::move(process_block);
668   *hdrplus_result_processor = std::move(result_processor);
669 
670   return OK;
671 }
672 
CreateProcessChain(const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::vector<HalStream> * hal_configured_streams)673 status_t RgbirdCaptureSession::CreateProcessChain(
674     const StreamConfiguration& stream_config,
675     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
676     std::vector<HalStream>* hal_configured_streams) {
677   ATRACE_CALL();
678   // Setup realtime process chain
679   std::unique_ptr<ProcessBlock> realtime_process_block;
680   std::unique_ptr<RgbirdResultRequestProcessor> realtime_result_processor;
681   std::unique_ptr<ProcessBlock> depth_process_block;
682   std::unique_ptr<ResultProcessor> depth_result_processor;
683 
684   status_t res = SetupRealtimeProcessChain(
685       stream_config, process_capture_result, notify, &realtime_process_block,
686       &realtime_result_processor, &depth_process_block, &depth_result_processor);
687   if (res != OK) {
688     ALOGE("%s: SetupRealtimeProcessChain fail: %s(%d)", __FUNCTION__,
689           strerror(-res), res);
690     return res;
691   }
692 
693   // Setup hdrplus process chain
694   std::unique_ptr<ProcessBlock> hdrplus_process_block;
695   std::unique_ptr<ResultProcessor> hdrplus_result_processor;
696   if (is_hdrplus_supported_) {
697     res = SetupHdrplusProcessChain(stream_config, process_capture_result,
698                                    notify, &hdrplus_process_block,
699                                    &hdrplus_result_processor);
700     if (res != OK) {
701       ALOGE("%s: SetupHdrplusProcessChain fail: %s(%d)", __FUNCTION__,
702             strerror(-res), res);
703       return res;
704     }
705   }
706   // Realtime and HDR+ streams are configured
707   // Start to build pipleline
708   res = BuildPipelines(stream_config, realtime_process_block.get(),
709                        depth_process_block.get(), hdrplus_process_block.get(),
710                        hal_configured_streams);
711   if (res != OK) {
712     ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
713           res);
714     return res;
715   }
716 
717   // Connecting the depth segment of the realtime process chain.
718   if (NeedDepthProcessBlock()) {
719     depth_result_processor->SetResultCallback(process_capture_result, notify);
720 
721     res = ConnectProcessChain(realtime_result_processor.get(),
722                               std::move(depth_process_block),
723                               std::move(depth_result_processor));
724     if (res != OK) {
725       ALOGE("%s: Connecting depth segment of realtime chain failed: %s(%d)",
726             __FUNCTION__, strerror(-res), res);
727       return res;
728     }
729   }
730 
731   // Connect realtime process chain
732   res = ConnectProcessChain(rt_request_processor_.get(),
733                             std::move(realtime_process_block),
734                             std::move(realtime_result_processor));
735   if (res != OK) {
736     ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__,
737           strerror(-res), res);
738     return res;
739   }
740 
741   if (is_hdrplus_supported_) {
742     // Connect HDR+ process chain
743     res = ConnectProcessChain(hdrplus_request_processor_.get(),
744                               std::move(hdrplus_process_block),
745                               std::move(hdrplus_result_processor));
746     if (res != OK) {
747       ALOGE("%s: Connecting HDR+ process chain failed: %s(%d)", __FUNCTION__,
748             strerror(-res), res);
749       return res;
750     }
751   }
752   return OK;
753 }
754 
ConnectProcessChain(RequestProcessor * request_processor,std::unique_ptr<ProcessBlock> process_block,std::unique_ptr<ResultProcessor> result_processor)755 status_t RgbirdCaptureSession::ConnectProcessChain(
756     RequestProcessor* request_processor,
757     std::unique_ptr<ProcessBlock> process_block,
758     std::unique_ptr<ResultProcessor> result_processor) {
759   ATRACE_CALL();
760   if (request_processor == nullptr) {
761     ALOGE("%s: request_processor is nullptr", __FUNCTION__);
762     return BAD_VALUE;
763   }
764 
765   status_t res = process_block->SetResultProcessor(std::move(result_processor));
766   if (res != OK) {
767     ALOGE("%s: Setting result process in process block failed.", __FUNCTION__);
768     return res;
769   }
770 
771   res = request_processor->SetProcessBlock(std::move(process_block));
772   if (res != OK) {
773     ALOGE("%s: Setting process block for request processor failed: %s(%d)",
774           __FUNCTION__, strerror(-res), res);
775     return res;
776   }
777 
778   return OK;
779 }
780 
ConfigureHdrplusUsageAndBuffers(std::vector<HalStream> * hal_configured_streams,std::vector<HalStream> * hdrplus_hal_configured_streams)781 status_t RgbirdCaptureSession::ConfigureHdrplusUsageAndBuffers(
782     std::vector<HalStream>* hal_configured_streams,
783     std::vector<HalStream>* hdrplus_hal_configured_streams) {
784   ATRACE_CALL();
785   if (hal_configured_streams == nullptr ||
786       hdrplus_hal_configured_streams == nullptr) {
787     ALOGE(
788         "%s: hal_configured_streams (%p) or hdrplus_hal_configured_streams "
789         "(%p) is nullptr",
790         __FUNCTION__, hal_configured_streams, hdrplus_hal_configured_streams);
791     return BAD_VALUE;
792   }
793   // Combine realtime and HDR+ hal stream.
794   // Only usage of internal raw stream is different, so combine usage directly
795   uint64_t consumer_usage = 0;
796   for (uint32_t i = 0; i < (*hdrplus_hal_configured_streams).size(); i++) {
797     if (hdrplus_hal_configured_streams->at(i).override_format ==
798             kHdrplusRawFormat &&
799         hdrplus_hal_configured_streams->at(i).id == rgb_raw_stream_id_) {
800       consumer_usage = hdrplus_hal_configured_streams->at(i).consumer_usage;
801       break;
802     }
803   }
804 
805   for (uint32_t i = 0; i < hal_configured_streams->size(); i++) {
806     if (hal_configured_streams->at(i).override_format == kHdrplusRawFormat &&
807         hal_configured_streams->at(i).id == rgb_raw_stream_id_) {
808       hal_configured_streams->at(i).consumer_usage = consumer_usage;
809       // Allocate internal raw stream buffers
810       if (hal_configured_streams->at(i).max_buffers < kRgbMinRawBufferCount) {
811         hal_configured_streams->at(i).max_buffers = kRgbMinRawBufferCount;
812       }
813 
814       uint32_t additional_num_buffers =
815           (hal_configured_streams->at(i).max_buffers >= kRgbRawBufferCount)
816               ? 0
817               : (kRgbRawBufferCount - hal_configured_streams->at(i).max_buffers);
818       status_t res = internal_stream_manager_->AllocateBuffers(
819           hal_configured_streams->at(i), additional_num_buffers);
820       if (res != OK) {
821         ALOGE("%s: AllocateBuffers failed.", __FUNCTION__);
822         return UNKNOWN_ERROR;
823       }
824       break;
825     }
826   }
827 
828   return OK;
829 }
830 
BuildPipelines(const StreamConfiguration & stream_config,ProcessBlock * realtime_process_block,ProcessBlock * depth_process_block,ProcessBlock * hdrplus_process_block,std::vector<HalStream> * hal_configured_streams)831 status_t RgbirdCaptureSession::BuildPipelines(
832     const StreamConfiguration& stream_config,
833     ProcessBlock* realtime_process_block, ProcessBlock* depth_process_block,
834     ProcessBlock* hdrplus_process_block,
835     std::vector<HalStream>* hal_configured_streams) {
836   ATRACE_CALL();
837   if (realtime_process_block == nullptr) {
838     ALOGE("%s: realtime_process_block (%p) is nullptr", __FUNCTION__,
839           realtime_process_block);
840     return BAD_VALUE;
841   }
842 
843   if (depth_process_block == nullptr && has_depth_stream_) {
844     ALOGE("%s: depth_process_block (%p) is nullptr", __FUNCTION__,
845           depth_process_block);
846     return BAD_VALUE;
847   }
848 
849   if (hal_configured_streams == nullptr) {
850     ALOGE("%s: hal_configured_streams (%p) is nullptr", __FUNCTION__,
851           hal_configured_streams);
852     return BAD_VALUE;
853   }
854 
855   if (is_hdrplus_supported_ && hdrplus_process_block == nullptr) {
856     ALOGE("%s: hdrplus_process_block is nullptr", __FUNCTION__);
857     return BAD_VALUE;
858   }
859 
860   status_t res = device_session_hwl_->BuildPipelines();
861   if (res != OK) {
862     ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
863           res);
864     return res;
865   }
866 
867   res = realtime_process_block->GetConfiguredHalStreams(hal_configured_streams);
868   if (res != OK) {
869     ALOGE("%s: Getting HAL streams failed: %s(%d)", __FUNCTION__,
870           strerror(-res), res);
871     return res;
872   }
873 
874   res = AllocateInternalBuffers(stream_config, hal_configured_streams,
875                                 hdrplus_process_block);
876 
877   // Need to update hal_configured_streams if there is a depth stream
878   std::vector<HalStream> depth_streams;
879   if (has_depth_stream_) {
880     res = depth_process_block->GetConfiguredHalStreams(&depth_streams);
881     if (res != OK) {
882       ALOGE("%s: Failed to get configured hal streams from DepthProcessBlock",
883             __FUNCTION__);
884       return UNKNOWN_ERROR;
885     }
886 
887     // Depth Process Block can only configure one depth stream so far
888     if (depth_streams.size() != 1) {
889       ALOGE("%s: DepthProcessBlock configured more than one stream.",
890             __FUNCTION__);
891       return UNKNOWN_ERROR;
892     }
893 
894     hal_configured_streams->push_back(depth_streams[0]);
895   }
896 
897   if (res != OK) {
898     ALOGE("%s: Allocating buffer for internal stream managers failed: %s(%d)",
899           __FUNCTION__, strerror(-res), res);
900     return res;
901   }
902 
903   hal_utils::DumpHalConfiguredStreams(*hal_configured_streams,
904                                       "hal_configured_streams BEFORE purge");
905 
906   // TODO(b/128633958): cover the streams Depth PB processes
907   res = PurgeHalConfiguredStream(stream_config, hal_configured_streams);
908   if (res != OK) {
909     ALOGE("%s: Removing internal streams from configured stream failed: %s(%d)",
910           __FUNCTION__, strerror(-res), res);
911     return res;
912   }
913 
914   hal_utils::DumpHalConfiguredStreams(*hal_configured_streams,
915                                       "hal_configured_streams AFTER purge");
916 
917   return OK;
918 }
919 
InitializeCameraIds(CameraDeviceSessionHwl * device_session_hwl)920 status_t RgbirdCaptureSession::InitializeCameraIds(
921     CameraDeviceSessionHwl* device_session_hwl) {
922   ATRACE_CALL();
923   if (device_session_hwl == nullptr) {
924     ALOGE("%s: Device session hwl is null.", __FUNCTION__);
925     return BAD_VALUE;
926   }
927 
928   std::vector<uint32_t> physical_camera_ids =
929       device_session_hwl->GetPhysicalCameraIds();
930   if (physical_camera_ids.size() != 3) {
931     ALOGE("%s: Failed to initialize camera ids. Only support 3 cameras",
932           __FUNCTION__);
933     return UNKNOWN_ERROR;
934   }
935 
936   // TODO(b/127322570): Figure out physical camera IDs from static metadata.
937   rgb_camera_id_ = physical_camera_ids[0];
938   ir1_camera_id_ = physical_camera_ids[1];
939   ir2_camera_id_ = physical_camera_ids[2];
940   return OK;
941 }
942 
Initialize(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,HwlRequestBuffersFunc request_stream_buffers,std::vector<HalStream> * hal_configured_streams)943 status_t RgbirdCaptureSession::Initialize(
944     CameraDeviceSessionHwl* device_session_hwl,
945     const StreamConfiguration& stream_config,
946     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
947     HwlRequestBuffersFunc request_stream_buffers,
948     std::vector<HalStream>* hal_configured_streams) {
949   ATRACE_CALL();
950   if (!IsStreamConfigurationSupported(device_session_hwl, stream_config)) {
951     ALOGE("%s: stream configuration is not supported.", __FUNCTION__);
952     return BAD_VALUE;
953   }
954 
955   // TODO(b/128633958): remove this after FLL syncing is verified
956   force_internal_stream_ =
957       property_get_bool("persist.vendor.camera.rgbird.forceinternal", false);
958   if (force_internal_stream_) {
959     ALOGI("%s: Force creating internal streams for IR pipelines", __FUNCTION__);
960   }
961 
962   device_session_hwl_ = device_session_hwl;
963   internal_stream_manager_ = InternalStreamManager::Create();
964   if (internal_stream_manager_ == nullptr) {
965     ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__);
966     return UNKNOWN_ERROR;
967   }
968 
969   std::unique_ptr<HalCameraMetadata> characteristics;
970   status_t res = device_session_hwl->GetCameraCharacteristics(&characteristics);
971   if (res != OK) {
972     ALOGE("%s: GetCameraCharacteristics failed.", __FUNCTION__);
973     return BAD_VALUE;
974   }
975 
976   is_hdrplus_supported_ = hal_utils::IsStreamHdrplusCompatible(
977       stream_config, characteristics.get());
978 
979   if (is_hdrplus_supported_) {
980     for (auto stream : stream_config.streams) {
981       if (utils::IsPreviewStream(stream)) {
982         hal_preview_stream_id_ = stream.id;
983         break;
984       }
985     }
986   }
987 
988   // Create result dispatcher
989   result_dispatcher_ =
990       ResultDispatcher::Create(kPartialResult, process_capture_result, notify);
991   if (result_dispatcher_ == nullptr) {
992     ALOGE("%s: Cannot create result dispatcher.", __FUNCTION__);
993     return UNKNOWN_ERROR;
994   }
995 
996   // Reroute callback functions
997   device_session_notify_ = notify;
998   process_capture_result_ =
999       ProcessCaptureResultFunc([this](std::unique_ptr<CaptureResult> result) {
1000         ProcessCaptureResult(std::move(result));
1001       });
1002   notify_ = NotifyFunc(
1003       [this](const NotifyMessage& message) { NotifyHalMessage(message); });
1004   request_stream_buffers_ = request_stream_buffers;
1005 
1006   // Initialize physical camera ids
1007   res = InitializeCameraIds(device_session_hwl_);
1008   if (res != OK) {
1009     ALOGE("%s: Initializing camera ids failed: %s(%d)", __FUNCTION__,
1010           strerror(-res), res);
1011     return res;
1012   }
1013 
1014   for (auto& stream : stream_config.streams) {
1015     if (utils::IsDepthStream(stream)) {
1016       ALOGI("%s: Depth stream exists in the stream config.", __FUNCTION__);
1017       has_depth_stream_ = true;
1018     }
1019   }
1020 
1021   // Finally create the process chains
1022   res = CreateProcessChain(stream_config, process_capture_result_, notify_,
1023                            hal_configured_streams);
1024   if (res != OK) {
1025     ALOGE("%s: Creating the process  chain failed: %s(%d)", __FUNCTION__,
1026           strerror(-res), res);
1027     return res;
1028   }
1029 
1030   return OK;
1031 }
1032 
ProcessRequest(const CaptureRequest & request)1033 status_t RgbirdCaptureSession::ProcessRequest(const CaptureRequest& request) {
1034   ATRACE_CALL();
1035   bool is_hdrplus_request = false;
1036   if (is_hdrplus_supported_) {
1037     is_hdrplus_request =
1038         hal_utils::IsRequestHdrplusCompatible(request, hal_preview_stream_id_);
1039     // TODO: Check if request is HDR+ request when contains a depth buffer
1040   }
1041 
1042   status_t res = result_dispatcher_->AddPendingRequest(request);
1043   if (res != OK) {
1044     ALOGE("%s: frame(%d) fail to AddPendingRequest", __FUNCTION__,
1045           request.frame_number);
1046     return BAD_VALUE;
1047   }
1048 
1049   if (is_hdrplus_request) {
1050     ALOGI("%s: hdrplus snapshot (%d), output stream size:%zu", __FUNCTION__,
1051           request.frame_number, request.output_buffers.size());
1052     res = hdrplus_request_processor_->ProcessRequest(request);
1053     if (res != OK) {
1054       ALOGI("%s: hdrplus snapshot frame(%d) request to realtime process",
1055             __FUNCTION__, request.frame_number);
1056       res = rt_request_processor_->ProcessRequest(request);
1057     }
1058   } else {
1059     res = rt_request_processor_->ProcessRequest(request);
1060   }
1061 
1062   if (res != OK) {
1063     ALOGE("%s: ProcessRequest (%d) fail and remove pending request",
1064           __FUNCTION__, request.frame_number);
1065     result_dispatcher_->RemovePendingRequest(request.frame_number);
1066   }
1067   return res;
1068 }
1069 
Flush()1070 status_t RgbirdCaptureSession::Flush() {
1071   ATRACE_CALL();
1072   return rt_request_processor_->Flush();
1073 }
1074 
ProcessCaptureResult(std::unique_ptr<CaptureResult> result)1075 void RgbirdCaptureSession::ProcessCaptureResult(
1076     std::unique_ptr<CaptureResult> result) {
1077   ATRACE_CALL();
1078   std::lock_guard<std::mutex> lock(callback_lock_);
1079   status_t res = result_dispatcher_->AddResult(std::move(result));
1080   if (res != OK) {
1081     ALOGE("%s: fail to AddResult", __FUNCTION__);
1082     return;
1083   }
1084 }
1085 
NotifyHalMessage(const NotifyMessage & message)1086 void RgbirdCaptureSession::NotifyHalMessage(const NotifyMessage& message) {
1087   ATRACE_CALL();
1088   std::lock_guard<std::mutex> lock(callback_lock_);
1089   if (device_session_notify_ == nullptr) {
1090     ALOGE("%s: device_session_notify_ is nullptr. Dropping a message.",
1091           __FUNCTION__);
1092     return;
1093   }
1094 
1095   if (message.type == MessageType::kShutter) {
1096     status_t res =
1097         result_dispatcher_->AddShutter(message.message.shutter.frame_number,
1098                                        message.message.shutter.timestamp_ns);
1099     if (res != OK) {
1100       ALOGE("%s: frame(%d) fail to AddShutter", __FUNCTION__,
1101             message.message.shutter.frame_number);
1102       return;
1103     }
1104   } else if (message.type == MessageType::kError) {
1105     // drop the error notifications for the internal streams
1106     auto error_stream_id = message.message.error.error_stream_id;
1107     if (has_depth_stream_ &&
1108         message.message.error.error_code == ErrorCode::kErrorBuffer &&
1109         error_stream_id != kInvalidStreamId &&
1110         (error_stream_id == rgb_internal_yuv_stream_id_ ||
1111          error_stream_id == ir1_internal_raw_stream_id_ ||
1112          error_stream_id == ir2_internal_raw_stream_id_)) {
1113       return;
1114     }
1115 
1116     status_t res = result_dispatcher_->AddError(message.message.error);
1117     if (res != OK) {
1118       ALOGE("%s: AddError for frame %u failed: %s (%d).", __FUNCTION__,
1119             message.message.error.frame_number, strerror(-res), res);
1120       return;
1121     }
1122   } else {
1123     ALOGW("%s: Unsupported message type: %u", __FUNCTION__, message.type);
1124     device_session_notify_(message);
1125   }
1126 }
1127 }  // namespace google_camera_hal
1128 }  // namespace android
1129