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_NDEBUG 0
18 #include <cstdint>
19 #define LOG_TAG "GCH_Utils"
20 
21 #include <cutils/properties.h>
22 #include <dirent.h>
23 #include <dlfcn.h>
24 #include <hardware/gralloc.h>
25 #include <sys/stat.h>
26 
27 #include "utils.h"
28 #include "vendor_tag_defs.h"
29 
30 namespace android {
31 namespace google_camera_hal {
32 namespace utils {
33 
34 constexpr char kRealtimeThreadSetProp[] =
35     "persist.vendor.camera.realtimethread";
36 
37 constexpr uint32_t kMinSupportedSoftwareDenoiseDimension = 1000;
38 
IsDepthStream(const Stream & stream)39 bool IsDepthStream(const Stream& stream) {
40   if (stream.stream_type == StreamType::kOutput &&
41       stream.data_space == HAL_DATASPACE_DEPTH &&
42       stream.format == HAL_PIXEL_FORMAT_Y16) {
43     return true;
44   }
45 
46   return false;
47 }
48 
IsPreviewStream(const Stream & stream)49 bool IsPreviewStream(const Stream& stream) {
50   if (stream.stream_type == StreamType::kOutput &&
51       stream.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
52       ((stream.usage & GRALLOC_USAGE_HW_COMPOSER) == GRALLOC_USAGE_HW_COMPOSER ||
53        (stream.usage & GRALLOC_USAGE_HW_TEXTURE) == GRALLOC_USAGE_HW_TEXTURE)) {
54     return true;
55   }
56 
57   return false;
58 }
59 
IsJPEGSnapshotStream(const Stream & stream)60 bool IsJPEGSnapshotStream(const Stream& stream) {
61   if (stream.stream_type == StreamType::kOutput &&
62       stream.format == HAL_PIXEL_FORMAT_BLOB &&
63       (stream.data_space == HAL_DATASPACE_JFIF ||
64        stream.data_space == HAL_DATASPACE_V0_JFIF)) {
65     return true;
66   }
67 
68   return false;
69 }
70 
IsOutputZslStream(const Stream & stream)71 bool IsOutputZslStream(const Stream& stream) {
72   if (stream.stream_type == StreamType::kOutput &&
73       (stream.usage & GRALLOC_USAGE_HW_CAMERA_ZSL) ==
74           GRALLOC_USAGE_HW_CAMERA_ZSL) {
75     return true;
76   }
77 
78   return false;
79 }
80 
IsVideoStream(const Stream & stream)81 bool IsVideoStream(const Stream& stream) {
82   if (stream.stream_type == StreamType::kOutput &&
83       (stream.usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) != 0) {
84     return true;
85   }
86 
87   return false;
88 }
89 
IsRawStream(const Stream & stream)90 bool IsRawStream(const Stream& stream) {
91   if (stream.stream_type == StreamType::kOutput &&
92       (stream.format == HAL_PIXEL_FORMAT_RAW10 ||
93        stream.format == HAL_PIXEL_FORMAT_RAW16 ||
94        stream.format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
95     return true;
96   }
97 
98   return false;
99 }
100 
IsInputRawStream(const Stream & stream)101 bool IsInputRawStream(const Stream& stream) {
102   if (stream.stream_type == StreamType::kInput &&
103       (stream.format == HAL_PIXEL_FORMAT_RAW10 ||
104        stream.format == HAL_PIXEL_FORMAT_RAW16 ||
105        stream.format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
106     return true;
107   }
108 
109   return false;
110 }
111 
IsArbitraryDataSpaceRawStream(const Stream & stream)112 bool IsArbitraryDataSpaceRawStream(const Stream& stream) {
113   return IsRawStream(stream) && (stream.data_space == HAL_DATASPACE_ARBITRARY);
114 }
115 
IsYUVSnapshotStream(const Stream & stream)116 bool IsYUVSnapshotStream(const Stream& stream) {
117   if (stream.stream_type == StreamType::kOutput &&
118       stream.format == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
119       !IsVideoStream(stream) && !IsPreviewStream(stream)) {
120     return true;
121   }
122 
123   return false;
124 }
125 
IsSoftwareDenoiseEligibleSnapshotStream(const Stream & stream)126 bool IsSoftwareDenoiseEligibleSnapshotStream(const Stream& stream) {
127   if (utils::IsYUVSnapshotStream(stream) ||
128       utils::IsJPEGSnapshotStream(stream)) {
129     return stream.width >= kMinSupportedSoftwareDenoiseDimension ||
130            stream.height >= kMinSupportedSoftwareDenoiseDimension;
131   }
132   return false;
133 }
134 
GetSensorPhysicalSize(const HalCameraMetadata * characteristics,float * width,float * height)135 status_t GetSensorPhysicalSize(const HalCameraMetadata* characteristics,
136                                float* width, float* height) {
137   if (characteristics == nullptr || width == nullptr || height == nullptr) {
138     ALOGE("%s: characteristics or width/height is nullptr", __FUNCTION__);
139     return BAD_VALUE;
140   }
141 
142   camera_metadata_ro_entry entry;
143   status_t res = characteristics->Get(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, &entry);
144   if (res != OK || entry.count != 2) {
145     ALOGE(
146         "%s: Getting ANDROID_SENSOR_INFO_PHYSICAL_SIZE failed: %s(%d) count: "
147         "%zu",
148         __FUNCTION__, strerror(-res), res, entry.count);
149     return res;
150   }
151 
152   *width = entry.data.f[0];
153   *height = entry.data.f[1];
154   return OK;
155 }
156 
HasCapability(const HalCameraMetadata * metadata,uint8_t capability)157 bool HasCapability(const HalCameraMetadata* metadata, uint8_t capability) {
158   if (metadata == nullptr) {
159     return false;
160   }
161 
162   camera_metadata_ro_entry_t entry;
163   auto ret = metadata->Get(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
164   if (ret != OK) {
165     return false;
166   }
167   for (size_t i = 0; i < entry.count; i++) {
168     if (entry.data.u8[i] == capability) {
169       return true;
170     }
171   }
172   return false;
173 }
174 
GetSensorActiveArraySize(const HalCameraMetadata * characteristics,Rect * active_array,bool maximum_resolution)175 status_t GetSensorActiveArraySize(const HalCameraMetadata* characteristics,
176                                   Rect* active_array, bool maximum_resolution) {
177   if (characteristics == nullptr || active_array == nullptr) {
178     ALOGE("%s: characteristics or active_array is nullptr", __FUNCTION__);
179     return BAD_VALUE;
180   }
181   uint32_t active_array_tag =
182       maximum_resolution
183           ? ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
184           : ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE;
185   camera_metadata_ro_entry entry;
186   status_t res = characteristics->Get(active_array_tag, &entry);
187   if (res != OK || entry.count != 4) {
188     ALOGE(
189         "%s: Getting ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE failed: %s(%d) "
190         "count: %zu max resolution ? %s",
191         __FUNCTION__, strerror(-res), res, entry.count,
192         maximum_resolution ? "true" : "false");
193     return res;
194   }
195 
196   active_array->left = entry.data.i32[0];
197   active_array->top = entry.data.i32[1];
198   active_array->right = entry.data.i32[0] + entry.data.i32[2] - 1;
199   active_array->bottom = entry.data.i32[1] + entry.data.i32[3] - 1;
200 
201   return OK;
202 }
203 
GetZoomRatioRange(const HalCameraMetadata * characteristics,ZoomRatioRange * zoom_ratio_range)204 status_t GetZoomRatioRange(const HalCameraMetadata* characteristics,
205                            ZoomRatioRange* zoom_ratio_range) {
206   if (characteristics == nullptr || zoom_ratio_range == nullptr) {
207     ALOGE("%s: characteristics or zoom_ratio_range is nullptr", __FUNCTION__);
208     return BAD_VALUE;
209   }
210 
211   camera_metadata_ro_entry entry;
212   status_t res = characteristics->Get(ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
213   if (res != OK || entry.count != 2) {
214     ALOGE(
215         "%s: Getting ANDROID_CONTROL_ZOOM_RATIO_RANGE failed: %s(%d) "
216         "count: %zu",
217         __FUNCTION__, strerror(-res), res, entry.count);
218     return res;
219   }
220 
221   zoom_ratio_range->min = entry.data.f[0];
222   zoom_ratio_range->max = entry.data.f[1];
223 
224   return OK;
225 }
226 
GetSensorPixelArraySize(const HalCameraMetadata * characteristics,Dimension * pixel_array)227 status_t GetSensorPixelArraySize(const HalCameraMetadata* characteristics,
228                                  Dimension* pixel_array) {
229   if (characteristics == nullptr || pixel_array == nullptr) {
230     ALOGE("%s: characteristics or pixel_array is nullptr", __FUNCTION__);
231     return BAD_VALUE;
232   }
233 
234   camera_metadata_ro_entry entry;
235   status_t res =
236       characteristics->Get(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, &entry);
237   if (res != OK || entry.count != 2) {
238     ALOGE(
239         "%s: Getting ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE failed: %s(%d) "
240         "count: %zu",
241         __FUNCTION__, strerror(-res), res, entry.count);
242     return res;
243   }
244 
245   pixel_array->width = entry.data.i32[0];
246   pixel_array->height = entry.data.i32[1];
247 
248   return OK;
249 }
250 
GetFocalLength(const HalCameraMetadata * characteristics,float * focal_length)251 status_t GetFocalLength(const HalCameraMetadata* characteristics,
252                         float* focal_length) {
253   if (characteristics == nullptr || focal_length == nullptr) {
254     ALOGE("%s: characteristics or focal_length is nullptr", __FUNCTION__);
255     return BAD_VALUE;
256   }
257 
258   camera_metadata_ro_entry entry;
259   status_t res =
260       characteristics->Get(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, &entry);
261   if (res != OK || entry.count != 1) {
262     ALOGE(
263         "%s: Getting ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS failed: %s(%d) "
264         "count: %zu",
265         __FUNCTION__, strerror(-res), res, entry.count);
266     return res;
267   }
268 
269   *focal_length = entry.data.f[0];
270 
271   return OK;
272 }
273 
IsLiveSnapshotConfigured(const StreamConfiguration & stream_config)274 bool IsLiveSnapshotConfigured(const StreamConfiguration& stream_config) {
275   bool has_video_stream = false;
276   bool has_jpeg_stream = false;
277   for (auto stream : stream_config.streams) {
278     if (utils::IsVideoStream(stream)) {
279       has_video_stream = true;
280     } else if (utils::IsJPEGSnapshotStream(stream)) {
281       has_jpeg_stream = true;
282     }
283   }
284 
285   return (has_video_stream & has_jpeg_stream);
286 }
287 
IsHighSpeedModeFpsCompatible(StreamConfigurationMode mode,const HalCameraMetadata * old_session,const HalCameraMetadata * new_session)288 bool IsHighSpeedModeFpsCompatible(StreamConfigurationMode mode,
289                                   const HalCameraMetadata* old_session,
290                                   const HalCameraMetadata* new_session) {
291   if (mode != StreamConfigurationMode::kConstrainedHighSpeed) {
292     return false;
293   }
294 
295   camera_metadata_ro_entry_t ae_target_fps_entry;
296   int32_t old_max_fps = 0;
297   int32_t new_max_fps = 0;
298 
299   if (old_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
300                        &ae_target_fps_entry) == OK) {
301     old_max_fps = ae_target_fps_entry.data.i32[1];
302   }
303   if (new_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
304                        &ae_target_fps_entry) == OK) {
305     new_max_fps = ae_target_fps_entry.data.i32[1];
306   }
307 
308   ALOGI("%s: HFR: old max fps: %d, new max fps: %d", __FUNCTION__, old_max_fps,
309         new_max_fps);
310 
311   if (new_max_fps == old_max_fps) {
312     return true;
313   }
314 
315   return false;
316 }
317 
IsSessionParameterCompatible(const HalCameraMetadata * old_session,const HalCameraMetadata * new_session)318 bool IsSessionParameterCompatible(const HalCameraMetadata* old_session,
319                                   const HalCameraMetadata* new_session) {
320   auto old_session_count = old_session->GetEntryCount();
321   auto new_session_count = new_session->GetEntryCount();
322   if (old_session_count == 0 || new_session_count == 0) {
323     ALOGI("No session paramerter, old:%zu, new:%zu", old_session_count,
324           new_session_count);
325     if (new_session_count != 0) {
326       camera_metadata_ro_entry_t entry;
327       if (new_session->Get(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &entry) == OK) {
328         int32_t max_fps = entry.data.i32[1];
329         if (max_fps > 30) {
330           ALOGI("new session paramerter max fps:%d", max_fps);
331           return false;
332         }
333       }
334     }
335     return true;
336   }
337 
338   if (old_session_count != new_session_count) {
339     ALOGI(
340         "Entry count has changed from %zu "
341         "to %zu",
342         old_session_count, new_session_count);
343     return false;
344   }
345 
346   for (size_t entry_index = 0; entry_index < new_session_count; entry_index++) {
347     camera_metadata_ro_entry_t new_entry;
348     // Get the medata from new session first
349     if (new_session->GetByIndex(&new_entry, entry_index) != OK) {
350       ALOGW("Unable to get new session entry for index %zu", entry_index);
351       return false;
352     }
353 
354     // Get the same tag from old session
355     camera_metadata_ro_entry_t old_entry;
356     if (old_session->Get(new_entry.tag, &old_entry) != OK) {
357       ALOGW("Unable to get old session tag 0x%x", new_entry.tag);
358       return false;
359     }
360 
361     if (new_entry.count != old_entry.count) {
362       ALOGI(
363           "New entry count %zu doesn't "
364           "match old entry count %zu",
365           new_entry.count, old_entry.count);
366       return false;
367     }
368 
369     if (new_entry.tag == ANDROID_CONTROL_AE_TARGET_FPS_RANGE) {
370       // Stream reconfiguration is not needed in case the upper
371       // framerate range remains unchanged. Any other modification
372       // to the session parameters must trigger new stream
373       // configuration.
374       int32_t old_min_fps = old_entry.data.i32[0];
375       int32_t old_max_fps = old_entry.data.i32[1];
376       int32_t new_min_fps = new_entry.data.i32[0];
377       int32_t new_max_fps = new_entry.data.i32[1];
378       if (old_max_fps == new_max_fps) {
379         ALOGI("%s: Ignore fps (%d, %d) to (%d, %d)", __FUNCTION__, old_min_fps,
380               old_max_fps, new_min_fps, new_max_fps);
381         continue;
382       }
383 
384       return false;
385     } else {
386       // Same type and count, compare values
387       size_t type_size = camera_metadata_type_size[old_entry.type];
388       size_t entry_size = type_size * old_entry.count;
389       int32_t cmp = memcmp(new_entry.data.u8, old_entry.data.u8, entry_size);
390       if (cmp != 0) {
391         ALOGI("Session parameter value has changed");
392         return false;
393       }
394     }
395   }
396 
397   return true;
398 }
399 
ConvertZoomRatio(const float zoom_ratio,const Dimension & active_array_dimension,int32_t * left,int32_t * top,int32_t * width,int32_t * height)400 void ConvertZoomRatio(const float zoom_ratio,
401                       const Dimension& active_array_dimension, int32_t* left,
402                       int32_t* top, int32_t* width, int32_t* height) {
403   if (left == nullptr || top == nullptr || width == nullptr ||
404       height == nullptr) {
405     ALOGE("%s, invalid params", __FUNCTION__);
406     return;
407   }
408 
409   assert(zoom_ratio != 0);
410   *left = std::round(*left / zoom_ratio + 0.5f * active_array_dimension.width *
411                                               (1.0f - 1.0f / zoom_ratio));
412   *top = std::round(*top / zoom_ratio + 0.5f * active_array_dimension.height *
413                                             (1.0f - 1.0f / zoom_ratio));
414   *width = std::round(*width / zoom_ratio);
415   *height = std::round(*height / zoom_ratio);
416 
417   if (zoom_ratio >= 1.0f) {
418     utils::ClampBoundary(active_array_dimension, left, top, width, height);
419   }
420 }
421 
SupportRealtimeThread()422 bool SupportRealtimeThread() {
423   static bool support_real_time = false;
424   static bool first_time = false;
425   if (first_time == false) {
426     first_time = true;
427     support_real_time = property_get_bool(kRealtimeThreadSetProp, false);
428   }
429 
430   return support_real_time;
431 }
432 
SetRealtimeThread(pthread_t thread)433 status_t SetRealtimeThread(pthread_t thread) {
434   struct sched_param param = {
435       .sched_priority = 1,
436   };
437   int32_t res =
438       pthread_setschedparam(thread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param);
439   if (res != 0) {
440     ALOGE("%s: Couldn't set SCHED_FIFO", __FUNCTION__);
441     return BAD_VALUE;
442   }
443 
444   return OK;
445 }
446 
UpdateThreadSched(pthread_t thread,int32_t policy,struct sched_param * param)447 status_t UpdateThreadSched(pthread_t thread, int32_t policy,
448                            struct sched_param* param) {
449   if (param == nullptr) {
450     ALOGE("%s: sched_param is nullptr", __FUNCTION__);
451     return BAD_VALUE;
452   }
453   int32_t res = pthread_setschedparam(thread, policy, param);
454   if (res != 0) {
455     ALOGE("%s: Couldn't set schedparam", __FUNCTION__);
456     return BAD_VALUE;
457   }
458 
459   return OK;
460 }
461 
462 // Returns an array of regular files under dir_path.
FindLibraryPaths(const char * dir_path)463 std::vector<std::string> FindLibraryPaths(const char* dir_path) {
464   std::vector<std::string> libs;
465 
466   errno = 0;
467   DIR* dir = opendir(dir_path);
468   if (!dir) {
469     ALOGD("%s: Unable to open directory %s (%s)", __FUNCTION__, dir_path,
470           strerror(errno));
471     return libs;
472   }
473 
474   struct dirent* entry = nullptr;
475   while ((entry = readdir(dir)) != nullptr) {
476     std::string lib_path(dir_path);
477     lib_path += entry->d_name;
478     struct stat st;
479     if (stat(lib_path.c_str(), &st) == 0) {
480       if (S_ISREG(st.st_mode)) {
481         libs.push_back(lib_path);
482       }
483     }
484   }
485 
486   return libs;
487 }
488 
489 }  // namespace utils
490 }  // namespace google_camera_hal
491 }  // namespace android
492