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