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