blob: 649bf43f49f5b2c49c5c33bb0492a87fdfaf3439 [file] [log] [blame]
Avichal Rakeshe1857f82022-06-08 17:47:23 -07001/*
2 * Copyright (C) 2022 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 "ExtCamDev"
18// #define LOG_NDEBUG 0
19#include <log/log.h>
20
21#include "ExternalCameraDevice.h"
22
23#include <aidl/android/hardware/camera/common/Status.h>
24#include <convert.h>
25#include <linux/videodev2.h>
26#include <regex>
27#include <set>
28
29namespace android {
30namespace hardware {
31namespace camera {
32namespace device {
33namespace implementation {
34
35using ::aidl::android::hardware::camera::common::Status;
36
37namespace {
38// Only support MJPEG for now as it seems to be the one supports higher fps
39// Other formats to consider in the future:
40// * V4L2_PIX_FMT_YVU420 (== YV12)
41// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
42const std::array<uint32_t, /*size*/ 2> kSupportedFourCCs{
43 {V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_Z16}}; // double braces required in C++11
44
45constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
46constexpr int OPEN_RETRY_SLEEP_US = 100'000; // 100ms * MAX_RETRY = 0.5 seconds
47
48const std::regex kDevicePathRE("/dev/video([0-9]+)");
49} // namespace
50
51std::string ExternalCameraDevice::kDeviceVersion = "1.1";
52
53ExternalCameraDevice::ExternalCameraDevice(const std::string& devicePath,
54 const ExternalCameraConfig& config)
55 : mCameraId("-1"), mDevicePath(devicePath), mCfg(config) {
56 std::smatch sm;
57 if (std::regex_match(mDevicePath, sm, kDevicePathRE)) {
58 mCameraId = std::to_string(mCfg.cameraIdOffset + std::stoi(sm[1]));
59 } else {
60 ALOGE("%s: device path match failed for %s", __FUNCTION__, mDevicePath.c_str());
61 }
62}
63
64ExternalCameraDevice::~ExternalCameraDevice() {}
65
66ndk::ScopedAStatus ExternalCameraDevice::getCameraCharacteristics(CameraMetadata* _aidl_return) {
67 Mutex::Autolock _l(mLock);
68 if (_aidl_return == nullptr) {
69 return fromStatus(Status::ILLEGAL_ARGUMENT);
70 }
71
72 if (isInitFailedLocked()) {
73 return fromStatus(Status::INTERNAL_ERROR);
74 }
75
76 const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
77 convertToAidl(rawMetadata, _aidl_return);
78 mCameraCharacteristics.unlock(rawMetadata);
79 return fromStatus(Status::OK);
80}
81
82ndk::ScopedAStatus ExternalCameraDevice::getPhysicalCameraCharacteristics(const std::string&,
83 CameraMetadata*) {
84 ALOGE("%s: Physical camera functions are not supported for external cameras.", __FUNCTION__);
85 return fromStatus(Status::ILLEGAL_ARGUMENT);
86}
87
88ndk::ScopedAStatus ExternalCameraDevice::getResourceCost(CameraResourceCost* _aidl_return) {
89 if (_aidl_return == nullptr) {
90 return fromStatus(Status::ILLEGAL_ARGUMENT);
91 }
92
93 _aidl_return->resourceCost = 100;
94 return fromStatus(Status::OK);
95}
96
97ndk::ScopedAStatus ExternalCameraDevice::isStreamCombinationSupported(
98 const StreamConfiguration& in_streams, bool* _aidl_return) {
99 if (isInitFailed()) {
100 ALOGE("%s: camera %s. camera init failed!", __FUNCTION__, mCameraId.c_str());
101 return fromStatus(Status::INTERNAL_ERROR);
102 }
103 Status s = ExternalCameraDeviceSession::isStreamCombinationSupported(in_streams,
104 mSupportedFormats, mCfg);
105 *_aidl_return = s == Status::OK;
106 return fromStatus(Status::OK);
107}
108
109ndk::ScopedAStatus ExternalCameraDevice::open(
110 const std::shared_ptr<ICameraDeviceCallback>& in_callback,
111 std::shared_ptr<ICameraDeviceSession>* _aidl_return) {
112 if (_aidl_return == nullptr) {
113 ALOGE("%s: cannot open camera %s. return session ptr is null!", __FUNCTION__,
114 mCameraId.c_str());
115 return fromStatus(Status::ILLEGAL_ARGUMENT);
116 }
117
118 Mutex::Autolock _l(mLock);
119 if (isInitFailedLocked()) {
120 ALOGE("%s: cannot open camera %s. camera init failed!", __FUNCTION__, mCameraId.c_str());
121 return fromStatus(Status::INTERNAL_ERROR);
122 }
123
124 std::shared_ptr<ExternalCameraDeviceSession> session;
125 ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
126 session = mSession.lock();
127
128 if (session != nullptr && !session->isClosed()) {
129 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
130 return fromStatus(Status::CAMERA_IN_USE);
131 }
132
133 int numAttempt = 0;
134 unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
135 while (fd.get() < 0 && numAttempt < MAX_RETRY) {
136 // Previous retry attempts failed. Retry opening the device at most MAX_RETRY times
137 ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again", __FUNCTION__,
138 mDevicePath.c_str());
139 usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
140 fd.reset(::open(mDevicePath.c_str(), O_RDWR));
141 numAttempt++;
142 }
143
144 if (fd.get() < 0) {
145 ALOGE("%s: v4l2 device open %s failed: %s", __FUNCTION__, mDevicePath.c_str(),
146 strerror(errno));
147 return fromStatus(Status::INTERNAL_ERROR);
148 }
149
150 session = createSession(in_callback, mCfg, mSupportedFormats, mCroppingType,
151 mCameraCharacteristics, mCameraId, std::move(fd));
152 if (session == nullptr) {
153 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
154 return fromStatus(Status::INTERNAL_ERROR);
155 }
156
157 if (session->isInitFailed()) {
158 ALOGE("%s: camera device session init failed", __FUNCTION__);
159 return fromStatus(Status::INTERNAL_ERROR);
160 }
161
162 mSession = session;
163 *_aidl_return = session;
164 return fromStatus(Status::OK);
165}
166
167ndk::ScopedAStatus ExternalCameraDevice::openInjectionSession(
168 const std::shared_ptr<ICameraDeviceCallback>&, std::shared_ptr<ICameraInjectionSession>*) {
169 return fromStatus(Status::OPERATION_NOT_SUPPORTED);
170}
171
172ndk::ScopedAStatus ExternalCameraDevice::setTorchMode(bool) {
173 return fromStatus(Status::OPERATION_NOT_SUPPORTED);
174}
175
176ndk::ScopedAStatus ExternalCameraDevice::turnOnTorchWithStrengthLevel(int32_t) {
177 return fromStatus(Status::OPERATION_NOT_SUPPORTED);
178}
179
180ndk::ScopedAStatus ExternalCameraDevice::getTorchStrengthLevel(int32_t*) {
181 return fromStatus(Status::OPERATION_NOT_SUPPORTED);
182}
183
184std::shared_ptr<ExternalCameraDeviceSession> ExternalCameraDevice::createSession(
185 const std::shared_ptr<ICameraDeviceCallback>& cb, const ExternalCameraConfig& cfg,
186 const std::vector<SupportedV4L2Format>& sortedFormats, const CroppingType& croppingType,
187 const common::V1_0::helper::CameraMetadata& chars, const std::string& cameraId,
188 unique_fd v4l2Fd) {
189 return ndk::SharedRefBase::make<ExternalCameraDeviceSession>(
190 cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd));
191}
192
193bool ExternalCameraDevice::isInitFailed() {
194 Mutex::Autolock _l(mLock);
195 return isInitFailedLocked();
196}
197
198bool ExternalCameraDevice::isInitFailedLocked() {
199 if (!mInitialized) {
200 status_t ret = initCameraCharacteristics();
201 if (ret != OK) {
202 ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
203 mInitFailed = true;
204 }
205 mInitialized = true;
206 }
207 return mInitFailed;
208}
209
210void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
211 std::vector<SupportedV4L2Format> horizontalFmts =
212 getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.depthFpsLimits,
213 mCfg.minStreamSize, mCfg.depthEnabled);
214 std::vector<SupportedV4L2Format> verticalFmts =
215 getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.depthFpsLimits,
216 mCfg.minStreamSize, mCfg.depthEnabled);
217
218 size_t horiSize = horizontalFmts.size();
219 size_t vertSize = verticalFmts.size();
220
221 if (horiSize == 0 && vertSize == 0) {
222 ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
223 return;
224 }
225
226 if (horiSize == 0) {
227 mSupportedFormats = verticalFmts;
228 mCroppingType = VERTICAL;
229 return;
230 } else if (vertSize == 0) {
231 mSupportedFormats = horizontalFmts;
232 mCroppingType = HORIZONTAL;
233 return;
234 }
235
236 const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
237 const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
238
239 // Try to keep the largest possible output size
240 // When they are the same or ambiguous, pick the one support more sizes
241 if (maxHoriSize.width == maxVertSize.width && maxHoriSize.height == maxVertSize.height) {
242 if (horiSize > vertSize) {
243 mSupportedFormats = horizontalFmts;
244 mCroppingType = HORIZONTAL;
245 } else {
246 mSupportedFormats = verticalFmts;
247 mCroppingType = VERTICAL;
248 }
249 } else if (maxHoriSize.width >= maxVertSize.width && maxHoriSize.height >= maxVertSize.height) {
250 mSupportedFormats = horizontalFmts;
251 mCroppingType = HORIZONTAL;
252 } else if (maxHoriSize.width <= maxVertSize.width && maxHoriSize.height <= maxVertSize.height) {
253 mSupportedFormats = verticalFmts;
254 mCroppingType = VERTICAL;
255 } else {
256 if (horiSize > vertSize) {
257 mSupportedFormats = horizontalFmts;
258 mCroppingType = HORIZONTAL;
259 } else {
260 mSupportedFormats = verticalFmts;
261 mCroppingType = VERTICAL;
262 }
263 }
264}
265
266status_t ExternalCameraDevice::initCameraCharacteristics() {
267 if (!mCameraCharacteristics.isEmpty()) {
268 // Camera Characteristics previously initialized. Skip.
269 return OK;
270 }
271
272 // init camera characteristics
273 unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
274 if (fd.get() < 0) {
275 ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mDevicePath.c_str());
276 return DEAD_OBJECT;
277 }
278
279 status_t ret;
280 ret = initDefaultCharsKeys(&mCameraCharacteristics);
281 if (ret != OK) {
282 ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
283 mCameraCharacteristics.clear();
284 return ret;
285 }
286
287 ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
288 if (ret != OK) {
289 ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
290 mCameraCharacteristics.clear();
291 return ret;
292 }
293
294 ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
295 if (ret != OK) {
296 ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
297 mCameraCharacteristics.clear();
298 return ret;
299 }
300
301 ret = initAvailableCapabilities(&mCameraCharacteristics);
302 if (ret != OK) {
303 ALOGE("%s: init available capabilities key failed: errorno %d", __FUNCTION__, ret);
304 mCameraCharacteristics.clear();
305 return ret;
306 }
307
308 return OK;
309}
310
311#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
312#define UPDATE(tag, data, size) \
313 do { \
314 if (metadata->update((tag), (data), (size))) { \
315 ALOGE("Update " #tag " failed!"); \
316 return -EINVAL; \
317 } \
318 } while (0)
319
320status_t ExternalCameraDevice::initAvailableCapabilities(
321 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
322 if (mSupportedFormats.empty()) {
323 ALOGE("%s: Supported formats list is empty", __FUNCTION__);
324 return UNKNOWN_ERROR;
325 }
326
327 bool hasDepth = false;
328 bool hasColor = false;
329 for (const auto& fmt : mSupportedFormats) {
330 switch (fmt.fourcc) {
331 case V4L2_PIX_FMT_Z16:
332 hasDepth = true;
333 break;
334 case V4L2_PIX_FMT_MJPEG:
335 hasColor = true;
336 break;
337 default:
338 ALOGW("%s: Unsupported format found", __FUNCTION__);
339 }
340 }
341
342 std::vector<uint8_t> availableCapabilities;
343 if (hasDepth) {
344 availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT);
345 }
346 if (hasColor) {
347 availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
348 }
349 if (!availableCapabilities.empty()) {
350 UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities.data(),
351 availableCapabilities.size());
352 }
353
354 return OK;
355}
356
357status_t ExternalCameraDevice::initDefaultCharsKeys(
358 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
359 const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
360 UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
361
362 // android.colorCorrection
363 const uint8_t availableAberrationModes[] = {ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
364 UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, availableAberrationModes,
365 ARRAY_SIZE(availableAberrationModes));
366
367 // android.control
368 const uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
369 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, &antibandingMode, 1);
370
371 const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
372 UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions, ARRAY_SIZE(controlMaxRegions));
373
374 const uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
375 UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, &videoStabilizationMode, 1);
376
377 const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
378 UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
379
380 const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
381 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
382
383 const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
384 UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
385
386 const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF, ANDROID_CONTROL_MODE_AUTO};
387 UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
388 ARRAY_SIZE(controlAvailableModes));
389
390 // android.edge
391 const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
392 UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
393
394 // android.flash
395 const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
396 UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
397
398 // android.hotPixel
399 const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
400 UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
401
Sangheumaa9d8dc2023-12-20 16:48:03 +0900402 // android.info
403 const uint8_t bufMgrVer = ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5;
404 UPDATE(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &bufMgrVer, 1);
405
Avichal Rakeshe1857f82022-06-08 17:47:23 -0700406 // android.jpeg
407 const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 176, 144, 240, 144, 256,
408 144, 240, 160, 256, 154, 240, 180};
409 UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
410 ARRAY_SIZE(jpegAvailableThumbnailSizes));
411
412 const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
413 UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
414
415 // android.lens
416 const uint8_t focusDistanceCalibration =
417 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
418 UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
419
420 const uint8_t opticalStabilizationMode = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
421 UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION, &opticalStabilizationMode, 1);
422
423 const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
424 UPDATE(ANDROID_LENS_FACING, &facing, 1);
425
426 // android.noiseReduction
427 const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
428 UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, &noiseReductionMode, 1);
429 UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
430
431 const int32_t partialResultCount = 1;
432 UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
433
434 // This means pipeline latency of X frame intervals. The maximum number is 4.
435 const uint8_t requestPipelineMaxDepth = 4;
436 UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
437
438 // Three numbers represent the maximum numbers of different types of output
439 // streams simultaneously. The types are raw sensor, processed (but not
440 // stalling), and processed (but stalling). For usb limited mode, raw sensor
441 // is not supported. Stalling stream is JPEG. Non-stalling streams are
442 // YUV_420_888 or YV12.
443 const int32_t requestMaxNumOutputStreams[] = {
444 /*RAW*/ 0,
445 /*Processed*/ ExternalCameraDeviceSession::kMaxProcessedStream,
446 /*Stall*/ ExternalCameraDeviceSession::kMaxStallStream};
447 UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
448 ARRAY_SIZE(requestMaxNumOutputStreams));
449
450 // Limited mode doesn't support reprocessing.
451 const int32_t requestMaxNumInputStreams = 0;
452 UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams, 1);
453
454 // android.scaler
455 // TODO: b/72263447 V4L2_CID_ZOOM_*
456 const float scalerAvailableMaxDigitalZoom[] = {1};
457 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, scalerAvailableMaxDigitalZoom,
458 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
459
460 const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
461 UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
462
463 const int32_t testPatternModes[] = {ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
464 ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR};
465 UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
466 ARRAY_SIZE(testPatternModes));
467
468 const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
469 UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
470
471 // Orientation is a bit odd for external camera, but consider it as the orientation
472 // between the external camera sensor (which is usually landscape) and the device's
473 // natural display orientation. For devices with natural landscape display (ex: tablet/TV), the
474 // orientation should be 0. For devices with natural portrait display (phone), the orientation
475 // should be 270.
476 const int32_t orientation = mCfg.orientation;
477 UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
478
479 // android.shading
480 const uint8_t availableMode = ANDROID_SHADING_MODE_OFF;
481 UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availableMode, 1);
482
483 // android.statistics
484 const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
485 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode, 1);
486
487 const int32_t maxFaceCount = 0;
488 UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
489
490 const uint8_t availableHotpixelMode = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
491 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, &availableHotpixelMode, 1);
492
493 const uint8_t lensShadingMapMode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
494 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, &lensShadingMapMode, 1);
495
496 // android.sync
497 const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
498 UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
499
500 /* Other sensor/RAW related keys:
501 * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
502 * android.sensor.info.physicalSize -> not available
503 * android.sensor.info.whiteLevel -> not available/not needed
504 * android.sensor.info.lensShadingApplied -> not needed
505 * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
506 * android.sensor.blackLevelPattern -> not available/not needed
507 */
508
509 const int32_t availableRequestKeys[] = {ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
510 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
511 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
512 ANDROID_CONTROL_AE_LOCK,
513 ANDROID_CONTROL_AE_MODE,
514 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
515 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
516 ANDROID_CONTROL_AF_MODE,
517 ANDROID_CONTROL_AF_TRIGGER,
518 ANDROID_CONTROL_AWB_LOCK,
519 ANDROID_CONTROL_AWB_MODE,
520 ANDROID_CONTROL_CAPTURE_INTENT,
521 ANDROID_CONTROL_EFFECT_MODE,
522 ANDROID_CONTROL_MODE,
523 ANDROID_CONTROL_SCENE_MODE,
524 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
525 ANDROID_FLASH_MODE,
526 ANDROID_JPEG_ORIENTATION,
527 ANDROID_JPEG_QUALITY,
528 ANDROID_JPEG_THUMBNAIL_QUALITY,
529 ANDROID_JPEG_THUMBNAIL_SIZE,
530 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
531 ANDROID_NOISE_REDUCTION_MODE,
532 ANDROID_SCALER_CROP_REGION,
533 ANDROID_SENSOR_TEST_PATTERN_MODE,
534 ANDROID_STATISTICS_FACE_DETECT_MODE,
535 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
536 UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
537 ARRAY_SIZE(availableRequestKeys));
538
539 const int32_t availableResultKeys[] = {ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
540 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
541 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
542 ANDROID_CONTROL_AE_LOCK,
543 ANDROID_CONTROL_AE_MODE,
544 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
545 ANDROID_CONTROL_AE_STATE,
546 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
547 ANDROID_CONTROL_AF_MODE,
548 ANDROID_CONTROL_AF_STATE,
549 ANDROID_CONTROL_AF_TRIGGER,
550 ANDROID_CONTROL_AWB_LOCK,
551 ANDROID_CONTROL_AWB_MODE,
552 ANDROID_CONTROL_AWB_STATE,
553 ANDROID_CONTROL_CAPTURE_INTENT,
554 ANDROID_CONTROL_EFFECT_MODE,
555 ANDROID_CONTROL_MODE,
556 ANDROID_CONTROL_SCENE_MODE,
557 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
558 ANDROID_FLASH_MODE,
559 ANDROID_FLASH_STATE,
560 ANDROID_JPEG_ORIENTATION,
561 ANDROID_JPEG_QUALITY,
562 ANDROID_JPEG_THUMBNAIL_QUALITY,
563 ANDROID_JPEG_THUMBNAIL_SIZE,
564 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
565 ANDROID_NOISE_REDUCTION_MODE,
566 ANDROID_REQUEST_PIPELINE_DEPTH,
567 ANDROID_SCALER_CROP_REGION,
568 ANDROID_SENSOR_TIMESTAMP,
569 ANDROID_STATISTICS_FACE_DETECT_MODE,
570 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
571 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
572 ANDROID_STATISTICS_SCENE_FLICKER};
573 UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
574 ARRAY_SIZE(availableResultKeys));
575
576 UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, AVAILABLE_CHARACTERISTICS_KEYS.data(),
577 AVAILABLE_CHARACTERISTICS_KEYS.size());
578
579 return OK;
580}
581
582status_t ExternalCameraDevice::initCameraControlsCharsKeys(
583 int, ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
584 // android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
585 // android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
586 // android.sensor.info.maxFrameDuration -> TBD
587 // android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
588 // android.lens.info.hyperfocalDistance
589 // android.lens.info.availableFocalLengths -> not available?
590
591 // android.control
592 // No AE compensation support for now.
593 // TODO: V4L2_CID_EXPOSURE_BIAS
594 const int32_t controlAeCompensationRange[] = {0, 0};
595 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
596 ARRAY_SIZE(controlAeCompensationRange));
597 const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
598 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
599 ARRAY_SIZE(controlAeCompensationStep));
600
601 // TODO: Check V4L2_CID_AUTO_FOCUS_*.
602 const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO, ANDROID_CONTROL_AF_MODE_OFF};
603 UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes, ARRAY_SIZE(afAvailableModes));
604
605 // TODO: V4L2_CID_SCENE_MODE
606 const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
607 UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
608
609 // TODO: V4L2_CID_3A_LOCK
610 const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
611 UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
612 const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
613 UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
614
615 // TODO: V4L2_CID_ZOOM_*
616 const float scalerAvailableMaxDigitalZoom[] = {1};
617 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, scalerAvailableMaxDigitalZoom,
618 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
619
620 return OK;
621}
622
623status_t ExternalCameraDevice::initOutputCharsKeys(
624 int fd, ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
625 initSupportedFormatsLocked(fd);
626 if (mSupportedFormats.empty()) {
627 ALOGE("%s: Init supported format list failed", __FUNCTION__);
628 return UNKNOWN_ERROR;
629 }
630
631 bool hasDepth = false;
632 bool hasColor = false;
633
634 // For V4L2_PIX_FMT_Z16
635 std::array<int, /*size*/ 1> halDepthFormats{{HAL_PIXEL_FORMAT_Y16}};
636 // For V4L2_PIX_FMT_MJPEG
637 std::array<int, /*size*/ 3> halFormats{{HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888,
638 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
639
640 for (const auto& supportedFormat : mSupportedFormats) {
641 switch (supportedFormat.fourcc) {
642 case V4L2_PIX_FMT_Z16:
643 hasDepth = true;
644 break;
645 case V4L2_PIX_FMT_MJPEG:
646 hasColor = true;
647 break;
648 default:
649 ALOGW("%s: format %c%c%c%c is not supported!", __FUNCTION__,
650 supportedFormat.fourcc & 0xFF, (supportedFormat.fourcc >> 8) & 0xFF,
651 (supportedFormat.fourcc >> 16) & 0xFF, (supportedFormat.fourcc >> 24) & 0xFF);
652 }
653 }
654
655 if (hasDepth) {
656 status_t ret = initOutputCharsKeysByFormat(
657 metadata, V4L2_PIX_FMT_Z16, halDepthFormats,
658 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
659 ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
660 ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
661 ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
662 if (ret != OK) {
663 ALOGE("%s: Unable to initialize depth format keys: %s", __FUNCTION__,
664 statusToString(ret).c_str());
665 return ret;
666 }
667 }
668 if (hasColor) {
669 status_t ret =
670 initOutputCharsKeysByFormat(metadata, V4L2_PIX_FMT_MJPEG, halFormats,
671 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
672 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
673 ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
674 ANDROID_SCALER_AVAILABLE_STALL_DURATIONS);
675 if (ret != OK) {
676 ALOGE("%s: Unable to initialize color format keys: %s", __FUNCTION__,
677 statusToString(ret).c_str());
678 return ret;
679 }
680 }
681
682 status_t ret = calculateMinFps(metadata);
683 if (ret != OK) {
684 ALOGE("%s: Unable to update fps metadata: %s", __FUNCTION__, statusToString(ret).c_str());
685 return ret;
686 }
687
688 SupportedV4L2Format maximumFormat{.width = 0, .height = 0};
689 for (const auto& supportedFormat : mSupportedFormats) {
690 if (supportedFormat.width >= maximumFormat.width &&
691 supportedFormat.height >= maximumFormat.height) {
692 maximumFormat = supportedFormat;
693 }
694 }
695 int32_t activeArraySize[] = {0, 0, static_cast<int32_t>(maximumFormat.width),
696 static_cast<int32_t>(maximumFormat.height)};
697 UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, activeArraySize,
698 ARRAY_SIZE(activeArraySize));
699 UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize, ARRAY_SIZE(activeArraySize));
700
701 int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
702 static_cast<int32_t>(maximumFormat.height)};
703 UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize, ARRAY_SIZE(pixelArraySize));
704 return OK;
705}
706
707template <size_t SIZE>
708status_t ExternalCameraDevice::initOutputCharsKeysByFormat(
709 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata,
710 uint32_t fourcc, const std::array<int, SIZE>& halFormats, int streamConfigTag,
711 int streamConfigurationKey, int minFrameDurationKey, int stallDurationKey) {
712 if (mSupportedFormats.empty()) {
713 ALOGE("%s: Init supported format list failed", __FUNCTION__);
714 return UNKNOWN_ERROR;
715 }
716
717 std::vector<int32_t> streamConfigurations;
718 std::vector<int64_t> minFrameDurations;
719 std::vector<int64_t> stallDurations;
720
721 for (const auto& supportedFormat : mSupportedFormats) {
722 if (supportedFormat.fourcc != fourcc) {
723 // Skip 4CCs not meant for the halFormats
724 continue;
725 }
726 for (const auto& format : halFormats) {
727 streamConfigurations.push_back(format);
728 streamConfigurations.push_back(supportedFormat.width);
729 streamConfigurations.push_back(supportedFormat.height);
730 streamConfigurations.push_back(streamConfigTag);
731 }
732
733 int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
734 for (const auto& fr : supportedFormat.frameRates) {
735 // 1000000000LL < (2^32 - 1) and
736 // fr.durationNumerator is uint32_t, so no overflow here
737 int64_t frameDuration = 1000000000LL * fr.durationNumerator / fr.durationDenominator;
738 if (frameDuration < minFrameDuration) {
739 minFrameDuration = frameDuration;
740 }
741 }
742
743 for (const auto& format : halFormats) {
744 minFrameDurations.push_back(format);
745 minFrameDurations.push_back(supportedFormat.width);
746 minFrameDurations.push_back(supportedFormat.height);
747 minFrameDurations.push_back(minFrameDuration);
748 }
749
750 // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
751 // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
752 // TODO: b/72261675. Maybe set this dynamically
753 for (const auto& format : halFormats) {
754 const int64_t NS_TO_SECOND = 1E9;
755 int64_t stall_duration = (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
756 stallDurations.push_back(format);
757 stallDurations.push_back(supportedFormat.width);
758 stallDurations.push_back(supportedFormat.height);
759 stallDurations.push_back(stall_duration);
760 }
761 }
762
763 UPDATE(streamConfigurationKey, streamConfigurations.data(), streamConfigurations.size());
764
765 UPDATE(minFrameDurationKey, minFrameDurations.data(), minFrameDurations.size());
766
767 UPDATE(stallDurationKey, stallDurations.data(), stallDurations.size());
768
769 return OK;
770}
771
772status_t ExternalCameraDevice::calculateMinFps(
773 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
774 std::set<int32_t> framerates;
775 int32_t minFps = std::numeric_limits<int32_t>::max();
776
777 for (const auto& supportedFormat : mSupportedFormats) {
778 for (const auto& fr : supportedFormat.frameRates) {
779 int32_t frameRateInt = static_cast<int32_t>(fr.getFramesPerSecond());
780 if (minFps > frameRateInt) {
781 minFps = frameRateInt;
782 }
783 framerates.insert(frameRateInt);
784 }
785 }
786
787 std::vector<int32_t> fpsRanges;
788 // FPS ranges
789 for (const auto& framerate : framerates) {
790 // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
791 fpsRanges.push_back(framerate / 2);
792 fpsRanges.push_back(framerate);
793 }
794 minFps /= 2;
795 int64_t maxFrameDuration = 1000000000LL / minFps;
796
797 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(), fpsRanges.size());
798
799 UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
800
801 return OK;
802}
803
804#undef ARRAY_SIZE
805#undef UPDATE
806
807void ExternalCameraDevice::getFrameRateList(int fd, double fpsUpperBound,
808 SupportedV4L2Format* format) {
809 format->frameRates.clear();
810
811 v4l2_frmivalenum frameInterval{
812 .index = 0,
813 .pixel_format = format->fourcc,
814 .width = static_cast<__u32>(format->width),
815 .height = static_cast<__u32>(format->height),
816 };
817
818 for (frameInterval.index = 0;
819 TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
820 ++frameInterval.index) {
821 if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
822 if (frameInterval.discrete.numerator != 0) {
823 SupportedV4L2Format::FrameRate fr = {frameInterval.discrete.numerator,
824 frameInterval.discrete.denominator};
825 double framerate = fr.getFramesPerSecond();
826 if (framerate > fpsUpperBound) {
827 continue;
828 }
829 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f", frameInterval.index,
830 frameInterval.pixel_format & 0xFF, (frameInterval.pixel_format >> 8) & 0xFF,
831 (frameInterval.pixel_format >> 16) & 0xFF,
832 (frameInterval.pixel_format >> 24) & 0xFF, frameInterval.width,
833 frameInterval.height, framerate);
834 format->frameRates.push_back(fr);
835 }
836 }
837 }
838
839 if (format->frameRates.empty()) {
840 ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d", __FUNCTION__,
841 frameInterval.pixel_format & 0xFF, (frameInterval.pixel_format >> 8) & 0xFF,
842 (frameInterval.pixel_format >> 16) & 0xFF, (frameInterval.pixel_format >> 24) & 0xFF,
843 frameInterval.width, frameInterval.height);
844 }
845}
846
847void ExternalCameraDevice::updateFpsBounds(
848 int fd, CroppingType cropType,
849 const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
850 SupportedV4L2Format format, std::vector<SupportedV4L2Format>& outFmts) {
851 double fpsUpperBound = -1.0;
852 for (const auto& limit : fpsLimits) {
853 if (cropType == VERTICAL) {
854 if (format.width <= limit.size.width) {
855 fpsUpperBound = limit.fpsUpperBound;
856 break;
857 }
858 } else { // HORIZONTAL
859 if (format.height <= limit.size.height) {
860 fpsUpperBound = limit.fpsUpperBound;
861 break;
862 }
863 }
864 }
865 if (fpsUpperBound < 0.f) {
866 return;
867 }
868
869 getFrameRateList(fd, fpsUpperBound, &format);
870 if (!format.frameRates.empty()) {
871 outFmts.push_back(format);
872 }
873}
874
875std::vector<SupportedV4L2Format> ExternalCameraDevice::getCandidateSupportedFormatsLocked(
876 int fd, CroppingType cropType,
877 const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
878 const std::vector<ExternalCameraConfig::FpsLimitation>& depthFpsLimits,
879 const Size& minStreamSize, bool depthEnabled) {
880 std::vector<SupportedV4L2Format> outFmts;
881 struct v4l2_fmtdesc fmtdesc {
882 .index = 0, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
883 };
884 int ret = 0;
885 while (ret == 0) {
886 ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
887 ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret, fmtdesc.pixelformat & 0xFF,
888 (fmtdesc.pixelformat >> 8) & 0xFF, (fmtdesc.pixelformat >> 16) & 0xFF,
889 (fmtdesc.pixelformat >> 24) & 0xFF);
890
891 if (ret != 0 || (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
892 // Skip if IOCTL failed, or if the format is emulated
893 fmtdesc.index++;
894 continue;
895 }
896 auto it =
897 std::find(kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
898 if (it == kSupportedFourCCs.end()) {
899 fmtdesc.index++;
900 continue;
901 }
902
903 // Found supported format
904 v4l2_frmsizeenum frameSize{.index = 0, .pixel_format = fmtdesc.pixelformat};
905 for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
906 ++frameSize.index) {
907 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
908 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
909 fmtdesc.pixelformat & 0xFF, (fmtdesc.pixelformat >> 8) & 0xFF,
910 (fmtdesc.pixelformat >> 16) & 0xFF, (fmtdesc.pixelformat >> 24) & 0xFF,
911 frameSize.discrete.width, frameSize.discrete.height);
912
913 // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
914 // This will simplify the crop/scaling logic down the road
915 if (frameSize.discrete.height > frameSize.discrete.width) {
916 continue;
917 }
918
919 // Discard all formats which is smaller than minStreamSize
920 if (frameSize.discrete.width < minStreamSize.width ||
921 frameSize.discrete.height < minStreamSize.height) {
922 continue;
923 }
924
925 SupportedV4L2Format format{
926 .width = static_cast<int32_t>(frameSize.discrete.width),
927 .height = static_cast<int32_t>(frameSize.discrete.height),
928 .fourcc = fmtdesc.pixelformat};
929
930 if (format.fourcc == V4L2_PIX_FMT_Z16 && depthEnabled) {
931 updateFpsBounds(fd, cropType, depthFpsLimits, format, outFmts);
932 } else {
933 updateFpsBounds(fd, cropType, fpsLimits, format, outFmts);
934 }
935 }
936 }
937 fmtdesc.index++;
938 }
939 trimSupportedFormats(cropType, &outFmts);
940 return outFmts;
941}
942
943void ExternalCameraDevice::trimSupportedFormats(CroppingType cropType,
944 std::vector<SupportedV4L2Format>* pFmts) {
945 std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
946 if (cropType == VERTICAL) {
947 std::sort(sortedFmts.begin(), sortedFmts.end(),
948 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
949 if (a.width == b.width) {
950 return a.height < b.height;
951 }
952 return a.width < b.width;
953 });
954 } else {
955 std::sort(sortedFmts.begin(), sortedFmts.end(),
956 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
957 if (a.height == b.height) {
958 return a.width < b.width;
959 }
960 return a.height < b.height;
961 });
962 }
963
964 if (sortedFmts.empty()) {
965 ALOGE("%s: input format list is empty!", __FUNCTION__);
966 return;
967 }
968
969 const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
970 float maxSizeAr = ASPECT_RATIO(maxSize);
971
972 // Remove formats that has aspect ratio not croppable from largest size
973 std::vector<SupportedV4L2Format> out;
974 for (const auto& fmt : sortedFmts) {
975 float ar = ASPECT_RATIO(fmt);
976 if (isAspectRatioClose(ar, maxSizeAr)) {
977 out.push_back(fmt);
978 } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
979 out.push_back(fmt);
980 } else if (cropType == VERTICAL && ar > maxSizeAr) {
981 out.push_back(fmt);
982 } else {
983 ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)", __FUNCTION__,
984 fmt.width, fmt.height, cropType == VERTICAL ? "vertically" : "horizontally",
985 maxSize.width, maxSize.height);
986 }
987 }
988 sortedFmts = out;
989}
990
991binder_status_t ExternalCameraDevice::dump(int fd, const char** args, uint32_t numArgs) {
992 std::shared_ptr<ExternalCameraDeviceSession> session = mSession.lock();
993 if (session == nullptr) {
994 dprintf(fd, "No active camera device session instance\n");
995 return STATUS_OK;
996 }
997
998 return session->dump(fd, args, numArgs);
999}
1000
1001} // namespace implementation
1002} // namespace device
1003} // namespace camera
1004} // namespace hardware
1005} // namespace android