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 = GetSensorCharacteristics(it.second.second.get(), &physical_chars);
187 if (stat == OK) {
188 logical_chars_.emplace(it.first, physical_chars);
189 } else {
190 ALOGE("%s: Unable to extract physical device: %u characteristics %s (%d)",
191 __FUNCTION__, it.first, strerror(-ret), ret);
192 return ret;
193 }
194 camera_ids_to_dimensions[it.first] =
195 GetArrayDimensions(it.first, it.second.second.get());
196 physical_stream_configuration_map_.emplace(
197 it.first,
198 std::make_unique<StreamConfigurationMap>(*it.second.second.get()));
199 physical_stream_configuration_map_max_resolution_.emplace(
200 it.first, std::make_unique<StreamConfigurationMap>(
201 *it.second.second.get(), true));
202 }
203
204 zoom_ratio_mapper_hwl_impl_ = std::move(
205 EmulatedCameraZoomRatioMapperHwlImpl::Create(camera_ids_to_dimensions));
206 return InitializeRequestProcessor();
207 }
208
InitializeRequestProcessor()209 status_t EmulatedCameraDeviceSessionHwlImpl::InitializeRequestProcessor() {
210 sp<EmulatedSensor> emulated_sensor = new EmulatedSensor();
211 auto logical_chars = std::make_unique<LogicalCharacteristics>(logical_chars_);
212 auto ret = emulated_sensor->StartUp(camera_id_, std::move(logical_chars));
213 if (ret != OK) {
214 ALOGE("%s: Failed on sensor start up %s (%d)", __FUNCTION__, strerror(-ret),
215 ret);
216 return ret;
217 }
218
219 request_processor_ = std::make_shared<EmulatedRequestProcessor>(
220 camera_id_, emulated_sensor, session_callback_);
221
222 request_processor_->InitializeSensorQueue(request_processor_);
223
224 return request_processor_->Initialize(
225 EmulatedCameraDeviceInfo::Clone(*device_info_),
226 ClonePhysicalDeviceMap(physical_device_map_));
227 }
228
~EmulatedCameraDeviceSessionHwlImpl()229 EmulatedCameraDeviceSessionHwlImpl::~EmulatedCameraDeviceSessionHwlImpl() {
230 if (torch_state_.get() != nullptr) {
231 torch_state_->ReleaseFlashHw();
232 }
233 }
234
ConstructDefaultRequestSettings(RequestTemplate type,std::unique_ptr<HalCameraMetadata> * default_settings)235 status_t EmulatedCameraDeviceSessionHwlImpl::ConstructDefaultRequestSettings(
236 RequestTemplate type, std::unique_ptr<HalCameraMetadata>* default_settings) {
237 ATRACE_CALL();
238 std::lock_guard<std::mutex> lock(api_mutex_);
239
240 return request_processor_->GetDefaultRequest(type, default_settings);
241 }
242
ConfigurePipeline(uint32_t physical_camera_id,HwlPipelineCallback hwl_pipeline_callback,const StreamConfiguration & request_config,const StreamConfiguration &,uint32_t * pipeline_id)243 status_t EmulatedCameraDeviceSessionHwlImpl::ConfigurePipeline(
244 uint32_t physical_camera_id, HwlPipelineCallback hwl_pipeline_callback,
245 const StreamConfiguration& request_config,
246 const StreamConfiguration& /*overall_config*/, uint32_t* pipeline_id) {
247 ATRACE_CALL();
248 std::lock_guard<std::mutex> lock(api_mutex_);
249 if (pipeline_id == nullptr) {
250 ALOGE("%s pipeline_id is nullptr", __FUNCTION__);
251 return BAD_VALUE;
252 }
253
254 if (pipelines_built_) {
255 ALOGE("%s Cannot configure pipelines after calling BuildPipelines()",
256 __FUNCTION__);
257 return ALREADY_EXISTS;
258 }
259
260 if (!EmulatedSensor::IsStreamCombinationSupported(
261 physical_camera_id, request_config, *stream_configuration_map_,
262 *stream_configuration_map_max_resolution_,
263 physical_stream_configuration_map_,
264 physical_stream_configuration_map_max_resolution_, logical_chars_)) {
265 ALOGE("%s: Stream combination not supported!", __FUNCTION__);
266 return BAD_VALUE;
267 }
268
269 if ((physical_camera_id != camera_id_) &&
270 (physical_device_map_.get() != nullptr)) {
271 if (physical_device_map_->find(physical_camera_id) ==
272 physical_device_map_->end()) {
273 ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
274 __FUNCTION__, camera_id_, physical_camera_id);
275 return BAD_VALUE;
276 }
277 }
278
279 *pipeline_id = pipelines_.size();
280 EmulatedPipeline emulated_pipeline{.cb = hwl_pipeline_callback,
281 .physical_camera_id = physical_camera_id,
282 .pipeline_id = *pipeline_id,};
283
284 emulated_pipeline.streams.reserve(request_config.streams.size());
285 for (const auto& stream : request_config.streams) {
286 bool is_input = stream.stream_type == google_camera_hal::StreamType::kInput;
287 emulated_pipeline.streams.emplace(
288 stream.id,
289 EmulatedStream(
290 {{.id = stream.id,
291 .override_format =
292 is_input ? stream.format
293 : EmulatedSensor::OverrideFormat(
294 stream.format, stream.dynamic_profile),
295 .producer_usage = is_input ? 0
296 : GRALLOC_USAGE_SW_WRITE_OFTEN |
297 GRALLOC_USAGE_HW_CAMERA_WRITE |
298 GRALLOC_USAGE_HW_CAMERA_READ,
299 .consumer_usage = 0,
300 .max_buffers = max_pipeline_depth_,
301 .override_data_space =
302 (stream.dynamic_profile ==
303 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10) &&
304 (stream.format ==
305 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
306 ? static_cast<android_dataspace_t>(
307 Dataspace::BT2020_ITU_HLG)
308 : stream.data_space,
309 .is_physical_camera_stream = stream.is_physical_camera_stream,
310 .physical_camera_id = stream.physical_camera_id},
311 .width = stream.width,
312 .height = stream.height,
313 .buffer_size = stream.buffer_size,
314 .is_input = is_input,
315 .group_id = stream.group_id,
316 .use_case = stream.use_case,
317 .color_space = stream.color_space}));
318
319 if (stream.group_id != -1 && stream.is_physical_camera_stream) {
320 // TODO: For quad bayer camera, the logical camera id should be used if
321 // this is not a physical camera.
322 dynamic_stream_id_map_[stream.physical_camera_id][stream.group_id] =
323 stream.id;
324 }
325 if (!stream.is_physical_camera_stream &&
326 (stream.format == HAL_PIXEL_FORMAT_RAW16)) {
327 has_raw_stream_ = true;
328 }
329 }
330
331 pipelines_.push_back(emulated_pipeline);
332
333 return OK;
334 }
335
GetConfiguredHalStream(uint32_t pipeline_id,std::vector<HalStream> * hal_streams) const336 status_t EmulatedCameraDeviceSessionHwlImpl::GetConfiguredHalStream(
337 uint32_t pipeline_id, std::vector<HalStream>* hal_streams) const {
338 ATRACE_CALL();
339 std::lock_guard<std::mutex> lock(api_mutex_);
340 if (hal_streams == nullptr) {
341 ALOGE("%s hal_streams is nullptr", __FUNCTION__);
342 return BAD_VALUE;
343 }
344
345 if (!pipelines_built_) {
346 ALOGE("%s No pipeline was built.", __FUNCTION__);
347 return NO_INIT;
348 }
349
350 if (pipeline_id >= pipelines_.size()) {
351 ALOGE("%s: Unknown pipeline ID: %u", __FUNCTION__, pipeline_id);
352 return NAME_NOT_FOUND;
353 }
354
355 const auto& streams = pipelines_[pipeline_id].streams;
356 hal_streams->reserve(streams.size());
357 for (const auto& it : streams) {
358 hal_streams->push_back(it.second);
359 }
360
361 return OK;
362 }
363
BuildPipelines()364 status_t EmulatedCameraDeviceSessionHwlImpl::BuildPipelines() {
365 ATRACE_CALL();
366 std::lock_guard<std::mutex> lock(api_mutex_);
367 if (pipelines_built_) {
368 ALOGE("%s Pipelines have already been built!", __FUNCTION__);
369 return ALREADY_EXISTS;
370 } else if (pipelines_.size() == 0) {
371 ALOGE("%s No pipelines have been configured yet!", __FUNCTION__);
372 return NO_INIT;
373 }
374
375 status_t ret = OK;
376 if (request_processor_ == nullptr) {
377 ret = InitializeRequestProcessor();
378 }
379
380 if (ret == OK) {
381 pipelines_built_ = true;
382 }
383
384 return OK;
385 }
386
GetHalBufferManagedStreams(const StreamConfiguration & config)387 std::set<int32_t> EmulatedCameraDeviceSessionHwlImpl::GetHalBufferManagedStreams(
388 const StreamConfiguration& config) {
389 std::set<int32_t> ret;
390 for (const auto& stream : config.streams) {
391 if (stream.stream_type == google_camera_hal::StreamType::kInput) {
392 continue;
393 }
394 // Just a heuristic - odd numbered stream ids are hal buffer managed.
395 if ((stream.group_id != -1) || (stream.id % 2)) {
396 ret.insert(stream.id);
397 }
398 }
399 return ret;
400 }
401
DestroyPipelines()402 void EmulatedCameraDeviceSessionHwlImpl::DestroyPipelines() {
403 ATRACE_CALL();
404 std::lock_guard<std::mutex> lock(api_mutex_);
405 if (!pipelines_built_) {
406 // Not an error - nothing to destroy
407 ALOGV("%s nothing to destroy", __FUNCTION__);
408 return;
409 }
410
411 pipelines_built_ = false;
412 has_raw_stream_ = false;
413 pipelines_.clear();
414 request_processor_ = nullptr;
415 }
416
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)417 status_t EmulatedCameraDeviceSessionHwlImpl::CheckOutputFormatsForInput(
418 const HwlPipelineRequest& request,
419 const std::unordered_map<uint32_t, EmulatedStream>& streams,
420 const std::unique_ptr<StreamConfigurationMap>& stream_configuration_map,
421 android_pixel_format_t input_format) {
422 auto output_formats =
423 stream_configuration_map->GetValidOutputFormatsForInput(input_format);
424 for (const auto& output_buffer : request.output_buffers) {
425 auto output_stream = streams.at(output_buffer.stream_id);
426 if (output_formats.find(output_stream.override_format) ==
427 output_formats.end()) {
428 ALOGE(
429 "%s: Reprocess request with input format: 0x%x to output "
430 "format: 0x%x"
431 " not supported!",
432 __FUNCTION__, input_format, output_stream.override_format);
433 return BAD_VALUE;
434 }
435 }
436 return OK;
437 }
438
SubmitRequests(uint32_t frame_number,std::vector<HwlPipelineRequest> & requests)439 status_t EmulatedCameraDeviceSessionHwlImpl::SubmitRequests(
440 uint32_t frame_number, std::vector<HwlPipelineRequest>& requests) {
441 ATRACE_CALL();
442 std::lock_guard<std::mutex> lock(api_mutex_);
443
444 // Check whether reprocess request has valid/supported outputs.
445 for (const auto& request : requests) {
446 if (!request.input_buffers.empty()) {
447 for (const auto& input_buffer : request.input_buffers) {
448 const auto& streams = pipelines_[request.pipeline_id].streams;
449 auto input_stream = streams.at(input_buffer.stream_id);
450 if ((CheckOutputFormatsForInput(request, streams,
451 stream_configuration_map_,
452 input_stream.override_format) != OK) &&
453 (CheckOutputFormatsForInput(
454 request, streams, stream_configuration_map_max_resolution_,
455 input_stream.override_format) != OK)) {
456 return BAD_VALUE;
457 }
458 }
459 }
460 }
461
462 if (error_state_) {
463 ALOGE("%s session is in error state and cannot process further requests",
464 __FUNCTION__);
465 return INVALID_OPERATION;
466 }
467
468 return request_processor_->ProcessPipelineRequests(
469 frame_number, requests, pipelines_, dynamic_stream_id_map_,
470 has_raw_stream_);
471 }
472
Flush()473 status_t EmulatedCameraDeviceSessionHwlImpl::Flush() {
474 ATRACE_CALL();
475 std::lock_guard<std::mutex> lock(api_mutex_);
476 return request_processor_->Flush();
477 }
478
GetCameraId() const479 uint32_t EmulatedCameraDeviceSessionHwlImpl::GetCameraId() const {
480 return camera_id_;
481 }
482
GetPhysicalCameraIds() const483 std::vector<uint32_t> EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraIds()
484 const {
485 if ((physical_device_map_.get() == nullptr) ||
486 (physical_device_map_->empty())) {
487 return std::vector<uint32_t>{};
488 }
489
490 std::vector<uint32_t> ret;
491 ret.reserve(physical_device_map_->size());
492 for (const auto& it : *physical_device_map_) {
493 ret.push_back(it.first);
494 }
495
496 return ret;
497 }
498
GetCameraCharacteristics(std::unique_ptr<HalCameraMetadata> * characteristics) const499 status_t EmulatedCameraDeviceSessionHwlImpl::GetCameraCharacteristics(
500 std::unique_ptr<HalCameraMetadata>* characteristics) const {
501 ATRACE_CALL();
502 if (characteristics == nullptr) {
503 return BAD_VALUE;
504 }
505
506 (*characteristics) =
507 HalCameraMetadata::Clone(device_info_->static_metadata_.get());
508
509 if (*characteristics == nullptr) {
510 ALOGE("%s metadata clone failed", __FUNCTION__);
511 return NO_MEMORY;
512 }
513
514 return OK;
515 }
516
GetPhysicalCameraCharacteristics(uint32_t physical_camera_id,std::unique_ptr<HalCameraMetadata> * characteristics) const517 status_t EmulatedCameraDeviceSessionHwlImpl::GetPhysicalCameraCharacteristics(
518 uint32_t physical_camera_id,
519 std::unique_ptr<HalCameraMetadata>* characteristics) const {
520 ATRACE_CALL();
521 if (characteristics == nullptr) {
522 return BAD_VALUE;
523 }
524
525 if (physical_device_map_.get() == nullptr) {
526 ALOGE("%s: Camera: %d doesn't have physical device support!", __FUNCTION__,
527 camera_id_);
528 return BAD_VALUE;
529 }
530
531 if (physical_device_map_->find(physical_camera_id) ==
532 physical_device_map_->end()) {
533 ALOGE("%s: Camera: %d doesn't include physical device with id: %u",
534 __FUNCTION__, camera_id_, physical_camera_id);
535 return BAD_VALUE;
536 }
537
538 (*characteristics) = HalCameraMetadata::Clone(
539 physical_device_map_->at(physical_camera_id).second.get());
540
541 return OK;
542 }
543
SetSessionCallback(const HwlSessionCallback & hwl_session_callback)544 void EmulatedCameraDeviceSessionHwlImpl::SetSessionCallback(
545 const HwlSessionCallback& hwl_session_callback) {
546 ATRACE_CALL();
547 std::lock_guard<std::mutex> lock(api_mutex_);
548 session_callback_ = hwl_session_callback;
549 if (request_processor_ != nullptr) {
550 request_processor_->SetSessionCallback(hwl_session_callback);
551 }
552 }
553
554 } // namespace android
555