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 
17 #define LOG_TAG "EmulatedLogicalState"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 
21 #include "EmulatedLogicalRequestState.h"
22 
23 #include <log/log.h>
24 
25 #include "vendor_tag_defs.h"
26 
27 namespace android {
28 
EmulatedLogicalRequestState(uint32_t camera_id)29 EmulatedLogicalRequestState::EmulatedLogicalRequestState(uint32_t camera_id)
30     : logical_camera_id_(camera_id),
31       logical_request_state_(std::make_unique<EmulatedRequestState>(camera_id)) {
32 }
33 
~EmulatedLogicalRequestState()34 EmulatedLogicalRequestState::~EmulatedLogicalRequestState() {
35 }
36 
Initialize(std::unique_ptr<EmulatedCameraDeviceInfo> device_info,PhysicalDeviceMapPtr physical_devices)37 status_t EmulatedLogicalRequestState::Initialize(
38     std::unique_ptr<EmulatedCameraDeviceInfo> device_info,
39     PhysicalDeviceMapPtr physical_devices) {
40   if ((physical_devices.get() != nullptr) && (!physical_devices->empty())) {
41     zoom_ratio_physical_camera_info_ = GetZoomRatioPhysicalCameraInfo(
42         device_info->static_metadata_.get(), physical_devices.get());
43 
44     physical_device_map_ = std::move(physical_devices);
45 
46     static const float ZOOM_RATIO_THRESHOLD = 0.001f;
47     for (const auto& one_zoom_range : zoom_ratio_physical_camera_info_) {
48       ALOGV("%s: cameraId %d, focalLength %f, zoomRatioRange [%f, %f]",
49             __FUNCTION__, one_zoom_range.physical_camera_id,
50             one_zoom_range.focal_length, one_zoom_range.min_zoom_ratio,
51             one_zoom_range.max_zoom_ratio);
52       if (std::abs(one_zoom_range.min_zoom_ratio - 1.0f) < ZOOM_RATIO_THRESHOLD) {
53         current_physical_camera_ = one_zoom_range.physical_camera_id;
54       }
55     }
56 
57     if (zoom_ratio_physical_camera_info_.size() > 1) {
58       is_logical_device_ = true;
59       for (const auto& it : *physical_device_map_) {
60         std::unique_ptr<EmulatedRequestState> physical_request_state =
61             std::make_unique<EmulatedRequestState>(it.first);
62         auto ret =
63             physical_request_state->Initialize(EmulatedCameraDeviceInfo::Create(
64                 HalCameraMetadata::Clone(it.second.second.get())));
65         if (ret != OK) {
66           ALOGE("%s: Physical device: %u request state initialization failed!",
67                 __FUNCTION__, it.first);
68           return ret;
69         }
70         physical_request_states_.emplace(it.first,
71                                          std::move(physical_request_state));
72       }
73     }
74   }
75 
76   return logical_request_state_->Initialize(std::move(device_info));
77 }
78 
GetDefaultRequest(RequestTemplate type,std::unique_ptr<HalCameraMetadata> * default_settings)79 status_t EmulatedLogicalRequestState::GetDefaultRequest(
80     RequestTemplate type,
81     std::unique_ptr<HalCameraMetadata>* default_settings /*out*/) {
82   return logical_request_state_->GetDefaultRequest(type, default_settings);
83 };
84 
UpdateActivePhysicalId(HalCameraMetadata * result_metadata,uint32_t device_id)85 void EmulatedLogicalRequestState::UpdateActivePhysicalId(
86     HalCameraMetadata* result_metadata, uint32_t device_id) {
87   if (result_metadata == nullptr) {
88     return;
89   }
90 
91   auto device_id_str = std::to_string(device_id);
92   std::vector<uint8_t> result;
93   result.reserve(device_id_str.size() + 1);
94   result.insert(result.end(), device_id_str.begin(), device_id_str.end());
95   result.push_back('\0');
96 
97   result_metadata->Set(ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID,
98                        result.data(), result.size());
99 }
100 
101 std::unique_ptr<HwlPipelineResult>
InitializeLogicalResult(uint32_t pipeline_id,uint32_t frame_number,bool is_partial_result)102 EmulatedLogicalRequestState::InitializeLogicalResult(uint32_t pipeline_id,
103                                                      uint32_t frame_number,
104                                                      bool is_partial_result) {
105   auto ret =
106       is_partial_result
107           ? logical_request_state_->InitializePartialResult(pipeline_id,
108                                                             frame_number)
109           : logical_request_state_->InitializeResult(pipeline_id, frame_number);
110 
111   if (is_logical_device_ && !is_partial_result) {
112     if ((physical_camera_output_ids_.get() != nullptr) &&
113         (!physical_camera_output_ids_->empty())) {
114       ret->physical_camera_results.reserve(physical_camera_output_ids_->size());
115       for (const auto& it : *physical_camera_output_ids_) {
116         ret->physical_camera_results[it] =
117             std::move(physical_request_states_[it]
118                           ->InitializeResult(pipeline_id, frame_number)
119                           ->result_metadata);
120 
121         UpdateActivePhysicalId(ret->physical_camera_results[it].get(), it);
122       }
123     }
124 
125     UpdateActivePhysicalId(ret->result_metadata.get(), current_physical_camera_);
126 
127     // The logical camera result lens intrinsic calibration must reflect
128     // calibration of the currently active physical device.
129     const auto& physical_device = physical_device_map_->find(current_physical_camera_);
130     if (physical_device != physical_device_map_->end()) {
131         camera_metadata_ro_entry_t entry, physical_entry;
132         if ((ret->result_metadata->Get(ANDROID_LENS_INTRINSIC_CALIBRATION,
133                                        &entry) == OK) &&
134             (entry.count > 0)) {
135           if ((physical_device->second.second->Get(
136                    ANDROID_LENS_INTRINSIC_CALIBRATION, &physical_entry) == OK) &&
137               (physical_entry.count > 0)) {
138             ret->result_metadata->Set(ANDROID_LENS_INTRINSIC_CALIBRATION,
139                                       physical_entry.data.f,
140                                       physical_entry.count);
141           } else {
142             ALOGE(
143                 "%s: Logical camera %d supports lens intrinsic calibration but "
144                 "physical device: %d does not!",
145                 __FUNCTION__, logical_camera_id_, current_physical_camera_);
146           }
147         }
148     } else {
149       ALOGE("%s: Couldn't find physical device id: %d", __FUNCTION__,
150             current_physical_camera_);
151     }
152   }
153 
154   return ret;
155 }
156 
InitializeLogicalSettings(std::unique_ptr<HalCameraMetadata> request_settings,std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids,uint32_t override_frame_number,EmulatedSensor::LogicalCameraSettings * logical_settings)157 status_t EmulatedLogicalRequestState::InitializeLogicalSettings(
158     std::unique_ptr<HalCameraMetadata> request_settings,
159     std::unique_ptr<std::set<uint32_t>> physical_camera_output_ids,
160     uint32_t override_frame_number,
161     EmulatedSensor::LogicalCameraSettings* logical_settings /*out*/) {
162   if (logical_settings == nullptr) {
163     return BAD_VALUE;
164   }
165 
166   // All logical and physical devices can potentially receive individual client
167   // requests (Currently this is not the case due to HWL API limitations).
168   // The emulated sensor can adapt its characteristics and apply most of them
169   // independently however the frame duration needs to be the same across all
170   // settings.
171   // Track the maximum frame duration and override this value at the end for all
172   // logical settings.
173   nsecs_t max_frame_duration = 0;
174   if (is_logical_device_) {
175     std::swap(physical_camera_output_ids_, physical_camera_output_ids);
176 
177     for (const auto& physical_request_state : physical_request_states_) {
178       // All physical devices will receive requests and will keep
179       // updating their respective request state.
180       // However only physical devices referenced by client need to propagate
181       // and apply their settings.
182       EmulatedSensor::SensorSettings physical_sensor_settings;
183       auto ret = physical_request_state.second->InitializeSensorSettings(
184           HalCameraMetadata::Clone(request_settings.get()),
185           override_frame_number, &physical_sensor_settings);
186       if (ret != OK) {
187         ALOGE(
188             "%s: Initialization of physical sensor settings for device id: %u  "
189             "failed!",
190             __FUNCTION__, physical_request_state.first);
191         return ret;
192       }
193 
194       if (physical_camera_output_ids_->find(physical_request_state.first) !=
195           physical_camera_output_ids_->end()) {
196         logical_settings->emplace(physical_request_state.first,
197                                   physical_sensor_settings);
198         if (max_frame_duration < physical_sensor_settings.exposure_time) {
199           max_frame_duration = physical_sensor_settings.exposure_time;
200         }
201       }
202     }
203   }
204 
205   EmulatedSensor::SensorSettings sensor_settings;
206   auto ret = logical_request_state_->InitializeSensorSettings(
207       std::move(request_settings), override_frame_number, &sensor_settings);
208   logical_settings->emplace(logical_camera_id_, sensor_settings);
209   if (max_frame_duration < sensor_settings.exposure_time) {
210     max_frame_duration = sensor_settings.exposure_time;
211   }
212 
213   for (auto it : *logical_settings) {
214     it.second.frame_duration = max_frame_duration;
215   }
216 
217   return ret;
218 }
219 
220 std::unique_ptr<HalCameraMetadata>
AdaptLogicalCharacteristics(std::unique_ptr<HalCameraMetadata> logical_chars,PhysicalDeviceMapPtr physical_devices)221 EmulatedLogicalRequestState::AdaptLogicalCharacteristics(
222     std::unique_ptr<HalCameraMetadata> logical_chars,
223     PhysicalDeviceMapPtr physical_devices) {
224   if ((logical_chars.get() == nullptr) || (physical_devices.get() == nullptr)) {
225     return nullptr;
226   }
227 
228   // Update 'android.logicalMultiCamera.physicalIds' according to the newly
229   // assigned physical ids.
230   // Additionally if possible try to emulate a logical camera device backed by
231   // physical devices with different focal lengths. Usually real logical
232   // cameras like that will have device specific logic to switch between
233   // physical sensors. Unfortunately we cannot infer this behavior using only
234   // static camera characteristics. Use a simplistic approach of inferring
235   // physical camera based on zoom ratio.
236   std::vector<ZoomRatioPhysicalCameraInfo> zoom_ratio_physical_camera_info =
237       GetZoomRatioPhysicalCameraInfo(logical_chars.get(),
238                                      physical_devices.get());
239 
240   std::vector<uint8_t> physical_ids;
241   for (const auto& physical_device : *physical_devices) {
242     auto physical_id = std::to_string(physical_device.first);
243     physical_ids.insert(physical_ids.end(), physical_id.begin(),
244                         physical_id.end());
245     physical_ids.push_back('\0');
246   }
247 
248   if (zoom_ratio_physical_camera_info.size() > 1) {
249     float zoom_range[2];
250     zoom_range[0] = zoom_ratio_physical_camera_info[0].min_zoom_ratio;
251     zoom_range[1] =
252         zoom_ratio_physical_camera_info[zoom_ratio_physical_camera_info.size() - 1]
253             .max_zoom_ratio;
254     logical_chars->Set(ANDROID_CONTROL_ZOOM_RATIO_RANGE, zoom_range, 2);
255 
256     logical_chars->Set(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
257                        &zoom_range[1], 1);
258 
259     logical_chars->Set(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
260                        physical_ids.data(), physical_ids.size());
261 
262     // Possibly needs to be removed at some later point:
263     int32_t default_physical_id = physical_devices->begin()->first;
264     logical_chars->Set(google_camera_hal::kLogicalCamDefaultPhysicalId,
265                        &default_physical_id, 1);
266 
267     camera_metadata_ro_entry entry;
268     logical_chars->Get(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
269     std::set<int32_t> keys(entry.data.i32, entry.data.i32 + entry.count);
270     keys.emplace(ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
271     std::vector<int32_t> keys_buffer(keys.begin(), keys.end());
272     logical_chars->Set(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
273                        keys_buffer.data(), keys_buffer.size());
274 
275     keys.clear();
276     keys_buffer.clear();
277     logical_chars->Get(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
278     keys.insert(entry.data.i32, entry.data.i32 + entry.count);
279     // Due to API limitations we currently don't support individual physical requests
280     logical_chars->Erase(ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
281     keys.erase(ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
282     keys.emplace(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
283     keys_buffer.insert(keys_buffer.end(), keys.begin(), keys.end());
284     logical_chars->Set(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
285                        keys_buffer.data(), keys_buffer.size());
286   } else {
287     ALOGW(
288         "%s: The logical camera doesn't support combined zoom ratio ranges. "
289         "Emulation "
290         "could be"
291         " very limited in this case!",
292         __FUNCTION__);
293   }
294 
295   return logical_chars;
296 }
297 
UpdateRequestForDynamicStreams(HwlPipelineRequest * request,const std::vector<EmulatedPipeline> & pipelines,const DynamicStreamIdMapType & dynamic_stream_id_map,bool use_default_physical_camera)298 status_t EmulatedLogicalRequestState::UpdateRequestForDynamicStreams(
299     HwlPipelineRequest* request, const std::vector<EmulatedPipeline>& pipelines,
300     const DynamicStreamIdMapType& dynamic_stream_id_map,
301     bool use_default_physical_camera) {
302   if (request == nullptr) {
303     ALOGE("%s: Request must not be null!", __FUNCTION__);
304     return BAD_VALUE;
305   }
306 
307   uint32_t pipeline_id = request->pipeline_id;
308   if (pipeline_id >= pipelines.size()) {
309     ALOGE("%s: Invalid pipeline id %d", __FUNCTION__, pipeline_id);
310     return BAD_VALUE;
311   }
312 
313   // Only logical camera support dynamic size streams.
314   if (!is_logical_device_) return OK;
315 
316   if (request->settings != nullptr) {
317     camera_metadata_ro_entry entry;
318     auto stat = request->settings->Get(ANDROID_CONTROL_ZOOM_RATIO, &entry);
319     if (stat != OK || entry.count != 1) {
320       ALOGW("%s: Zoom ratio absent from request, re-using older value!",
321             __FUNCTION__);
322       return BAD_VALUE;
323     }
324     if (!use_default_physical_camera) {
325       float zoom_ratio = entry.data.f[0];
326       for (const auto& one_range : zoom_ratio_physical_camera_info_) {
327         if (zoom_ratio >= one_range.min_zoom_ratio &&
328             zoom_ratio <= one_range.max_zoom_ratio) {
329           current_physical_camera_ = one_range.physical_camera_id;
330           break;
331         }
332       }
333     }
334   }
335 
336   const auto& current_pipeline = pipelines[pipeline_id];
337   for (auto& output_buffer : request->output_buffers) {
338     auto& current_stream = current_pipeline.streams.at(output_buffer.stream_id);
339     if (current_stream.group_id == -1) continue;
340 
341     const auto& stream_ids_for_camera =
342         dynamic_stream_id_map.find(current_physical_camera_);
343     if (stream_ids_for_camera == dynamic_stream_id_map.end()) {
344       ALOGW(
345           "%s: Failed to find physical camera id %d in dynamic stream id map!",
346           __FUNCTION__, current_physical_camera_);
347       continue;
348     }
349     const auto& stream_id =
350         stream_ids_for_camera->second.find(current_stream.group_id);
351     if (stream_id == stream_ids_for_camera->second.end()) {
352       ALOGW(
353           "%s: Failed to find group id %d in dynamic stream id map for camera "
354           "%d",
355           __FUNCTION__, current_stream.group_id, current_physical_camera_);
356       continue;
357     }
358 
359     output_buffer.stream_id = stream_id->second;
360   }
361   return OK;
362 }
363 
364 std::vector<ZoomRatioPhysicalCameraInfo>
GetZoomRatioPhysicalCameraInfo(const HalCameraMetadata * logical_chars,const PhysicalDeviceMap * physical_devices)365 EmulatedLogicalRequestState::GetZoomRatioPhysicalCameraInfo(
366     const HalCameraMetadata* logical_chars,
367     const PhysicalDeviceMap* physical_devices) {
368   std::vector<ZoomRatioPhysicalCameraInfo> zoom_ratio_physical_camera_info;
369   if ((logical_chars == nullptr) || (physical_devices == nullptr)) {
370     return zoom_ratio_physical_camera_info;
371   }
372 
373   // Get the logical camera's focal length and sensor size
374   camera_metadata_ro_entry_t entry;
375   auto ret =
376       logical_chars->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
377   if ((ret != OK) || (entry.count == 0)) {
378     return zoom_ratio_physical_camera_info;
379   }
380   float logical_focal_length = entry.data.f[0];
381   ret = logical_chars->Get(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, &entry);
382   if ((ret != OK) || (entry.count == 0)) {
383     return zoom_ratio_physical_camera_info;
384   }
385   float logical_sensor_width = entry.data.f[0];
386 
387   // Derive the zoom ratio boundary values for each physical camera id, based on
388   // focal lengths and camera sensor physical size.
389   for (const auto& physical_device : *physical_devices) {
390     ret = physical_device.second.second->Get(
391         ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
392     if ((ret == OK) && (entry.count > 0)) {
393       float focal_length = entry.data.f[0];
394       ret = physical_device.second.second->Get(
395           ANDROID_SENSOR_INFO_PHYSICAL_SIZE, &entry);
396       if ((ret == OK) && (entry.count > 0)) {
397         float sensor_width = entry.data.f[0];
398         ret = physical_device.second.second->Get(
399             ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &entry);
400         if ((ret == OK) && (entry.count > 0)) {
401           float max_digital_zoom = entry.data.f[0];
402           // focal length of ultrawide lens
403           float min_zoom_ratio = focal_length * logical_sensor_width /
404                                  (logical_focal_length * sensor_width);
405           float max_zoom_ratio = max_digital_zoom * min_zoom_ratio;
406           zoom_ratio_physical_camera_info.push_back(
407               {focal_length, min_zoom_ratio, max_zoom_ratio,
408                physical_device.first});
409         }
410       }
411     }
412   }
413 
414   // Sort the mapping by ascending focal length
415   std::sort(zoom_ratio_physical_camera_info.begin(),
416             zoom_ratio_physical_camera_info.end(),
417             [](const ZoomRatioPhysicalCameraInfo& a,
418                const ZoomRatioPhysicalCameraInfo& b) {
419               return a.focal_length < b.focal_length;
420             });
421 
422   // Modify the zoom ratio range for each focal length so that they don't
423   // overlap
424   for (size_t i = 0; i < zoom_ratio_physical_camera_info.size() - 1; i++) {
425     auto& current = zoom_ratio_physical_camera_info[i];
426     auto& next = zoom_ratio_physical_camera_info[i + 1];
427     if (current.max_zoom_ratio > next.min_zoom_ratio) {
428       current.max_zoom_ratio = next.min_zoom_ratio;
429     }
430   }
431 
432   return zoom_ratio_physical_camera_info;
433 }
434 
435 }  // namespace android
436