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 #define LOG_TAG "EmulatedCameraDevSession"
17 #define ATRACE_TAG ATRACE_TAG_CAMERA
18 
19 #include "EmulatedCameraDeviceSessionHWLImpl.h"
20 
21 #include <android/hardware/graphics/common/1.2/types.h>
22 #include <hardware/gralloc.h>
23 #include <inttypes.h>
24 #include <log/log.h>
25 #include <utils/Trace.h>
26 
27 #include <memory>
28 
29 #include "EmulatedSensor.h"
30 #include "utils.h"
31 #include "utils/HWLUtils.h"
32 
33 namespace android {
34 
35 using google_camera_hal::utils::GetSensorActiveArraySize;
36 using google_camera_hal::utils::HasCapability;
37 
38 using android::hardware::graphics::common::V1_2::Dataspace;
39 std::unique_ptr<EmulatedCameraZoomRatioMapperHwlImpl>
Create(const std::unordered_map<uint32_t,std::pair<Dimension,Dimension>> & dims)40 EmulatedCameraZoomRatioMapperHwlImpl::Create(
41     const std::unordered_map<uint32_t, std::pair<Dimension, Dimension>>& dims) {
42   auto zoom_ratio_mapper_hwl_impl =
43       std::make_unique<EmulatedCameraZoomRatioMapperHwlImpl>(dims);
44   return zoom_ratio_mapper_hwl_impl;
45 }
46 
EmulatedCameraZoomRatioMapperHwlImpl(const std::unordered_map<uint32_t,std::pair<Dimension,Dimension>> & dims)47 EmulatedCameraZoomRatioMapperHwlImpl::EmulatedCameraZoomRatioMapperHwlImpl(
48     const std::unordered_map<uint32_t, std::pair<Dimension, Dimension>>& dims)
49     : camera_ids_to_dimensions_(dims) {
50 }
51 
GetActiveArrayDimensionToBeUsed(uint32_t camera_id,const HalCameraMetadata * settings,Dimension * active_array_dimension) const52 bool EmulatedCameraZoomRatioMapperHwlImpl::GetActiveArrayDimensionToBeUsed(
53     uint32_t camera_id, const HalCameraMetadata* settings,
54     Dimension* active_array_dimension) const {
55   auto dim_it = camera_ids_to_dimensions_.find(camera_id);
56   if (settings == nullptr || active_array_dimension == nullptr ||
57       dim_it == camera_ids_to_dimensions_.end()) {
58     // default request / camera id not found
59     return false;
60   }
61   camera_metadata_ro_entry entry = {};
62   status_t res = settings->Get(ANDROID_SENSOR_PIXEL_MODE, &entry);
63   if (res != OK) {
64     // return default res dimension
65     *active_array_dimension = dim_it->second.second;
66     return true;
67   }
68   if (entry.data.u8[0] == ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) {
69     // return max res mode dimension
70     *active_array_dimension = dim_it->second.first;
71   } else {
72     *active_array_dimension = dim_it->second.second;
73   }
74   return true;
75 }
76 
77 std::unique_ptr<EmulatedCameraDeviceSessionHwlImpl>
Create(uint32_t camera_id,std::unique_ptr<EmulatedCameraDeviceInfo> device_info,PhysicalDeviceMapPtr physical_devices,std::shared_ptr<EmulatedTorchState> torch_state)78 EmulatedCameraDeviceSessionHwlImpl::Create(
79     uint32_t camera_id, std::unique_ptr<EmulatedCameraDeviceInfo> device_info,
80     PhysicalDeviceMapPtr physical_devices,
81     std::shared_ptr<EmulatedTorchState> torch_state) {
82   ATRACE_CALL();
83   if (device_info.get() == nullptr) {
84     return nullptr;
85   }
86 
87   auto session = std::unique_ptr<EmulatedCameraDeviceSessionHwlImpl>(
88       new EmulatedCameraDeviceSessionHwlImpl(std::move(physical_devices),
89                                              torch_state));
90   if (session == nullptr) {
91     ALOGE("%s: Creating EmulatedCameraDeviceSessionHwlImpl failed",
92           __FUNCTION__);
93     return nullptr;
94   }
95 
96   status_t res = session->Initialize(camera_id, std::move(device_info));
97   if (res != OK) {
98     ALOGE("%s: Initializing EmulatedCameraDeviceSessionHwlImpl failed: %s(%d)",
99           __FUNCTION__, strerror(-res), res);
100     return nullptr;
101   }
102 
103   return session;
104 }
105 
GetArrayDimensions(uint32_t camera_id,const HalCameraMetadata * metadata)106 static std::pair<Dimension, Dimension> GetArrayDimensions(
107     uint32_t camera_id, const HalCameraMetadata* metadata) {
108   google_camera_hal::Rect active_array_size;
109   Dimension active_array_size_dimension;
110   Dimension active_array_size_dimension_maximum_resolution;
111   status_t ret = GetSensorActiveArraySize(metadata, &active_array_size);
112   if (ret != OK) {
113     ALOGE("%s: Failed to get sensor active array size for camera id %d",
114           __FUNCTION__, (int)camera_id);
115     return std::pair<Dimension, Dimension>();
116   }
117   active_array_size_dimension = {
118       active_array_size.right - active_array_size.left + 1,
119       active_array_size.bottom - active_array_size.top + 1};
120 
121   active_array_size_dimension_maximum_resolution = active_array_size_dimension;
122   if (HasCapability(
123           metadata,
124           ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR)) {
125     status_t ret = GetSensorActiveArraySize(metadata, &active_array_size,
126                                             /*maximum_resolution=*/true);
127     if (ret != OK) {
128       ALOGE(
129           "%s: Failed to get max resolution sensor active array size for "
130           "camera id %d",
131           __FUNCTION__, (int)camera_id);
132       return std::pair<Dimension, Dimension>();
133     }
134     active_array_size_dimension_maximum_resolution = {
135         active_array_size.right - active_array_size.left + 1,
136         active_array_size.bottom - active_array_size.top + 1};
137   }
138   return std::make_pair(active_array_size_dimension_maximum_resolution,
139                         active_array_size_dimension);
140 }
141 
Initialize(uint32_t camera_id,std::unique_ptr<EmulatedCameraDeviceInfo> device_info)142 status_t EmulatedCameraDeviceSessionHwlImpl::Initialize(
143     uint32_t camera_id, std::unique_ptr<EmulatedCameraDeviceInfo> device_info) {
144   camera_id_ = camera_id;
145   device_info_ = std::move(device_info);
146   stream_configuration_map_ = std::make_unique<StreamConfigurationMap>(
147       *(device_info_->static_metadata_));
148   stream_configuration_map_max_resolution_ =
149       std::make_unique<StreamConfigurationMap>(
150           *(device_info_->static_metadata_), true);
151   camera_metadata_ro_entry_t entry;
152   auto ret = device_info_->static_metadata_->Get(
153       ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &entry);
154   if (ret != OK) {
155     ALOGE("%s: Unable to extract ANDROID_REQUEST_PIPELINE_MAX_DEPTH, %s (%d)",
156           __FUNCTION__, strerror(-ret), ret);
157     return ret;
158   }
159 
160   max_pipeline_depth_ = entry.data.u8[0];
161 
162   std::unordered_map<uint32_t, std::pair<Dimension, Dimension>>
163       camera_ids_to_dimensions;
164   camera_ids_to_dimensions[camera_id] =
165       GetArrayDimensions(camera_id, device_info_->static_metadata_.get());
166 
167   ret = GetSensorCharacteristics(device_info_->static_metadata_.get(),
168                                  &sensor_chars_);
169   if (ret != OK) {
170     ALOGE("%s: Unable to extract sensor characteristics %s (%d)", __FUNCTION__,
171           strerror(-ret), ret);
172     return ret;
173   }
174 
175   ret = SupportsSessionHalBufManager(device_info_->static_metadata_.get(),
176                                      &supports_session_hal_buf_manager_);
177   if (ret != OK) {
178     ALOGE("%s: Unable to get sensor hal buffer manager support %s (%d)",
179           __FUNCTION__, strerror(-ret), ret);
180     return ret;
181   }
182 
183   logical_chars_.emplace(camera_id_, sensor_chars_);
184   for (const auto& it : *physical_device_map_) {
185     SensorCharacteristics physical_chars;
186     auto stat =
187         GetSensorCharacteristics(it.second.second.get(), &physical_chars);
188     if (stat == OK) {
189       logical_chars_.emplace(it.first, physical_chars);
190     } else {
191       ALOGE("%s: Unable to extract physical device: %u characteristics %s (%d)",
192             __FUNCTION__, it.first, strerror(-ret), ret);
193       return ret;
194     }
195     camera_ids_to_dimensions[it.first] =
196         GetArrayDimensions(it.first, it.second.second.get());
197     physical_stream_configuration_map_.emplace(
198         it.first,
199         std::make_unique<StreamConfigurationMap>(*it.second.second.get()));
200     physical_stream_configuration_map_max_resolution_.emplace(
201         it.first, std::make_unique<StreamConfigurationMap>(
202                       *it.second.second.get(), true));
203   }
204 
205   zoom_ratio_mapper_hwl_impl_ = std::move(
206       EmulatedCameraZoomRatioMapperHwlImpl::Create(camera_ids_to_dimensions));
207   return InitializeRequestProcessor();
208 }
209 
InitializeRequestProcessor()210 status_t EmulatedCameraDeviceSessionHwlImpl::InitializeRequestProcessor() {
211   sp<EmulatedSensor> emulated_sensor = new EmulatedSensor();
212   auto logical_chars = std::make_unique<LogicalCharacteristics>(logical_chars_);
213   auto ret = emulated_sensor->StartUp(camera_id_, std::move(logical_chars));
214   if (ret != OK) {
215     ALOGE("%s: Failed on sensor start up %s (%d)", __FUNCTION__, strerror(-ret),
216           ret);
217     return ret;
218   }
219 
220   request_processor_ = std::make_shared<EmulatedRequestProcessor>(
221       camera_id_, emulated_sensor, session_callback_);
222 
223   request_processor_->InitializeSensorQueue(request_processor_);
224 
225   return request_processor_->Initialize(
226       EmulatedCameraDeviceInfo::Clone(*device_info_),
227       ClonePhysicalDeviceMap(physical_device_map_));
228 }
229 
~EmulatedCameraDeviceSessionHwlImpl()230 EmulatedCameraDeviceSessionHwlImpl::~EmulatedCameraDeviceSessionHwlImpl() {
231   if (torch_state_.get() != nullptr) {
232     torch_state_->ReleaseFlashHw();
233   }
234 }
235 
ConstructDefaultRequestSettings(RequestTemplate type,std::unique_ptr<HalCameraMetadata> * default_settings)236 status_t EmulatedCameraDeviceSessionHwlImpl::ConstructDefaultRequestSettings(
237     RequestTemplate type, std::unique_ptr<HalCameraMetadata>* default_settings) {
238   ATRACE_CALL();
239   std::lock_guard<std::mutex> lock(api_mutex_);
240 
241   return request_processor_->GetDefaultRequest(type, default_settings);
242 }
243 
ConfigurePipeline(uint32_t physical_camera_id,HwlPipelineCallback hwl_pipeline_callback,const StreamConfiguration & request_config,const StreamConfiguration &,uint32_t * pipeline_id)244 status_t EmulatedCameraDeviceSessionHwlImpl::ConfigurePipeline(
245     uint32_t physical_camera_id, HwlPipelineCallback hwl_pipeline_callback,
246     const StreamConfiguration& request_config,
247     const StreamConfiguration& /*overall_config*/, uint32_t* pipeline_id) {
248   ATRACE_CALL();
249   std::lock_guard<std::mutex> lock(api_mutex_);
250   if (pipeline_id == nullptr) {
251     ALOGE("%s pipeline_id is nullptr", __FUNCTION__);
252     return BAD_VALUE;
253   }
254 
255   if (pipelines_built_) {
256     ALOGE("%s Cannot configure pipelines after calling BuildPipelines()",
257           __FUNCTION__);
258     return ALREADY_EXISTS;
259   }
260 
261   if (!EmulatedSensor::IsStreamCombinationSupported(
262           physical_camera_id, request_config, *stream_configuration_map_,
263           *stream_configuration_map_max_resolution_,
264           physical_stream_configuration_map_,
265           physical_stream_configuration_map_max_resolution_, logical_chars_)) {
266     ALOGE("%s: Stream combination not supported!", __FUNCTION__);
267     return BAD_VALUE;
268   }
269 
270   if ((physical_camera_id != camera_id_) &&
271       (physical_device_map_.get() != nullptr)) {
272     if (physical_device_map_->find(physical_camera_id) ==
273         physical_device_map_->end()) {
274       ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
275             __FUNCTION__, camera_id_, physical_camera_id);
276       return BAD_VALUE;
277     }
278   }
279 
280   *pipeline_id = pipelines_.size();
281   EmulatedPipeline emulated_pipeline{
282       .cb = hwl_pipeline_callback,
283       .physical_camera_id = physical_camera_id,
284       .pipeline_id = *pipeline_id,
285   };
286 
287   emulated_pipeline.streams.reserve(request_config.streams.size());
288   for (const auto& stream : request_config.streams) {
289     bool is_input = stream.stream_type == google_camera_hal::StreamType::kInput;
290     emulated_pipeline.streams.emplace(
291         stream.id,
292         EmulatedStream(
293             {{.id = stream.id,
294               .override_format =
295                   is_input ? stream.format
296                            : EmulatedSensor::OverrideFormat(
297                                  stream.format, stream.dynamic_profile),
298               .producer_usage = is_input ? 0
299                                          : GRALLOC_USAGE_SW_WRITE_OFTEN |
300                                                GRALLOC_USAGE_HW_CAMERA_WRITE |
301                                                GRALLOC_USAGE_HW_CAMERA_READ,
302               .consumer_usage = 0,
303               .max_buffers = max_pipeline_depth_,
304               .override_data_space =
305                   (stream.dynamic_profile ==
306                    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10) &&
307                           (stream.format ==
308                            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
309                       ? static_cast<android_dataspace_t>(
310                             Dataspace::BT2020_ITU_HLG)
311                       : stream.data_space,
312               .is_physical_camera_stream = stream.is_physical_camera_stream,
313               .physical_camera_id = stream.physical_camera_id},
314              .width = stream.width,
315              .height = stream.height,
316              .buffer_size = stream.buffer_size,
317              .is_input = is_input,
318              .group_id = stream.group_id,
319              .use_case = stream.use_case,
320              .color_space = stream.color_space}));
321 
322     if (stream.group_id != -1 && stream.is_physical_camera_stream) {
323       // TODO: For quad bayer camera, the logical camera id should be used if
324       // this is not a physical camera.
325       dynamic_stream_id_map_[stream.physical_camera_id][stream.group_id] =
326           stream.id;
327     }
328     if (!stream.is_physical_camera_stream &&
329         (stream.format == HAL_PIXEL_FORMAT_RAW16)) {
330       has_raw_stream_ = true;
331     }
332   }
333 
334   pipelines_.push_back(emulated_pipeline);
335 
336   return OK;
337 }
338 
GetConfiguredHalStream(uint32_t pipeline_id,std::vector<HalStream> * hal_streams) const339 status_t EmulatedCameraDeviceSessionHwlImpl::GetConfiguredHalStream(
340     uint32_t pipeline_id, std::vector<HalStream>* hal_streams) const {
341   ATRACE_CALL();
342   std::lock_guard<std::mutex> lock(api_mutex_);
343   if (hal_streams == nullptr) {
344     ALOGE("%s hal_streams is nullptr", __FUNCTION__);
345     return BAD_VALUE;
346   }
347 
348   if (!pipelines_built_) {
349     ALOGE("%s No pipeline was built.", __FUNCTION__);
350     return NO_INIT;
351   }
352 
353   if (pipeline_id >= pipelines_.size()) {
354     ALOGE("%s: Unknown pipeline ID: %u", __FUNCTION__, pipeline_id);
355     return NAME_NOT_FOUND;
356   }
357 
358   const auto& streams = pipelines_[pipeline_id].streams;
359   hal_streams->reserve(streams.size());
360   for (const auto& it : streams) {
361     hal_streams->push_back(it.second);
362   }
363 
364   return OK;
365 }
366 
BuildPipelines()367 status_t EmulatedCameraDeviceSessionHwlImpl::BuildPipelines() {
368   ATRACE_CALL();
369   std::lock_guard<std::mutex> lock(api_mutex_);
370   if (pipelines_built_) {
371     ALOGE("%s Pipelines have already been built!", __FUNCTION__);
372     return ALREADY_EXISTS;
373   } else if (pipelines_.size() == 0) {
374     ALOGE("%s No pipelines have been configured yet!", __FUNCTION__);
375     return NO_INIT;
376   }
377 
378   status_t ret = OK;
379   if (request_processor_ == nullptr) {
380     ret = InitializeRequestProcessor();
381   }
382 
383   if (ret == OK) {
384     pipelines_built_ = true;
385   }
386 
387   return OK;
388 }
389 
GetHalBufferManagedStreams(const StreamConfiguration & config)390 std::set<int32_t> EmulatedCameraDeviceSessionHwlImpl::GetHalBufferManagedStreams(
391     const StreamConfiguration& config) {
392   std::set<int32_t> ret;
393   for (const auto& stream : config.streams) {
394     if (stream.stream_type == google_camera_hal::StreamType::kInput) {
395       continue;
396     }
397     // Just a heuristic - odd numbered stream ids are hal buffer managed.
398     if ((stream.group_id != -1) || (stream.id % 2)) {
399       ret.insert(stream.id);
400     }
401   }
402   return ret;
403 }
404 
DestroyPipelines()405 void EmulatedCameraDeviceSessionHwlImpl::DestroyPipelines() {
406   ATRACE_CALL();
407   std::lock_guard<std::mutex> lock(api_mutex_);
408   if (!pipelines_built_) {
409     // Not an error - nothing to destroy
410     ALOGV("%s nothing to destroy", __FUNCTION__);
411     return;
412   }
413 
414   pipelines_built_ = false;
415   has_raw_stream_ = false;
416   pipelines_.clear();
417   request_processor_ = nullptr;
418 }
419 
CheckOutputFormatsForInput(const HwlPipelineRequest & request,const std::unordered_map<uint32_t,EmulatedStream> & streams,const std::unique_ptr<StreamConfigurationMap> & stream_configuration_map,android_pixel_format_t input_format)420 status_t EmulatedCameraDeviceSessionHwlImpl::CheckOutputFormatsForInput(
421     const HwlPipelineRequest& request,
422     const std::unordered_map<uint32_t, EmulatedStream>& streams,
423     const std::unique_ptr<StreamConfigurationMap>& stream_configuration_map,
424     android_pixel_format_t input_format) {
425   auto output_formats =
426       stream_configuration_map->GetValidOutputFormatsForInput(input_format);
427   for (const auto& output_buffer : request.output_buffers) {
428     auto output_stream = streams.at(output_buffer.stream_id);
429     if (output_formats.find(output_stream.override_format) ==
430         output_formats.end()) {
431       ALOGE(
432           "%s: Reprocess request with input format: 0x%x to output "
433           "format: 0x%x"
434           " not supported!",
435           __FUNCTION__, input_format, output_stream.override_format);
436       return BAD_VALUE;
437     }
438   }
439   return OK;
440 }
441 
SubmitRequests(uint32_t frame_number,std::vector<HwlPipelineRequest> & requests)442 status_t EmulatedCameraDeviceSessionHwlImpl::SubmitRequests(
443     uint32_t frame_number, std::vector<HwlPipelineRequest>& requests) {
444   ATRACE_CALL();
445   std::lock_guard<std::mutex> lock(api_mutex_);
446 
447   // Check whether reprocess request has valid/supported outputs.
448   for (const auto& request : requests) {
449     if (!request.input_buffers.empty()) {
450       for (const auto& input_buffer : request.input_buffers) {
451         const auto& streams = pipelines_[request.pipeline_id].streams;
452         auto input_stream = streams.at(input_buffer.stream_id);
453         if ((CheckOutputFormatsForInput(request, streams,
454                                         stream_configuration_map_,
455                                         input_stream.override_format) != OK) &&
456             (CheckOutputFormatsForInput(
457                  request, streams, stream_configuration_map_max_resolution_,
458                  input_stream.override_format) != OK)) {
459           return BAD_VALUE;
460         }
461       }
462     }
463   }
464 
465   if (error_state_) {
466     ALOGE("%s session is in error state and cannot process further requests",
467           __FUNCTION__);
468     return INVALID_OPERATION;
469   }
470 
471   return request_processor_->ProcessPipelineRequests(
472       frame_number, requests, pipelines_, dynamic_stream_id_map_,
473       has_raw_stream_);
474 }
475 
Flush()476 status_t EmulatedCameraDeviceSessionHwlImpl::Flush() {
477   ATRACE_CALL();
478   std::lock_guard<std::mutex> lock(api_mutex_);
479   return request_processor_->Flush();
480 }
481 
RepeatingRequestEnd(int32_t,const std::vector<int32_t> &)482 void EmulatedCameraDeviceSessionHwlImpl::RepeatingRequestEnd(
483     int32_t /*frame_number*/, const std::vector<int32_t>& /*stream_ids*/) {
484 }
485 
GetCameraId() const486 uint32_t EmulatedCameraDeviceSessionHwlImpl::GetCameraId() const {
487   return camera_id_;
488 }
489 
GetPhysicalCameraIds() const490 std::vector<uint32_t> EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraIds()
491     const {
492   if ((physical_device_map_.get() == nullptr) ||
493       (physical_device_map_->empty())) {
494     return std::vector<uint32_t>{};
495   }
496 
497   std::vector<uint32_t> ret;
498   ret.reserve(physical_device_map_->size());
499   for (const auto& it : *physical_device_map_) {
500     ret.push_back(it.first);
501   }
502 
503   return ret;
504 }
505 
GetCameraCharacteristics(std::unique_ptr<HalCameraMetadata> * characteristics) const506 status_t EmulatedCameraDeviceSessionHwlImpl::GetCameraCharacteristics(
507     std::unique_ptr<HalCameraMetadata>* characteristics) const {
508   ATRACE_CALL();
509   if (characteristics == nullptr) {
510     return BAD_VALUE;
511   }
512 
513   (*characteristics) =
514       HalCameraMetadata::Clone(device_info_->static_metadata_.get());
515 
516   if (*characteristics == nullptr) {
517     ALOGE("%s metadata clone failed", __FUNCTION__);
518     return NO_MEMORY;
519   }
520 
521   return OK;
522 }
523 
GetPhysicalCameraCharacteristics(uint32_t physical_camera_id,std::unique_ptr<HalCameraMetadata> * characteristics) const524 status_t EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraCharacteristics(
525     uint32_t physical_camera_id,
526     std::unique_ptr<HalCameraMetadata>* characteristics) const {
527   ATRACE_CALL();
528   if (characteristics == nullptr) {
529     return BAD_VALUE;
530   }
531 
532   if (physical_device_map_.get() == nullptr) {
533     ALOGE("%s: Camera: %d doesn't have physical device support!", __FUNCTION__,
534           camera_id_);
535     return BAD_VALUE;
536   }
537 
538   if (physical_device_map_->find(physical_camera_id) ==
539       physical_device_map_->end()) {
540     ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
541           __FUNCTION__, camera_id_, physical_camera_id);
542     return BAD_VALUE;
543   }
544 
545   (*characteristics) = HalCameraMetadata::Clone(
546       physical_device_map_->at(physical_camera_id).second.get());
547 
548   return OK;
549 }
550 
SetSessionCallback(const HwlSessionCallback & hwl_session_callback)551 void EmulatedCameraDeviceSessionHwlImpl::SetSessionCallback(
552     const HwlSessionCallback& hwl_session_callback) {
553   ATRACE_CALL();
554   std::lock_guard<std::mutex> lock(api_mutex_);
555   session_callback_ = hwl_session_callback;
556   if (request_processor_ != nullptr) {
557     request_processor_->SetSessionCallback(hwl_session_callback);
558   }
559 }
560 
561 }  // namespace android
562