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