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