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