1 /* 2 * Copyright 2014 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 package android.hardware.camera2.cts.helpers; 18 19 import android.graphics.Rect; 20 import android.graphics.ImageFormat; 21 import android.hardware.camera2.CameraCharacteristics; 22 import android.hardware.camera2.CameraCharacteristics.Key; 23 import android.hardware.camera2.CameraMetadata; 24 import android.hardware.camera2.CaptureRequest; 25 import android.hardware.camera2.CaptureResult; 26 import android.hardware.camera2.cts.CameraTestUtils; 27 import android.hardware.camera2.params.StreamConfigurationMap; 28 import android.util.Range; 29 import android.util.Size; 30 import android.util.Log; 31 import android.util.Rational; 32 33 import junit.framework.Assert; 34 35 import java.lang.reflect.Array; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.Collection; 39 import java.util.HashMap; 40 import java.util.HashSet; 41 import java.util.List; 42 import java.util.Set; 43 44 import static android.hardware.camera2.cts.helpers.AssertHelpers.*; 45 46 /** 47 * Helpers to get common static info out of the camera. 48 * 49 * <p>Avoid boiler plate by putting repetitive get/set patterns in this class.</p> 50 * 51 * <p>Attempt to be durable against the camera device having bad or missing metadata 52 * by providing reasonable defaults and logging warnings when that happens.</p> 53 */ 54 public class StaticMetadata { 55 56 private static final String TAG = "StaticMetadata"; 57 private static final int IGNORE_SIZE_CHECK = -1; 58 59 private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST = 100000L; // 100us 60 private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST = 100000000; // 100ms 61 private static final int SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST = 100; 62 private static final int SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST = 800; 63 private static final int STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST = 4; 64 private static final int TONEMAP_MAX_CURVE_POINTS_AT_LEAST = 64; 65 private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN = -2; 66 private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX = 2; 67 private static final Rational CONTROL_AE_COMPENSATION_STEP_DEFAULT = new Rational(1, 2); 68 private static final byte REQUEST_PIPELINE_MAX_DEPTH_MAX = 8; 69 private static final int MAX_REPROCESS_MAX_CAPTURE_STALL = 4; 70 71 // TODO: Consider making this work across any metadata object, not just camera characteristics 72 private final CameraCharacteristics mCharacteristics; 73 private final CheckLevel mLevel; 74 private final CameraErrorCollector mCollector; 75 76 // Last defined capability enum, for iterating over all of them 77 public static final int LAST_CAPABILITY_ENUM = 78 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA; 79 80 // Access via getAeModeName() to account for vendor extensions 81 public static final String[] AE_MODE_NAMES = new String[] { 82 "AE_MODE_OFF", 83 "AE_MODE_ON", 84 "AE_MODE_ON_AUTO_FLASH", 85 "AE_MODE_ON_ALWAYS_FLASH", 86 "AE_MODE_ON_AUTO_FLASH_REDEYE" 87 }; 88 89 // Access via getAfModeName() to account for vendor extensions 90 public static final String[] AF_MODE_NAMES = new String[] { 91 "AF_MODE_OFF", 92 "AF_MODE_AUTO", 93 "AF_MODE_MACRO", 94 "AF_MODE_CONTINUOUS_VIDEO", 95 "AF_MODE_CONTINUOUS_PICTURE", 96 "AF_MODE_EDOF" 97 }; 98 99 // Index with android.control.aeState 100 public static final String[] AE_STATE_NAMES = new String[] { 101 "AE_STATE_INACTIVE", 102 "AE_STATE_SEARCHING", 103 "AE_STATE_CONVERGED", 104 "AE_STATE_LOCKED", 105 "AE_STATE_FLASH_REQUIRED", 106 "AE_STATE_PRECAPTURE" 107 }; 108 109 // Index with android.control.afState 110 public static final String[] AF_STATE_NAMES = new String[] { 111 "AF_STATE_INACTIVE", 112 "AF_STATE_PASSIVE_SCAN", 113 "AF_STATE_PASSIVE_FOCUSED", 114 "AF_STATE_ACTIVE_SCAN", 115 "AF_STATE_FOCUSED_LOCKED", 116 "AF_STATE_NOT_FOCUSED_LOCKED", 117 "AF_STATE_PASSIVE_UNFOCUSED" 118 }; 119 120 // Index with android.control.aePrecaptureTrigger 121 public static final String[] AE_TRIGGER_NAMES = new String[] { 122 "AE_TRIGGER_IDLE", 123 "AE_TRIGGER_START", 124 "AE_TRIGGER_CANCEL" 125 }; 126 127 // Index with android.control.afTrigger 128 public static final String[] AF_TRIGGER_NAMES = new String[] { 129 "AF_TRIGGER_IDLE", 130 "AF_TRIGGER_START", 131 "AF_TRIGGER_CANCEL" 132 }; 133 134 public enum CheckLevel { 135 /** Only log warnings for metadata check failures. Execution continues. */ 136 WARN, 137 /** 138 * Use ErrorCollector to collect the metadata check failures, Execution 139 * continues. 140 */ 141 COLLECT, 142 /** Assert the metadata check failures. Execution aborts. */ 143 ASSERT 144 } 145 146 /** 147 * Construct a new StaticMetadata object. 148 * 149 *<p> Default constructor, only log warnings for the static metadata check failures</p> 150 * 151 * @param characteristics static info for a camera 152 * @throws IllegalArgumentException if characteristics was null 153 */ StaticMetadata(CameraCharacteristics characteristics)154 public StaticMetadata(CameraCharacteristics characteristics) { 155 this(characteristics, CheckLevel.WARN, /*collector*/null); 156 } 157 158 /** 159 * Construct a new StaticMetadata object with {@link CameraErrorCollector}. 160 * <p> 161 * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be 162 * ignored, otherwise, it will be used to log the check failures. 163 * </p> 164 * 165 * @param characteristics static info for a camera 166 * @param collector The {@link CameraErrorCollector} used by this StaticMetadata 167 * @throws IllegalArgumentException if characteristics or collector was null. 168 */ StaticMetadata(CameraCharacteristics characteristics, CameraErrorCollector collector)169 public StaticMetadata(CameraCharacteristics characteristics, CameraErrorCollector collector) { 170 this(characteristics, CheckLevel.COLLECT, collector); 171 } 172 173 /** 174 * Construct a new StaticMetadata object with {@link CheckLevel} and 175 * {@link CameraErrorCollector}. 176 * <p> 177 * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be 178 * ignored, otherwise, it will be used to log the check failures. 179 * </p> 180 * 181 * @param characteristics static info for a camera 182 * @param level The {@link CheckLevel} of this StaticMetadata 183 * @param collector The {@link CameraErrorCollector} used by this StaticMetadata 184 * @throws IllegalArgumentException if characteristics was null or level was 185 * {@link CheckLevel.COLLECT} but collector was null. 186 */ StaticMetadata(CameraCharacteristics characteristics, CheckLevel level, CameraErrorCollector collector)187 public StaticMetadata(CameraCharacteristics characteristics, CheckLevel level, 188 CameraErrorCollector collector) { 189 if (characteristics == null) { 190 throw new IllegalArgumentException("characteristics was null"); 191 } 192 if (level == CheckLevel.COLLECT && collector == null) { 193 throw new IllegalArgumentException("collector must valid when COLLECT level is set"); 194 } 195 196 mCharacteristics = characteristics; 197 mLevel = level; 198 mCollector = collector; 199 } 200 201 /** 202 * Get the CameraCharacteristics associated with this StaticMetadata. 203 * 204 * @return A non-null CameraCharacteristics object 205 */ getCharacteristics()206 public CameraCharacteristics getCharacteristics() { 207 return mCharacteristics; 208 } 209 210 /** 211 * Whether or not the hardware level reported by android.info.supportedHardwareLevel 212 * is at least {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL}. 213 * 214 * <p>If the camera device is not reporting the hardwareLevel, this 215 * will cause the test to fail.</p> 216 * 217 * @return {@code true} if the device is {@code FULL}, {@code false} otherwise. 218 */ isHardwareLevelAtLeastFull()219 public boolean isHardwareLevelAtLeastFull() { 220 return isHardwareLevelAtLeast(CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL); 221 } 222 223 /** 224 * Whether or not the hardware level reported by android.info.supportedHardwareLevel is 225 * at least the desired one (but could be higher) 226 */ isHardwareLevelAtLeast(int level)227 public boolean isHardwareLevelAtLeast(int level) { 228 final int[] sortedHwLevels = { 229 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, 230 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, 231 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, 232 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, 233 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 234 }; 235 int deviceLevel = getHardwareLevelChecked(); 236 if (level == deviceLevel) { 237 return true; 238 } 239 240 for (int sortedlevel : sortedHwLevels) { 241 if (sortedlevel == level) { 242 return true; 243 } else if (sortedlevel == deviceLevel) { 244 return false; 245 } 246 } 247 Assert.fail("Unknown hardwareLevel " + level + " and device hardware level " + deviceLevel); 248 return false; 249 } 250 251 /** 252 * Whether or not the camera is an external camera. If so the hardware level 253 * reported by android.info.supportedHardwareLevel is 254 * {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL}. 255 * 256 * <p>If the camera device is not reporting the hardwareLevel, this 257 * will cause the test to fail.</p> 258 * 259 * @return {@code true} if the device is external, {@code false} otherwise. 260 */ isExternalCamera()261 public boolean isExternalCamera() { 262 int deviceLevel = getHardwareLevelChecked(); 263 return deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL; 264 } 265 266 /** 267 * Whether or not the hardware level reported by android.info.supportedHardwareLevel 268 * Return the supported hardware level of the device, or fail if no value is reported. 269 * 270 * @return the supported hardware level as a constant defined for 271 * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}. 272 */ getHardwareLevelChecked()273 public int getHardwareLevelChecked() { 274 Integer hwLevel = getValueFromKeyNonNull( 275 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 276 if (hwLevel == null) { 277 Assert.fail("No supported hardware level reported."); 278 } 279 return hwLevel; 280 } 281 282 /** 283 * Whether or not the hardware level reported by android.info.supportedHardwareLevel 284 * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY}. 285 * 286 * <p>If the camera device is not reporting the hardwareLevel, this 287 * will cause the test to fail.</p> 288 * 289 * @return {@code true} if the device is {@code LEGACY}, {@code false} otherwise. 290 */ isHardwareLevelLegacy()291 public boolean isHardwareLevelLegacy() { 292 return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY; 293 } 294 295 /** 296 * Whether or not the per frame control is supported by the camera device. 297 * 298 * @return {@code true} if per frame control is supported, {@code false} otherwise. 299 */ isPerFrameControlSupported()300 public boolean isPerFrameControlSupported() { 301 return getSyncMaxLatency() == CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL; 302 } 303 304 /** 305 * Get the maximum number of frames to wait for a request settings being applied 306 * 307 * @return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN for unknown latency 308 * CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL for per frame control 309 * a positive int otherwise 310 */ getSyncMaxLatency()311 public int getSyncMaxLatency() { 312 Integer value = getValueFromKeyNonNull(CameraCharacteristics.SYNC_MAX_LATENCY); 313 if (value == null) { 314 return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN; 315 } 316 return value; 317 } 318 319 /** 320 * Get the color filter arrangement for this camera device. 321 * 322 * @return Color Filter arrangement of this camera device 323 */ getCFAChecked()324 public int getCFAChecked() { 325 Integer cfa = getValueFromKeyNonNull( 326 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT); 327 if (cfa == null) { 328 Assert.fail("No color filter array (CFA) reported."); 329 } 330 return cfa; 331 } 332 isNIRColorFilter()333 public boolean isNIRColorFilter() { 334 Integer cfa = mCharacteristics.get( 335 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT); 336 if (cfa == null) { 337 return false; 338 } 339 return cfa == CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR; 340 } 341 342 /** 343 * Whether or not the hardware level reported by android.info.supportedHardwareLevel 344 * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}. 345 * 346 * <p>If the camera device is incorrectly reporting the hardwareLevel, this 347 * will always return {@code true}.</p> 348 * 349 * @return {@code true} if the device is {@code LIMITED}, {@code false} otherwise. 350 */ isHardwareLevelLimited()351 public boolean isHardwareLevelLimited() { 352 return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; 353 } 354 355 /** 356 * Whether or not the hardware level reported by {@code android.info.supportedHardwareLevel} 357 * is at least {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}. 358 * 359 * <p>If the camera device is incorrectly reporting the hardwareLevel, this 360 * will always return {@code false}.</p> 361 * 362 * @return 363 * {@code true} if the device is {@code LIMITED} or {@code FULL}, 364 * {@code false} otherwise (i.e. LEGACY). 365 */ isHardwareLevelAtLeastLimited()366 public boolean isHardwareLevelAtLeastLimited() { 367 return isHardwareLevelAtLeast(CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED); 368 } 369 370 /** 371 * Get the maximum number of partial result a request can expect 372 * 373 * @return 1 if partial result is not supported. 374 * a integer value larger than 1 if partial result is supported. 375 */ getPartialResultCount()376 public int getPartialResultCount() { 377 Integer value = mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT); 378 if (value == null) { 379 // Optional key. Default value is 1 if key is missing. 380 return 1; 381 } 382 return value; 383 } 384 385 /** 386 * Get the exposure time value and clamp to the range if needed. 387 * 388 * @param exposure Input exposure time value to check. 389 * @return Exposure value in the legal range. 390 */ getExposureClampToRange(long exposure)391 public long getExposureClampToRange(long exposure) { 392 long minExposure = getExposureMinimumOrDefault(Long.MAX_VALUE); 393 long maxExposure = getExposureMaximumOrDefault(Long.MIN_VALUE); 394 if (minExposure > SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST) { 395 failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE, 396 String.format( 397 "Min value %d is too large, set to maximal legal value %d", 398 minExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST)); 399 minExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST; 400 } 401 if (isHardwareLevelAtLeastFull() && 402 maxExposure < SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST) { 403 failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE, 404 String.format( 405 "Max value %d is too small, set to minimal legal value %d", 406 maxExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST)); 407 maxExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST; 408 } 409 410 return Math.max(minExposure, Math.min(maxExposure, exposure)); 411 } 412 413 /** 414 * Check if the camera device support focuser. 415 * 416 * @return true if camera device support focuser, false otherwise. 417 */ hasFocuser()418 public boolean hasFocuser() { 419 if (areKeysAvailable(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE)) { 420 // LEGACY devices don't have lens.info.minimumFocusDistance, so guard this query 421 return (getMinimumFocusDistanceChecked() > 0); 422 } else { 423 // Check available AF modes 424 int[] availableAfModes = mCharacteristics.get( 425 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES); 426 427 if (availableAfModes == null) { 428 return false; 429 } 430 431 // Assume that if we have an AF mode which doesn't ignore AF trigger, we have a focuser 432 boolean hasFocuser = false; 433 loop: for (int mode : availableAfModes) { 434 switch (mode) { 435 case CameraMetadata.CONTROL_AF_MODE_AUTO: 436 case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE: 437 case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO: 438 case CameraMetadata.CONTROL_AF_MODE_MACRO: 439 hasFocuser = true; 440 break loop; 441 } 442 } 443 444 return hasFocuser; 445 } 446 } 447 448 /** 449 * Check if the camera device has flash unit. 450 * @return true if flash unit is available, false otherwise. 451 */ hasFlash()452 public boolean hasFlash() { 453 return getFlashInfoChecked(); 454 } 455 456 /** 457 * Get minimum focus distance. 458 * 459 * @return minimum focus distance, 0 if minimum focus distance is invalid. 460 */ getMinimumFocusDistanceChecked()461 public float getMinimumFocusDistanceChecked() { 462 Key<Float> key = CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE; 463 Float minFocusDistance; 464 465 /** 466 * android.lens.info.minimumFocusDistance - required for FULL and MANUAL_SENSOR-capable 467 * devices; optional for all other devices. 468 */ 469 if (isHardwareLevelAtLeastFull() || isCapabilitySupported( 470 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) { 471 minFocusDistance = getValueFromKeyNonNull(key); 472 } else { 473 minFocusDistance = mCharacteristics.get(key); 474 } 475 476 if (minFocusDistance == null) { 477 return 0.0f; 478 } 479 480 checkTrueForKey(key, " minFocusDistance value shouldn't be negative", 481 minFocusDistance >= 0); 482 if (minFocusDistance < 0) { 483 minFocusDistance = 0.0f; 484 } 485 486 return minFocusDistance; 487 } 488 489 /** 490 * Get focusDistanceCalibration. 491 * 492 * @return focusDistanceCalibration, UNCALIBRATED if value is invalid. 493 */ getFocusDistanceCalibrationChecked()494 public int getFocusDistanceCalibrationChecked() { 495 Key<Integer> key = CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION; 496 Integer calibration = getValueFromKeyNonNull(key); 497 498 if (calibration == null) { 499 return CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED; 500 } 501 502 checkTrueForKey(key, " value is out of range" , 503 calibration >= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED && 504 calibration <= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED); 505 506 return calibration; 507 } 508 getAeModeName(int aeMode)509 public static String getAeModeName(int aeMode) { 510 return (aeMode >= AE_MODE_NAMES.length) ? String.format("VENDOR_AE_MODE_%d", aeMode) : 511 AE_MODE_NAMES[aeMode]; 512 } 513 getAfModeName(int afMode)514 public static String getAfModeName(int afMode) { 515 return (afMode >= AF_MODE_NAMES.length) ? String.format("VENDOR_AF_MODE_%d", afMode) : 516 AF_MODE_NAMES[afMode]; 517 } 518 519 /** 520 * Get max AE regions and do sanity check. 521 * 522 * @return AE max regions supported by the camera device 523 */ getAeMaxRegionsChecked()524 public int getAeMaxRegionsChecked() { 525 Integer regionCount = mCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE); 526 if (regionCount == null) { 527 return 0; 528 } 529 return regionCount; 530 } 531 532 /** 533 * Get max AWB regions and do sanity check. 534 * 535 * @return AWB max regions supported by the camera device 536 */ getAwbMaxRegionsChecked()537 public int getAwbMaxRegionsChecked() { 538 Integer regionCount = mCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB); 539 if (regionCount == null) { 540 return 0; 541 } 542 return regionCount; 543 } 544 545 /** 546 * Get max AF regions and do sanity check. 547 * 548 * @return AF max regions supported by the camera device 549 */ getAfMaxRegionsChecked()550 public int getAfMaxRegionsChecked() { 551 Integer regionCount = mCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF); 552 if (regionCount == null) { 553 return 0; 554 } 555 return regionCount; 556 } 557 /** 558 * Get the available anti-banding modes. 559 * 560 * @return The array contains available anti-banding modes. 561 */ getAeAvailableAntiBandingModesChecked()562 public int[] getAeAvailableAntiBandingModesChecked() { 563 Key<int[]> key = CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES; 564 int[] modes = getValueFromKeyNonNull(key); 565 566 boolean foundAuto = false; 567 boolean found50Hz = false; 568 boolean found60Hz = false; 569 for (int mode : modes) { 570 checkTrueForKey(key, "mode value " + mode + " is out if range", 571 mode >= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF || 572 mode <= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO); 573 if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO) { 574 foundAuto = true; 575 } else if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_50HZ) { 576 found50Hz = true; 577 } else if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_60HZ) { 578 found60Hz = true; 579 } 580 } 581 // Must contain AUTO mode or one of 50/60Hz mode. 582 checkTrueForKey(key, "Either AUTO mode or both 50HZ/60HZ mode should present", 583 foundAuto || (found50Hz && found60Hz)); 584 585 return modes; 586 } 587 588 /** 589 * Check if the antibanding OFF mode is supported. 590 * 591 * @return true if antibanding OFF mode is supported, false otherwise. 592 */ isAntiBandingOffModeSupported()593 public boolean isAntiBandingOffModeSupported() { 594 List<Integer> antiBandingModes = 595 Arrays.asList(CameraTestUtils.toObject(getAeAvailableAntiBandingModesChecked())); 596 597 return antiBandingModes.contains(CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF); 598 } 599 getFlashInfoChecked()600 public Boolean getFlashInfoChecked() { 601 Key<Boolean> key = CameraCharacteristics.FLASH_INFO_AVAILABLE; 602 Boolean hasFlash = getValueFromKeyNonNull(key); 603 604 // In case the failOnKey only gives warning. 605 if (hasFlash == null) { 606 return false; 607 } 608 609 return hasFlash; 610 } 611 getAvailableTestPatternModesChecked()612 public int[] getAvailableTestPatternModesChecked() { 613 Key<int[]> key = 614 CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES; 615 int[] modes = getValueFromKeyNonNull(key); 616 617 if (modes == null) { 618 return new int[0]; 619 } 620 621 int expectValue = CameraCharacteristics.SENSOR_TEST_PATTERN_MODE_OFF; 622 Integer[] boxedModes = CameraTestUtils.toObject(modes); 623 checkTrueForKey(key, " value must contain OFF mode", 624 Arrays.asList(boxedModes).contains(expectValue)); 625 626 return modes; 627 } 628 629 /** 630 * Get available thumbnail sizes and do the sanity check. 631 * 632 * @return The array of available thumbnail sizes 633 */ getAvailableThumbnailSizesChecked()634 public Size[] getAvailableThumbnailSizesChecked() { 635 Key<Size[]> key = CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES; 636 Size[] sizes = getValueFromKeyNonNull(key); 637 final List<Size> sizeList = Arrays.asList(sizes); 638 639 // Size must contain (0, 0). 640 checkTrueForKey(key, "size should contain (0, 0)", sizeList.contains(new Size(0, 0))); 641 642 // Each size must be distinct. 643 checkElementDistinct(key, sizeList); 644 645 // Must be sorted in ascending order by area, by width if areas are same. 646 List<Size> orderedSizes = 647 CameraTestUtils.getAscendingOrderSizes(sizeList, /*ascending*/true); 648 checkTrueForKey(key, "Sizes should be in ascending order: Original " + sizeList.toString() 649 + ", Expected " + orderedSizes.toString(), orderedSizes.equals(sizeList)); 650 651 // TODO: Aspect ratio match, need wait for android.scaler.availableStreamConfigurations 652 // implementation see b/12958122. 653 654 return sizes; 655 } 656 657 /** 658 * Get available focal lengths and do the sanity check. 659 * 660 * @return The array of available focal lengths 661 */ getAvailableFocalLengthsChecked()662 public float[] getAvailableFocalLengthsChecked() { 663 Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS; 664 float[] focalLengths = getValueFromKeyNonNull(key); 665 666 checkTrueForKey(key, "Array should contain at least one element", focalLengths.length >= 1); 667 668 for (int i = 0; i < focalLengths.length; i++) { 669 checkTrueForKey(key, 670 String.format("focalLength[%d] %f should be positive.", i, focalLengths[i]), 671 focalLengths[i] > 0); 672 } 673 checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(focalLengths))); 674 675 return focalLengths; 676 } 677 678 /** 679 * Get available apertures and do the sanity check. 680 * 681 * @return The non-null array of available apertures 682 */ getAvailableAperturesChecked()683 public float[] getAvailableAperturesChecked() { 684 Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES; 685 float[] apertures = getValueFromKeyNonNull(key); 686 687 checkTrueForKey(key, "Array should contain at least one element", apertures.length >= 1); 688 689 for (int i = 0; i < apertures.length; i++) { 690 checkTrueForKey(key, 691 String.format("apertures[%d] %f should be positive.", i, apertures[i]), 692 apertures[i] > 0); 693 } 694 checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(apertures))); 695 696 return apertures; 697 } 698 699 /** 700 * Get and check the available hot pixel map modes. 701 * 702 * @return the available hot pixel map modes 703 */ getAvailableHotPixelModesChecked()704 public int[] getAvailableHotPixelModesChecked() { 705 Key<int[]> key = CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES; 706 int[] modes = getValueFromKeyNonNull(key); 707 708 if (modes == null) { 709 return new int[0]; 710 } 711 712 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 713 if (isHardwareLevelAtLeastFull()) { 714 checkTrueForKey(key, "Full-capability camera devices must support FAST mode", 715 modeList.contains(CameraMetadata.HOT_PIXEL_MODE_FAST)); 716 } 717 718 if (isHardwareLevelAtLeastLimited()) { 719 // FAST and HIGH_QUALITY mode must be both present or both not present 720 List<Integer> coupledModes = Arrays.asList(new Integer[] { 721 CameraMetadata.HOT_PIXEL_MODE_FAST, 722 CameraMetadata.HOT_PIXEL_MODE_HIGH_QUALITY 723 }); 724 checkTrueForKey( 725 key, " FAST and HIGH_QUALITY mode must both present or both not present", 726 containsAllOrNone(modeList, coupledModes)); 727 } 728 checkElementDistinct(key, modeList); 729 checkArrayValuesInRange(key, modes, CameraMetadata.HOT_PIXEL_MODE_OFF, 730 CameraMetadata.HOT_PIXEL_MODE_HIGH_QUALITY); 731 732 return modes; 733 } 734 735 /** 736 * Get and check available face detection modes. 737 * 738 * @return The non-null array of available face detection modes 739 */ getAvailableFaceDetectModesChecked()740 public int[] getAvailableFaceDetectModesChecked() { 741 Key<int[]> key = CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES; 742 int[] modes = getValueFromKeyNonNull(key); 743 744 if (modes == null) { 745 return new int[0]; 746 } 747 748 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 749 checkTrueForKey(key, "Array should contain OFF mode", 750 modeList.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF)); 751 checkElementDistinct(key, modeList); 752 checkArrayValuesInRange(key, modes, CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF, 753 CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL); 754 755 return modes; 756 } 757 758 /** 759 * Get and check max face detected count. 760 * 761 * @return max number of faces that can be detected 762 */ getMaxFaceCountChecked()763 public int getMaxFaceCountChecked() { 764 Key<Integer> key = CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT; 765 Integer count = getValueFromKeyNonNull(key); 766 767 if (count == null) { 768 return 0; 769 } 770 771 List<Integer> faceDetectModes = 772 Arrays.asList(CameraTestUtils.toObject(getAvailableFaceDetectModesChecked())); 773 if (faceDetectModes.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF) && 774 faceDetectModes.size() == 1) { 775 checkTrueForKey(key, " value must be 0 if only OFF mode is supported in " 776 + "availableFaceDetectionModes", count == 0); 777 } else { 778 int maxFaceCountAtLeast = STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST; 779 780 // Legacy mode may support fewer than STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST faces. 781 if (isHardwareLevelLegacy()) { 782 maxFaceCountAtLeast = 1; 783 } 784 checkTrueForKey(key, " value must be no less than " + maxFaceCountAtLeast + " if SIMPLE" 785 + "or FULL is also supported in availableFaceDetectionModes", 786 count >= maxFaceCountAtLeast); 787 } 788 789 return count; 790 } 791 792 /** 793 * Get and check the available tone map modes. 794 * 795 * @return the available tone map modes 796 */ getAvailableToneMapModesChecked()797 public int[] getAvailableToneMapModesChecked() { 798 Key<int[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES; 799 int[] modes = mCharacteristics.get(key); 800 801 if (modes == null) { 802 return new int[0]; 803 } 804 805 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 806 checkTrueForKey(key, " Camera devices must always support FAST mode", 807 modeList.contains(CameraMetadata.TONEMAP_MODE_FAST)); 808 // Qualification check for MANUAL_POSTPROCESSING capability is in 809 // StaticMetadataTest#testCapabilities 810 811 if (isHardwareLevelAtLeastLimited()) { 812 // FAST and HIGH_QUALITY mode must be both present or both not present 813 List<Integer> coupledModes = Arrays.asList(new Integer[] { 814 CameraMetadata.TONEMAP_MODE_FAST, 815 CameraMetadata.TONEMAP_MODE_HIGH_QUALITY 816 }); 817 checkTrueForKey( 818 key, " FAST and HIGH_QUALITY mode must both present or both not present", 819 containsAllOrNone(modeList, coupledModes)); 820 } 821 checkElementDistinct(key, modeList); 822 checkArrayValuesInRange(key, modes, CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE, 823 CameraMetadata.TONEMAP_MODE_PRESET_CURVE); 824 825 return modes; 826 } 827 828 /** 829 * Get and check max tonemap curve point. 830 * 831 * @return Max tonemap curve points. 832 */ getMaxTonemapCurvePointChecked()833 public int getMaxTonemapCurvePointChecked() { 834 Key<Integer> key = CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS; 835 Integer count = getValueFromKeyNonNull(key); 836 List<Integer> modeList = 837 Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked())); 838 boolean tonemapCurveOutputSupported = 839 modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) || 840 modeList.contains(CameraMetadata.TONEMAP_MODE_GAMMA_VALUE) || 841 modeList.contains(CameraMetadata.TONEMAP_MODE_PRESET_CURVE); 842 843 if (count == null) { 844 if (tonemapCurveOutputSupported) { 845 Assert.fail("Tonemap curve output is supported but MAX_CURVE_POINTS is null"); 846 } 847 return 0; 848 } 849 850 if (tonemapCurveOutputSupported) { 851 checkTrueForKey(key, "Tonemap curve output supported camera device must support " 852 + "maxCurvePoints >= " + TONEMAP_MAX_CURVE_POINTS_AT_LEAST, 853 count >= TONEMAP_MAX_CURVE_POINTS_AT_LEAST); 854 } 855 856 return count; 857 } 858 859 /** 860 * Get and check pixel array size. 861 */ getPixelArraySizeChecked()862 public Size getPixelArraySizeChecked() { 863 Key<Size> key = CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE; 864 Size pixelArray = getValueFromKeyNonNull(key); 865 if (pixelArray == null) { 866 return new Size(0, 0); 867 } 868 869 return pixelArray; 870 } 871 872 /** 873 * Get and check pre-correction active array size. 874 */ getPreCorrectedActiveArraySizeChecked()875 public Rect getPreCorrectedActiveArraySizeChecked() { 876 Key<Rect> key = CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE; 877 Rect activeArray = getValueFromKeyNonNull(key); 878 879 if (activeArray == null) { 880 return new Rect(0, 0, 0, 0); 881 } 882 883 Size pixelArraySize = getPixelArraySizeChecked(); 884 checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0); 885 checkTrueForKey(key, "values width/height are invalid", 886 activeArray.width() <= pixelArraySize.getWidth() && 887 activeArray.height() <= pixelArraySize.getHeight()); 888 889 return activeArray; 890 } 891 892 /** 893 * Get and check active array size. 894 */ getActiveArraySizeChecked()895 public Rect getActiveArraySizeChecked() { 896 Key<Rect> key = CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE; 897 Rect activeArray = getValueFromKeyNonNull(key); 898 899 if (activeArray == null) { 900 return new Rect(0, 0, 0, 0); 901 } 902 903 Size pixelArraySize = getPixelArraySizeChecked(); 904 checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0); 905 checkTrueForKey(key, "values width/height are invalid", 906 activeArray.width() <= pixelArraySize.getWidth() && 907 activeArray.height() <= pixelArraySize.getHeight()); 908 909 return activeArray; 910 } 911 912 /** 913 * Get the dimensions to use for RAW16 buffers. 914 */ getRawDimensChecked()915 public Size getRawDimensChecked() throws Exception { 916 Size[] targetCaptureSizes = getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR, 917 StaticMetadata.StreamDirection.Output); 918 Assert.assertTrue("No capture sizes available for RAW format!", 919 targetCaptureSizes.length != 0); 920 Rect activeArray = getPreCorrectedActiveArraySizeChecked(); 921 Size preCorrectionActiveArraySize = 922 new Size(activeArray.width(), activeArray.height()); 923 Size pixelArraySize = getPixelArraySizeChecked(); 924 Assert.assertTrue("Missing pre-correction active array size", activeArray.width() > 0 && 925 activeArray.height() > 0); 926 Assert.assertTrue("Missing pixel array size", pixelArraySize.getWidth() > 0 && 927 pixelArraySize.getHeight() > 0); 928 Size[] allowedArraySizes = new Size[] { preCorrectionActiveArraySize, 929 pixelArraySize }; 930 return assertArrayContainsAnyOf("Available sizes for RAW format" + 931 " must include either the pre-corrected active array size, or the full " + 932 "pixel array size", targetCaptureSizes, allowedArraySizes); 933 } 934 935 /** 936 * Get the sensitivity value and clamp to the range if needed. 937 * 938 * @param sensitivity Input sensitivity value to check. 939 * @return Sensitivity value in legal range. 940 */ getSensitivityClampToRange(int sensitivity)941 public int getSensitivityClampToRange(int sensitivity) { 942 int minSensitivity = getSensitivityMinimumOrDefault(Integer.MAX_VALUE); 943 int maxSensitivity = getSensitivityMaximumOrDefault(Integer.MIN_VALUE); 944 if (minSensitivity > SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST) { 945 failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE, 946 String.format( 947 "Min value %d is too large, set to maximal legal value %d", 948 minSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST)); 949 minSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST; 950 } 951 if (maxSensitivity < SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST) { 952 failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE, 953 String.format( 954 "Max value %d is too small, set to minimal legal value %d", 955 maxSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST)); 956 maxSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST; 957 } 958 959 return Math.max(minSensitivity, Math.min(maxSensitivity, sensitivity)); 960 } 961 962 /** 963 * Get maxAnalogSensitivity for a camera device. 964 * <p> 965 * This is only available for FULL capability device, return 0 if it is unavailable. 966 * </p> 967 * 968 * @return maxAnalogSensitivity, 0 if it is not available. 969 */ getMaxAnalogSensitivityChecked()970 public int getMaxAnalogSensitivityChecked() { 971 972 Key<Integer> key = CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY; 973 Integer maxAnalogsensitivity = mCharacteristics.get(key); 974 if (maxAnalogsensitivity == null) { 975 if (isHardwareLevelAtLeastFull()) { 976 Assert.fail("Full device should report max analog sensitivity"); 977 } 978 return 0; 979 } 980 981 int minSensitivity = getSensitivityMinimumOrDefault(); 982 int maxSensitivity = getSensitivityMaximumOrDefault(); 983 checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity 984 + " should be no larger than max sensitivity " + maxSensitivity, 985 maxAnalogsensitivity <= maxSensitivity); 986 checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity 987 + " should be larger than min sensitivity " + maxSensitivity, 988 maxAnalogsensitivity > minSensitivity); 989 990 return maxAnalogsensitivity; 991 } 992 993 /** 994 * Get hyperfocalDistance and do the sanity check. 995 * <p> 996 * Note that, this tag is optional, will return -1 if this tag is not 997 * available. 998 * </p> 999 * 1000 * @return hyperfocalDistance of this device, -1 if this tag is not available. 1001 */ getHyperfocalDistanceChecked()1002 public float getHyperfocalDistanceChecked() { 1003 Key<Float> key = CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE; 1004 Float hyperfocalDistance = getValueFromKeyNonNull(key); 1005 if (hyperfocalDistance == null) { 1006 return -1; 1007 } 1008 1009 if (hasFocuser()) { 1010 float minFocusDistance = getMinimumFocusDistanceChecked(); 1011 checkTrueForKey(key, String.format(" hyperfocal distance %f should be in the range of" 1012 + " should be in the range of (%f, %f]", hyperfocalDistance, 0.0f, 1013 minFocusDistance), 1014 hyperfocalDistance > 0 && hyperfocalDistance <= minFocusDistance); 1015 } 1016 1017 return hyperfocalDistance; 1018 } 1019 1020 /** 1021 * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange. 1022 * 1023 * <p>If the camera is incorrectly reporting values, log a warning and return 1024 * the default value instead, which is the largest minimum value required to be supported 1025 * by all camera devices.</p> 1026 * 1027 * @return The value reported by the camera device or the defaultValue otherwise. 1028 */ getSensitivityMinimumOrDefault()1029 public int getSensitivityMinimumOrDefault() { 1030 return getSensitivityMinimumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST); 1031 } 1032 1033 /** 1034 * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange. 1035 * 1036 * <p>If the camera is incorrectly reporting values, log a warning and return 1037 * the default value instead.</p> 1038 * 1039 * @param defaultValue Value to return if no legal value is available 1040 * @return The value reported by the camera device or the defaultValue otherwise. 1041 */ getSensitivityMinimumOrDefault(int defaultValue)1042 public int getSensitivityMinimumOrDefault(int defaultValue) { 1043 Range<Integer> range = getValueFromKeyNonNull( 1044 CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE); 1045 if (range == null) { 1046 failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE, 1047 "had no valid minimum value; using default of " + defaultValue); 1048 return defaultValue; 1049 } 1050 return range.getLower(); 1051 } 1052 1053 /** 1054 * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange. 1055 * 1056 * <p>If the camera is incorrectly reporting values, log a warning and return 1057 * the default value instead, which is the smallest maximum value required to be supported 1058 * by all camera devices.</p> 1059 * 1060 * @return The value reported by the camera device or the defaultValue otherwise. 1061 */ getSensitivityMaximumOrDefault()1062 public int getSensitivityMaximumOrDefault() { 1063 return getSensitivityMaximumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST); 1064 } 1065 1066 /** 1067 * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange. 1068 * 1069 * <p>If the camera is incorrectly reporting values, log a warning and return 1070 * the default value instead.</p> 1071 * 1072 * @param defaultValue Value to return if no legal value is available 1073 * @return The value reported by the camera device or the defaultValue otherwise. 1074 */ getSensitivityMaximumOrDefault(int defaultValue)1075 public int getSensitivityMaximumOrDefault(int defaultValue) { 1076 Range<Integer> range = getValueFromKeyNonNull( 1077 CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE); 1078 if (range == null) { 1079 failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE, 1080 "had no valid maximum value; using default of " + defaultValue); 1081 return defaultValue; 1082 } 1083 return range.getUpper(); 1084 } 1085 1086 /** 1087 * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange. 1088 * 1089 * <p>If the camera is incorrectly reporting values, log a warning and return 1090 * the default value instead.</p> 1091 * 1092 * @param defaultValue Value to return if no legal value is available 1093 * @return The value reported by the camera device or the defaultValue otherwise. 1094 */ getExposureMinimumOrDefault(long defaultValue)1095 public long getExposureMinimumOrDefault(long defaultValue) { 1096 Range<Long> range = getValueFromKeyNonNull( 1097 CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE); 1098 if (range == null) { 1099 failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE, 1100 "had no valid minimum value; using default of " + defaultValue); 1101 return defaultValue; 1102 } 1103 return range.getLower(); 1104 } 1105 1106 /** 1107 * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange. 1108 * 1109 * <p>If the camera is incorrectly reporting values, log a warning and return 1110 * the default value instead, which is the largest minimum value required to be supported 1111 * by all camera devices.</p> 1112 * 1113 * @return The value reported by the camera device or the defaultValue otherwise. 1114 */ getExposureMinimumOrDefault()1115 public long getExposureMinimumOrDefault() { 1116 return getExposureMinimumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST); 1117 } 1118 1119 /** 1120 * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange. 1121 * 1122 * <p>If the camera is incorrectly reporting values, log a warning and return 1123 * the default value instead.</p> 1124 * 1125 * @param defaultValue Value to return if no legal value is available 1126 * @return The value reported by the camera device or the defaultValue otherwise. 1127 */ getExposureMaximumOrDefault(long defaultValue)1128 public long getExposureMaximumOrDefault(long defaultValue) { 1129 Range<Long> range = getValueFromKeyNonNull( 1130 CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE); 1131 if (range == null) { 1132 failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE, 1133 "had no valid maximum value; using default of " + defaultValue); 1134 return defaultValue; 1135 } 1136 return range.getUpper(); 1137 } 1138 1139 /** 1140 * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange. 1141 * 1142 * <p>If the camera is incorrectly reporting values, log a warning and return 1143 * the default value instead, which is the smallest maximum value required to be supported 1144 * by all camera devices.</p> 1145 * 1146 * @return The value reported by the camera device or the defaultValue otherwise. 1147 */ getExposureMaximumOrDefault()1148 public long getExposureMaximumOrDefault() { 1149 return getExposureMaximumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST); 1150 } 1151 1152 /** 1153 * get android.control.availableModes and do the sanity check. 1154 * 1155 * @return available control modes. 1156 */ getAvailableControlModesChecked()1157 public int[] getAvailableControlModesChecked() { 1158 Key<int[]> modesKey = CameraCharacteristics.CONTROL_AVAILABLE_MODES; 1159 int[] modes = getValueFromKeyNonNull(modesKey); 1160 if (modes == null) { 1161 modes = new int[0]; 1162 } 1163 1164 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1165 checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty()); 1166 1167 // All camera device must support AUTO 1168 checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain AUTO mode", 1169 modeList.contains(CameraMetadata.CONTROL_MODE_AUTO)); 1170 1171 boolean isAeOffSupported = Arrays.asList( 1172 CameraTestUtils.toObject(getAeAvailableModesChecked())).contains( 1173 CameraMetadata.CONTROL_AE_MODE_OFF); 1174 boolean isAfOffSupported = Arrays.asList( 1175 CameraTestUtils.toObject(getAfAvailableModesChecked())).contains( 1176 CameraMetadata.CONTROL_AF_MODE_OFF); 1177 boolean isAwbOffSupported = Arrays.asList( 1178 CameraTestUtils.toObject(getAwbAvailableModesChecked())).contains( 1179 CameraMetadata.CONTROL_AWB_MODE_OFF); 1180 if (isAeOffSupported && isAfOffSupported && isAwbOffSupported) { 1181 // 3A OFF controls are supported, OFF mode must be supported here. 1182 checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain OFF mode", 1183 modeList.contains(CameraMetadata.CONTROL_MODE_OFF)); 1184 } 1185 1186 if (isSceneModeSupported()) { 1187 checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain" 1188 + " USE_SCENE_MODE", 1189 modeList.contains(CameraMetadata.CONTROL_MODE_USE_SCENE_MODE)); 1190 } 1191 1192 return modes; 1193 } 1194 isSceneModeSupported()1195 public boolean isSceneModeSupported() { 1196 List<Integer> availableSceneModes = Arrays.asList( 1197 CameraTestUtils.toObject(getAvailableSceneModesChecked())); 1198 1199 if (availableSceneModes.isEmpty()) { 1200 return false; 1201 } 1202 1203 // If sceneMode is not supported, camera device will contain single entry: DISABLED. 1204 return availableSceneModes.size() > 1 || 1205 !availableSceneModes.contains(CameraMetadata.CONTROL_SCENE_MODE_DISABLED); 1206 } 1207 1208 /** 1209 * Get aeAvailableModes and do the sanity check. 1210 * 1211 * <p>Depending on the check level this class has, for WAR or COLLECT levels, 1212 * If the aeMode list is invalid, return an empty mode array. The the caller doesn't 1213 * have to abort the execution even the aeMode list is invalid.</p> 1214 * @return AE available modes 1215 */ getAeAvailableModesChecked()1216 public int[] getAeAvailableModesChecked() { 1217 Key<int[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES; 1218 int[] modes = getValueFromKeyNonNull(modesKey); 1219 if (modes == null) { 1220 modes = new int[0]; 1221 } 1222 List<Integer> modeList = new ArrayList<Integer>(); 1223 for (int mode : modes) { 1224 // Skip vendor-added modes 1225 if (mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) { 1226 modeList.add(mode); 1227 } 1228 } 1229 checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty()); 1230 modes = new int[modeList.size()]; 1231 for (int i = 0; i < modeList.size(); i++) { 1232 modes[i] = modeList.get(i); 1233 } 1234 1235 // All camera device must support ON 1236 checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain ON mode", 1237 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON)); 1238 1239 // All camera devices with flash units support ON_AUTO_FLASH and ON_ALWAYS_FLASH 1240 Key<Boolean> flashKey= CameraCharacteristics.FLASH_INFO_AVAILABLE; 1241 Boolean hasFlash = getValueFromKeyNonNull(flashKey); 1242 if (hasFlash == null) { 1243 hasFlash = false; 1244 } 1245 if (hasFlash) { 1246 boolean flashModeConsistentWithFlash = 1247 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) && 1248 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH); 1249 checkTrueForKey(modesKey, 1250 "value must contain ON_AUTO_FLASH and ON_ALWAYS_FLASH and when flash is" + 1251 "available", flashModeConsistentWithFlash); 1252 } else { 1253 boolean flashModeConsistentWithoutFlash = 1254 !(modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) || 1255 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH) || 1256 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE)); 1257 checkTrueForKey(modesKey, 1258 "value must not contain ON_AUTO_FLASH, ON_ALWAYS_FLASH and" + 1259 "ON_AUTO_FLASH_REDEYE when flash is unavailable", 1260 flashModeConsistentWithoutFlash); 1261 } 1262 1263 // FULL mode camera devices always support OFF mode. 1264 boolean condition = 1265 !isHardwareLevelAtLeastFull() || modeList.contains(CameraMetadata.CONTROL_AE_MODE_OFF); 1266 checkTrueForKey(modesKey, "Full capability device must have OFF mode", condition); 1267 1268 // Boundary check. 1269 for (int mode : modes) { 1270 checkTrueForKey(modesKey, "Value " + mode + " is out of bound", 1271 mode >= CameraMetadata.CONTROL_AE_MODE_OFF 1272 && mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE); 1273 } 1274 1275 return modes; 1276 } 1277 1278 /** 1279 * Get available AWB modes and do the sanity check. 1280 * 1281 * @return array that contains available AWB modes, empty array if awbAvailableModes is 1282 * unavailable. 1283 */ getAwbAvailableModesChecked()1284 public int[] getAwbAvailableModesChecked() { 1285 Key<int[]> key = 1286 CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES; 1287 int[] awbModes = getValueFromKeyNonNull(key); 1288 1289 if (awbModes == null) { 1290 return new int[0]; 1291 } 1292 1293 List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(awbModes)); 1294 checkTrueForKey(key, " All camera devices must support AUTO mode", 1295 modesList.contains(CameraMetadata.CONTROL_AWB_MODE_AUTO)); 1296 if (isHardwareLevelAtLeastFull()) { 1297 checkTrueForKey(key, " Full capability camera devices must support OFF mode", 1298 modesList.contains(CameraMetadata.CONTROL_AWB_MODE_OFF)); 1299 } 1300 1301 return awbModes; 1302 } 1303 1304 /** 1305 * Get available AF modes and do the sanity check. 1306 * 1307 * @return array that contains available AF modes, empty array if afAvailableModes is 1308 * unavailable. 1309 */ getAfAvailableModesChecked()1310 public int[] getAfAvailableModesChecked() { 1311 Key<int[]> key = 1312 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES; 1313 int[] afModes = getValueFromKeyNonNull(key); 1314 1315 if (afModes == null) { 1316 return new int[0]; 1317 } 1318 1319 List<Integer> modesList = new ArrayList<Integer>(); 1320 for (int afMode : afModes) { 1321 // Skip vendor-added AF modes 1322 if (afMode > CameraCharacteristics.CONTROL_AF_MODE_EDOF) continue; 1323 modesList.add(afMode); 1324 } 1325 afModes = new int[modesList.size()]; 1326 for (int i = 0; i < modesList.size(); i++) { 1327 afModes[i] = modesList.get(i); 1328 } 1329 1330 if (isHardwareLevelAtLeastLimited()) { 1331 // Some LEGACY mode devices do not support AF OFF 1332 checkTrueForKey(key, " All camera devices must support OFF mode", 1333 modesList.contains(CameraMetadata.CONTROL_AF_MODE_OFF)); 1334 } 1335 if (hasFocuser()) { 1336 checkTrueForKey(key, " Camera devices that have focuser units must support AUTO mode", 1337 modesList.contains(CameraMetadata.CONTROL_AF_MODE_AUTO)); 1338 } 1339 1340 return afModes; 1341 } 1342 1343 /** 1344 * Get supported raw output sizes and do the check. 1345 * 1346 * @return Empty size array if raw output is not supported 1347 */ getRawOutputSizesChecked()1348 public Size[] getRawOutputSizesChecked() { 1349 return getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR, 1350 StreamDirection.Output); 1351 } 1352 1353 /** 1354 * Get supported jpeg output sizes and do the check. 1355 * 1356 * @return Empty size array if jpeg output is not supported 1357 */ getJpegOutputSizesChecked()1358 public Size[] getJpegOutputSizesChecked() { 1359 return getAvailableSizesForFormatChecked(ImageFormat.JPEG, 1360 StreamDirection.Output); 1361 } 1362 1363 /** 1364 * Get supported heic output sizes and do the check. 1365 * 1366 * @return Empty size array if heic output is not supported 1367 */ getHeicOutputSizesChecked()1368 public Size[] getHeicOutputSizesChecked() { 1369 return getAvailableSizesForFormatChecked(ImageFormat.HEIC, 1370 StreamDirection.Output); 1371 } 1372 1373 /** 1374 * Used to determine the stream direction for various helpers that look up 1375 * format or size information. 1376 */ 1377 public enum StreamDirection { 1378 /** Stream is used with {@link android.hardware.camera2.CameraDevice#configureOutputs} */ 1379 Output, 1380 /** Stream is used with {@code CameraDevice#configureInputs} -- NOT YET PUBLIC */ 1381 Input 1382 } 1383 1384 /** 1385 * Get available formats for a given direction. 1386 * 1387 * @param direction The stream direction, input or output. 1388 * @return The formats of the given direction, empty array if no available format is found. 1389 */ getAvailableFormats(StreamDirection direction)1390 public int[] getAvailableFormats(StreamDirection direction) { 1391 Key<StreamConfigurationMap> key = 1392 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP; 1393 StreamConfigurationMap config = getValueFromKeyNonNull(key); 1394 1395 if (config == null) { 1396 return new int[0]; 1397 } 1398 1399 switch (direction) { 1400 case Output: 1401 return config.getOutputFormats(); 1402 case Input: 1403 return config.getInputFormats(); 1404 default: 1405 throw new IllegalArgumentException("direction must be output or input"); 1406 } 1407 } 1408 1409 /** 1410 * Get valid output formats for a given input format. 1411 * 1412 * @param inputFormat The input format used to produce the output images. 1413 * @return The output formats for the given input format, empty array if 1414 * no available format is found. 1415 */ getValidOutputFormatsForInput(int inputFormat)1416 public int[] getValidOutputFormatsForInput(int inputFormat) { 1417 Key<StreamConfigurationMap> key = 1418 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP; 1419 StreamConfigurationMap config = getValueFromKeyNonNull(key); 1420 1421 if (config == null) { 1422 return new int[0]; 1423 } 1424 1425 return config.getValidOutputFormatsForInput(inputFormat); 1426 } 1427 1428 /** 1429 * Get available sizes for given format and direction. 1430 * 1431 * @param format The format for the requested size array. 1432 * @param direction The stream direction, input or output. 1433 * @return The sizes of the given format, empty array if no available size is found. 1434 */ getAvailableSizesForFormatChecked(int format, StreamDirection direction)1435 public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction) { 1436 return getAvailableSizesForFormatChecked(format, direction, 1437 /*fastSizes*/true, /*slowSizes*/true); 1438 } 1439 1440 /** 1441 * Get available sizes for given format and direction, and whether to limit to slow or fast 1442 * resolutions. 1443 * 1444 * @param format The format for the requested size array. 1445 * @param direction The stream direction, input or output. 1446 * @param fastSizes whether to include getOutputSizes() sizes (generally faster) 1447 * @param slowSizes whether to include getHighResolutionOutputSizes() sizes (generally slower) 1448 * @return The sizes of the given format, empty array if no available size is found. 1449 */ getAvailableSizesForFormatChecked(int format, StreamDirection direction, boolean fastSizes, boolean slowSizes)1450 public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction, 1451 boolean fastSizes, boolean slowSizes) { 1452 Key<StreamConfigurationMap> key = 1453 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP; 1454 StreamConfigurationMap config = getValueFromKeyNonNull(key); 1455 1456 if (config == null) { 1457 return new Size[0]; 1458 } 1459 1460 Size[] sizes = null; 1461 1462 switch (direction) { 1463 case Output: 1464 Size[] fastSizeList = null; 1465 Size[] slowSizeList = null; 1466 if (fastSizes) { 1467 fastSizeList = config.getOutputSizes(format); 1468 } 1469 if (slowSizes) { 1470 slowSizeList = config.getHighResolutionOutputSizes(format); 1471 } 1472 if (fastSizeList != null && slowSizeList != null) { 1473 sizes = new Size[slowSizeList.length + fastSizeList.length]; 1474 System.arraycopy(fastSizeList, 0, sizes, 0, fastSizeList.length); 1475 System.arraycopy(slowSizeList, 0, sizes, fastSizeList.length, slowSizeList.length); 1476 } else if (fastSizeList != null) { 1477 sizes = fastSizeList; 1478 } else if (slowSizeList != null) { 1479 sizes = slowSizeList; 1480 } 1481 break; 1482 case Input: 1483 sizes = config.getInputSizes(format); 1484 break; 1485 default: 1486 throw new IllegalArgumentException("direction must be output or input"); 1487 } 1488 1489 if (sizes == null) { 1490 sizes = new Size[0]; 1491 } 1492 1493 return sizes; 1494 } 1495 1496 /** 1497 * Get available AE target fps ranges. 1498 * 1499 * @return Empty int array if aeAvailableTargetFpsRanges is invalid. 1500 */ 1501 @SuppressWarnings("raw") getAeAvailableTargetFpsRangesChecked()1502 public Range<Integer>[] getAeAvailableTargetFpsRangesChecked() { 1503 Key<Range<Integer>[]> key = 1504 CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES; 1505 Range<Integer>[] fpsRanges = getValueFromKeyNonNull(key); 1506 1507 if (fpsRanges == null) { 1508 return new Range[0]; 1509 } 1510 1511 // Round down to 2 boundary if it is not integer times of 2, to avoid array out of bound 1512 // in case the above check fails. 1513 int fpsRangeLength = fpsRanges.length; 1514 int minFps, maxFps; 1515 long maxFrameDuration = getMaxFrameDurationChecked(); 1516 for (int i = 0; i < fpsRangeLength; i += 1) { 1517 minFps = fpsRanges[i].getLower(); 1518 maxFps = fpsRanges[i].getUpper(); 1519 checkTrueForKey(key, " min fps must be no larger than max fps!", 1520 minFps > 0 && maxFps >= minFps); 1521 long maxDuration = (long) (1e9 / minFps); 1522 checkTrueForKey(key, String.format( 1523 " the frame duration %d for min fps %d must smaller than maxFrameDuration %d", 1524 maxDuration, minFps, maxFrameDuration), maxDuration <= maxFrameDuration); 1525 } 1526 return fpsRanges; 1527 } 1528 1529 /** 1530 * Get the highest supported target FPS range. 1531 * Prioritizes maximizing the min FPS, then the max FPS without lowering min FPS. 1532 */ getAeMaxTargetFpsRange()1533 public Range<Integer> getAeMaxTargetFpsRange() { 1534 Range<Integer>[] fpsRanges = getAeAvailableTargetFpsRangesChecked(); 1535 1536 Range<Integer> targetRange = fpsRanges[0]; 1537 // Assume unsorted list of target FPS ranges, so use two passes, first maximize min FPS 1538 for (Range<Integer> candidateRange : fpsRanges) { 1539 if (candidateRange.getLower() > targetRange.getLower()) { 1540 targetRange = candidateRange; 1541 } 1542 } 1543 // Then maximize max FPS while not lowering min FPS 1544 for (Range<Integer> candidateRange : fpsRanges) { 1545 if (candidateRange.getLower() >= targetRange.getLower() && 1546 candidateRange.getUpper() > targetRange.getUpper()) { 1547 targetRange = candidateRange; 1548 } 1549 } 1550 return targetRange; 1551 } 1552 1553 /** 1554 * Get max frame duration. 1555 * 1556 * @return 0 if maxFrameDuration is null 1557 */ getMaxFrameDurationChecked()1558 public long getMaxFrameDurationChecked() { 1559 Key<Long> key = 1560 CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION; 1561 Long maxDuration = getValueFromKeyNonNull(key); 1562 1563 if (maxDuration == null) { 1564 return 0; 1565 } 1566 1567 return maxDuration; 1568 } 1569 1570 /** 1571 * Get available minimal frame durations for a given format. 1572 * 1573 * @param format One of the format from {@link ImageFormat}. 1574 * @return HashMap of minimal frame durations for different sizes, empty HashMap 1575 * if availableMinFrameDurations is null. 1576 */ getAvailableMinFrameDurationsForFormatChecked(int format)1577 public HashMap<Size, Long> getAvailableMinFrameDurationsForFormatChecked(int format) { 1578 1579 HashMap<Size, Long> minDurationMap = new HashMap<Size, Long>(); 1580 1581 Key<StreamConfigurationMap> key = 1582 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP; 1583 StreamConfigurationMap config = getValueFromKeyNonNull(key); 1584 1585 if (config == null) { 1586 return minDurationMap; 1587 } 1588 1589 for (android.util.Size size : getAvailableSizesForFormatChecked(format, 1590 StreamDirection.Output)) { 1591 long minFrameDuration = config.getOutputMinFrameDuration(format, size); 1592 1593 if (minFrameDuration != 0) { 1594 minDurationMap.put(new Size(size.getWidth(), size.getHeight()), minFrameDuration); 1595 } 1596 } 1597 1598 return minDurationMap; 1599 } 1600 getAvailableEdgeModesChecked()1601 public int[] getAvailableEdgeModesChecked() { 1602 Key<int[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES; 1603 int[] edgeModes = getValueFromKeyNonNull(key); 1604 1605 if (edgeModes == null) { 1606 return new int[0]; 1607 } 1608 1609 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(edgeModes)); 1610 // Full device should always include OFF and FAST 1611 if (isHardwareLevelAtLeastFull()) { 1612 checkTrueForKey(key, "Full device must contain OFF and FAST edge modes", 1613 modeList.contains(CameraMetadata.EDGE_MODE_OFF) && 1614 modeList.contains(CameraMetadata.EDGE_MODE_FAST)); 1615 } 1616 1617 if (isHardwareLevelAtLeastLimited()) { 1618 // FAST and HIGH_QUALITY mode must be both present or both not present 1619 List<Integer> coupledModes = Arrays.asList(new Integer[] { 1620 CameraMetadata.EDGE_MODE_FAST, 1621 CameraMetadata.EDGE_MODE_HIGH_QUALITY 1622 }); 1623 checkTrueForKey( 1624 key, " FAST and HIGH_QUALITY mode must both present or both not present", 1625 containsAllOrNone(modeList, coupledModes)); 1626 } 1627 1628 return edgeModes; 1629 } 1630 getAvailableShadingModesChecked()1631 public int[] getAvailableShadingModesChecked() { 1632 Key<int[]> key = CameraCharacteristics.SHADING_AVAILABLE_MODES; 1633 int[] shadingModes = getValueFromKeyNonNull(key); 1634 1635 if (shadingModes == null) { 1636 return new int[0]; 1637 } 1638 1639 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(shadingModes)); 1640 // Full device should always include OFF and FAST 1641 if (isHardwareLevelAtLeastFull()) { 1642 checkTrueForKey(key, "Full device must contain OFF and FAST shading modes", 1643 modeList.contains(CameraMetadata.SHADING_MODE_OFF) && 1644 modeList.contains(CameraMetadata.SHADING_MODE_FAST)); 1645 } 1646 1647 if (isHardwareLevelAtLeastLimited()) { 1648 // FAST and HIGH_QUALITY mode must be both present or both not present 1649 List<Integer> coupledModes = Arrays.asList(new Integer[] { 1650 CameraMetadata.SHADING_MODE_FAST, 1651 CameraMetadata.SHADING_MODE_HIGH_QUALITY 1652 }); 1653 checkTrueForKey( 1654 key, " FAST and HIGH_QUALITY mode must both present or both not present", 1655 containsAllOrNone(modeList, coupledModes)); 1656 } 1657 1658 return shadingModes; 1659 } 1660 getAvailableNoiseReductionModesChecked()1661 public int[] getAvailableNoiseReductionModesChecked() { 1662 Key<int[]> key = 1663 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES; 1664 int[] noiseReductionModes = getValueFromKeyNonNull(key); 1665 1666 if (noiseReductionModes == null) { 1667 return new int[0]; 1668 } 1669 1670 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(noiseReductionModes)); 1671 // Full device should always include OFF and FAST 1672 if (isHardwareLevelAtLeastFull()) { 1673 1674 checkTrueForKey(key, "Full device must contain OFF and FAST noise reduction modes", 1675 modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_OFF) && 1676 modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_FAST)); 1677 } 1678 1679 if (isHardwareLevelAtLeastLimited()) { 1680 // FAST and HIGH_QUALITY mode must be both present or both not present 1681 List<Integer> coupledModes = Arrays.asList(new Integer[] { 1682 CameraMetadata.NOISE_REDUCTION_MODE_FAST, 1683 CameraMetadata.NOISE_REDUCTION_MODE_HIGH_QUALITY 1684 }); 1685 checkTrueForKey( 1686 key, " FAST and HIGH_QUALITY mode must both present or both not present", 1687 containsAllOrNone(modeList, coupledModes)); 1688 } 1689 return noiseReductionModes; 1690 } 1691 1692 /** 1693 * Get value of key android.control.aeCompensationStep and do the sanity check. 1694 * 1695 * @return default value if the value is null. 1696 */ getAeCompensationStepChecked()1697 public Rational getAeCompensationStepChecked() { 1698 Key<Rational> key = 1699 CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP; 1700 Rational compensationStep = getValueFromKeyNonNull(key); 1701 1702 if (compensationStep == null) { 1703 // Return default step. 1704 return CONTROL_AE_COMPENSATION_STEP_DEFAULT; 1705 } 1706 1707 // Legacy devices don't have a minimum step requirement 1708 if (isHardwareLevelAtLeastLimited()) { 1709 float compensationStepF = 1710 (float) compensationStep.getNumerator() / compensationStep.getDenominator(); 1711 checkTrueForKey(key, " value must be no more than 1/2", compensationStepF <= 0.5f); 1712 } 1713 1714 return compensationStep; 1715 } 1716 1717 /** 1718 * Get value of key android.control.aeCompensationRange and do the sanity check. 1719 * 1720 * @return default value if the value is null or malformed. 1721 */ getAeCompensationRangeChecked()1722 public Range<Integer> getAeCompensationRangeChecked() { 1723 Key<Range<Integer>> key = 1724 CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE; 1725 Range<Integer> compensationRange = getValueFromKeyNonNull(key); 1726 Rational compensationStep = getAeCompensationStepChecked(); 1727 float compensationStepF = compensationStep.floatValue(); 1728 final Range<Integer> DEFAULT_RANGE = Range.create( 1729 (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN / compensationStepF), 1730 (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX / compensationStepF)); 1731 final Range<Integer> ZERO_RANGE = Range.create(0, 0); 1732 if (compensationRange == null) { 1733 return ZERO_RANGE; 1734 } 1735 1736 // Legacy devices don't have a minimum range requirement 1737 if (isHardwareLevelAtLeastLimited() && !compensationRange.equals(ZERO_RANGE)) { 1738 checkTrueForKey(key, " range value must be at least " + DEFAULT_RANGE 1739 + ", actual " + compensationRange + ", compensation step " + compensationStep, 1740 compensationRange.getLower() <= DEFAULT_RANGE.getLower() && 1741 compensationRange.getUpper() >= DEFAULT_RANGE.getUpper()); 1742 } 1743 1744 return compensationRange; 1745 } 1746 1747 /** 1748 * Get availableVideoStabilizationModes and do the sanity check. 1749 * 1750 * @return available video stabilization modes, empty array if it is unavailable. 1751 */ getAvailableVideoStabilizationModesChecked()1752 public int[] getAvailableVideoStabilizationModesChecked() { 1753 Key<int[]> key = 1754 CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES; 1755 int[] modes = getValueFromKeyNonNull(key); 1756 1757 if (modes == null) { 1758 return new int[0]; 1759 } 1760 1761 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1762 checkTrueForKey(key, " All device should support OFF mode", 1763 modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF)); 1764 checkArrayValuesInRange(key, modes, 1765 CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF, 1766 CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON); 1767 1768 return modes; 1769 } 1770 isVideoStabilizationSupported()1771 public boolean isVideoStabilizationSupported() { 1772 Integer[] videoStabModes = 1773 CameraTestUtils.toObject(getAvailableVideoStabilizationModesChecked()); 1774 return Arrays.asList(videoStabModes).contains( 1775 CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON); 1776 } 1777 1778 /** 1779 * Get availableOpticalStabilization and do the sanity check. 1780 * 1781 * @return available optical stabilization modes, empty array if it is unavailable. 1782 */ getAvailableOpticalStabilizationChecked()1783 public int[] getAvailableOpticalStabilizationChecked() { 1784 Key<int[]> key = 1785 CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION; 1786 int[] modes = getValueFromKeyNonNull(key); 1787 1788 if (modes == null) { 1789 return new int[0]; 1790 } 1791 1792 checkArrayValuesInRange(key, modes, 1793 CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_OFF, 1794 CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON); 1795 1796 return modes; 1797 } 1798 1799 /** 1800 * Get the scaler's max digital zoom ({@code >= 1.0f}) ratio between crop and active array 1801 * @return the max zoom ratio, or {@code 1.0f} if the value is unavailable 1802 */ getAvailableMaxDigitalZoomChecked()1803 public float getAvailableMaxDigitalZoomChecked() { 1804 Key<Float> key = 1805 CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM; 1806 1807 Float maxZoom = getValueFromKeyNonNull(key); 1808 if (maxZoom == null) { 1809 return 1.0f; 1810 } 1811 1812 checkTrueForKey(key, " max digital zoom should be no less than 1", 1813 maxZoom >= 1.0f && !Float.isNaN(maxZoom) && !Float.isInfinite(maxZoom)); 1814 1815 return maxZoom; 1816 } 1817 getAvailableSceneModesChecked()1818 public int[] getAvailableSceneModesChecked() { 1819 Key<int[]> key = 1820 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES; 1821 int[] modes = getValueFromKeyNonNull(key); 1822 1823 if (modes == null) { 1824 return new int[0]; 1825 } 1826 1827 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1828 // FACE_PRIORITY must be included if face detection is supported. 1829 if (areKeysAvailable(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT) && 1830 getMaxFaceCountChecked() > 0) { 1831 checkTrueForKey(key, " FACE_PRIORITY must be included if face detection is supported", 1832 modeList.contains(CameraMetadata.CONTROL_SCENE_MODE_FACE_PRIORITY)); 1833 } 1834 1835 return modes; 1836 } 1837 getAvailableEffectModesChecked()1838 public int[] getAvailableEffectModesChecked() { 1839 Key<int[]> key = 1840 CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS; 1841 int[] modes = getValueFromKeyNonNull(key); 1842 1843 if (modes == null) { 1844 return new int[0]; 1845 } 1846 1847 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1848 // OFF must be included. 1849 checkTrueForKey(key, " OFF must be included", 1850 modeList.contains(CameraMetadata.CONTROL_EFFECT_MODE_OFF)); 1851 1852 return modes; 1853 } 1854 1855 /** 1856 * Get and check the available color aberration modes 1857 * 1858 * @return the available color aberration modes 1859 */ getAvailableColorAberrationModesChecked()1860 public int[] getAvailableColorAberrationModesChecked() { 1861 Key<int[]> key = 1862 CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES; 1863 int[] modes = getValueFromKeyNonNull(key); 1864 1865 if (modes == null) { 1866 return new int[0]; 1867 } 1868 1869 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1870 checkTrueForKey(key, " Camera devices must always support either OFF or FAST mode", 1871 modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF) || 1872 modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_FAST)); 1873 1874 if (isHardwareLevelAtLeastLimited()) { 1875 // FAST and HIGH_QUALITY mode must be both present or both not present 1876 List<Integer> coupledModes = Arrays.asList(new Integer[] { 1877 CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_FAST, 1878 CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY 1879 }); 1880 checkTrueForKey( 1881 key, " FAST and HIGH_QUALITY mode must both present or both not present", 1882 containsAllOrNone(modeList, coupledModes)); 1883 } 1884 checkElementDistinct(key, modeList); 1885 checkArrayValuesInRange(key, modes, 1886 CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF, 1887 CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY); 1888 1889 return modes; 1890 } 1891 1892 /** 1893 * Get max pipeline depth and do the sanity check. 1894 * 1895 * @return max pipeline depth, default value if it is not available. 1896 */ getPipelineMaxDepthChecked()1897 public byte getPipelineMaxDepthChecked() { 1898 Key<Byte> key = 1899 CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH; 1900 Byte maxDepth = getValueFromKeyNonNull(key); 1901 1902 if (maxDepth == null) { 1903 return REQUEST_PIPELINE_MAX_DEPTH_MAX; 1904 } 1905 1906 checkTrueForKey(key, " max pipeline depth should be no larger than " 1907 + REQUEST_PIPELINE_MAX_DEPTH_MAX, maxDepth <= REQUEST_PIPELINE_MAX_DEPTH_MAX); 1908 1909 return maxDepth; 1910 } 1911 1912 /** 1913 * Get available lens shading modes. 1914 */ getAvailableLensShadingModesChecked()1915 public int[] getAvailableLensShadingModesChecked() { 1916 Key<int[]> key = 1917 CameraCharacteristics.SHADING_AVAILABLE_MODES; 1918 int[] modes = getValueFromKeyNonNull(key); 1919 if (modes == null) { 1920 return new int[0]; 1921 } 1922 1923 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1924 // FAST must be included. 1925 checkTrueForKey(key, " FAST must be included", 1926 modeList.contains(CameraMetadata.SHADING_MODE_FAST)); 1927 1928 if (isCapabilitySupported( 1929 CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING)) { 1930 checkTrueForKey(key, " OFF must be included for MANUAL_POST_PROCESSING devices", 1931 modeList.contains(CameraMetadata.SHADING_MODE_OFF)); 1932 } 1933 return modes; 1934 } 1935 1936 /** 1937 * Get available lens shading map modes. 1938 */ getAvailableLensShadingMapModesChecked()1939 public int[] getAvailableLensShadingMapModesChecked() { 1940 Key<int[]> key = 1941 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES; 1942 int[] modes = getValueFromKeyNonNull(key); 1943 if (modes == null) { 1944 return new int[0]; 1945 } 1946 1947 List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes)); 1948 1949 if (isCapabilitySupported( 1950 CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 1951 checkTrueForKey(key, " ON must be included for RAW capability devices", 1952 modeList.contains(CameraMetadata.STATISTICS_LENS_SHADING_MAP_MODE_ON)); 1953 } 1954 return modes; 1955 } 1956 1957 1958 /** 1959 * Get available capabilities and do the sanity check. 1960 * 1961 * @return reported available capabilities list, empty list if the value is unavailable. 1962 */ getAvailableCapabilitiesChecked()1963 public List<Integer> getAvailableCapabilitiesChecked() { 1964 Key<int[]> key = 1965 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES; 1966 int[] availableCaps = getValueFromKeyNonNull(key); 1967 List<Integer> capList; 1968 1969 if (availableCaps == null) { 1970 return new ArrayList<Integer>(); 1971 } 1972 1973 checkArrayValuesInRange(key, availableCaps, 1974 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, 1975 LAST_CAPABILITY_ENUM); 1976 capList = Arrays.asList(CameraTestUtils.toObject(availableCaps)); 1977 return capList; 1978 } 1979 1980 /** 1981 * Determine whether the current device supports a capability or not. 1982 * 1983 * @param capability (non-negative) 1984 * 1985 * @return {@code true} if the capability is supported, {@code false} otherwise. 1986 * 1987 * @throws IllegalArgumentException if {@code capability} was negative 1988 * 1989 * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES 1990 */ isCapabilitySupported(int capability)1991 public boolean isCapabilitySupported(int capability) { 1992 if (capability < 0) { 1993 throw new IllegalArgumentException("capability must be non-negative"); 1994 } 1995 1996 List<Integer> availableCapabilities = getAvailableCapabilitiesChecked(); 1997 1998 return availableCapabilities.contains(capability); 1999 } 2000 2001 /** 2002 * Determine whether or not all the {@code keys} are available characteristics keys 2003 * (as in {@link CameraCharacteristics#getKeys}. 2004 * 2005 * <p>If this returns {@code true}, then querying for this key from a characteristics 2006 * object will always return a non-{@code null} value.</p> 2007 * 2008 * @param keys collection of camera characteristics keys 2009 * @return whether or not all characteristics keys are available 2010 */ areCharacteristicsKeysAvailable( Collection<CameraCharacteristics.Key<?>> keys)2011 public final boolean areCharacteristicsKeysAvailable( 2012 Collection<CameraCharacteristics.Key<?>> keys) { 2013 return mCharacteristics.getKeys().containsAll(keys); 2014 } 2015 2016 /** 2017 * Determine whether or not all the {@code keys} are available result keys 2018 * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}. 2019 * 2020 * <p>If this returns {@code true}, then querying for this key from a result 2021 * object will almost always return a non-{@code null} value.</p> 2022 * 2023 * <p>In some cases (e.g. lens shading map), the request must have additional settings 2024 * configured in order for the key to correspond to a value.</p> 2025 * 2026 * @param keys collection of capture result keys 2027 * @return whether or not all result keys are available 2028 */ areResultKeysAvailable(Collection<CaptureResult.Key<?>> keys)2029 public final boolean areResultKeysAvailable(Collection<CaptureResult.Key<?>> keys) { 2030 return mCharacteristics.getAvailableCaptureResultKeys().containsAll(keys); 2031 } 2032 2033 /** 2034 * Determine whether or not all the {@code keys} are available request keys 2035 * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}. 2036 * 2037 * <p>If this returns {@code true}, then setting this key in the request builder 2038 * may have some effect (and if it's {@code false}, then the camera device will 2039 * definitely ignore it).</p> 2040 * 2041 * <p>In some cases (e.g. manual control of exposure), other keys must be also be set 2042 * in order for a key to take effect (e.g. control.mode set to OFF).</p> 2043 * 2044 * @param keys collection of capture request keys 2045 * @return whether or not all result keys are available 2046 */ areRequestKeysAvailable(Collection<CaptureRequest.Key<?>> keys)2047 public final boolean areRequestKeysAvailable(Collection<CaptureRequest.Key<?>> keys) { 2048 return mCharacteristics.getAvailableCaptureRequestKeys().containsAll(keys); 2049 } 2050 2051 /** 2052 * Determine whether or not all the {@code keys} are available characteristics keys 2053 * (as in {@link CameraCharacteristics#getKeys}. 2054 * 2055 * <p>If this returns {@code true}, then querying for this key from a characteristics 2056 * object will always return a non-{@code null} value.</p> 2057 * 2058 * @param keys one or more camera characteristic keys 2059 * @return whether or not all characteristics keys are available 2060 */ 2061 @SafeVarargs areKeysAvailable(CameraCharacteristics.Key<?>.... keys)2062 public final boolean areKeysAvailable(CameraCharacteristics.Key<?>... keys) { 2063 return areCharacteristicsKeysAvailable(Arrays.asList(keys)); 2064 } 2065 2066 /** 2067 * Determine whether or not all the {@code keys} are available result keys 2068 * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}. 2069 * 2070 * <p>If this returns {@code true}, then querying for this key from a result 2071 * object will almost always return a non-{@code null} value.</p> 2072 * 2073 * <p>In some cases (e.g. lens shading map), the request must have additional settings 2074 * configured in order for the key to correspond to a value.</p> 2075 * 2076 * @param keys one or more capture result keys 2077 * @return whether or not all result keys are available 2078 */ 2079 @SafeVarargs areKeysAvailable(CaptureResult.Key<?>.... keys)2080 public final boolean areKeysAvailable(CaptureResult.Key<?>... keys) { 2081 return areResultKeysAvailable(Arrays.asList(keys)); 2082 } 2083 2084 /** 2085 * Determine whether or not all the {@code keys} are available request keys 2086 * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}. 2087 * 2088 * <p>If this returns {@code true}, then setting this key in the request builder 2089 * may have some effect (and if it's {@code false}, then the camera device will 2090 * definitely ignore it).</p> 2091 * 2092 * <p>In some cases (e.g. manual control of exposure), other keys must be also be set 2093 * in order for a key to take effect (e.g. control.mode set to OFF).</p> 2094 * 2095 * @param keys one or more capture request keys 2096 * @return whether or not all result keys are available 2097 */ 2098 @SafeVarargs areKeysAvailable(CaptureRequest.Key<?>.... keys)2099 public final boolean areKeysAvailable(CaptureRequest.Key<?>... keys) { 2100 return areRequestKeysAvailable(Arrays.asList(keys)); 2101 } 2102 2103 /* 2104 * Determine if camera device support AE lock control 2105 * 2106 * @return {@code true} if AE lock control is supported 2107 */ isAeLockSupported()2108 public boolean isAeLockSupported() { 2109 return getValueFromKeyNonNull(CameraCharacteristics.CONTROL_AE_LOCK_AVAILABLE); 2110 } 2111 2112 /* 2113 * Determine if camera device support AWB lock control 2114 * 2115 * @return {@code true} if AWB lock control is supported 2116 */ isAwbLockSupported()2117 public boolean isAwbLockSupported() { 2118 return getValueFromKeyNonNull(CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE); 2119 } 2120 2121 2122 /* 2123 * Determine if camera device support manual lens shading map control 2124 * 2125 * @return {@code true} if manual lens shading map control is supported 2126 */ isManualLensShadingMapSupported()2127 public boolean isManualLensShadingMapSupported() { 2128 return areKeysAvailable(CaptureRequest.SHADING_MODE); 2129 } 2130 2131 /** 2132 * Determine if camera device support manual color correction control 2133 * 2134 * @return {@code true} if manual color correction control is supported 2135 */ isColorCorrectionSupported()2136 public boolean isColorCorrectionSupported() { 2137 return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_MODE); 2138 } 2139 2140 /** 2141 * Determine if camera device support manual tone mapping control 2142 * 2143 * @return {@code true} if manual tone mapping control is supported 2144 */ isManualToneMapSupported()2145 public boolean isManualToneMapSupported() { 2146 return areKeysAvailable(CaptureRequest.TONEMAP_MODE); 2147 } 2148 2149 /** 2150 * Determine if camera device support manual color aberration control 2151 * 2152 * @return {@code true} if manual color aberration control is supported 2153 */ isManualColorAberrationControlSupported()2154 public boolean isManualColorAberrationControlSupported() { 2155 return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE); 2156 } 2157 2158 /** 2159 * Determine if camera device support edge mode control 2160 * 2161 * @return {@code true} if edge mode control is supported 2162 */ isEdgeModeControlSupported()2163 public boolean isEdgeModeControlSupported() { 2164 return areKeysAvailable(CaptureRequest.EDGE_MODE); 2165 } 2166 2167 /** 2168 * Determine if camera device support hot pixel mode control 2169 * 2170 * @return {@code true} if hot pixel mode control is supported 2171 */ isHotPixelMapModeControlSupported()2172 public boolean isHotPixelMapModeControlSupported() { 2173 return areKeysAvailable(CaptureRequest.HOT_PIXEL_MODE); 2174 } 2175 2176 /** 2177 * Determine if camera device support noise reduction mode control 2178 * 2179 * @return {@code true} if noise reduction mode control is supported 2180 */ isNoiseReductionModeControlSupported()2181 public boolean isNoiseReductionModeControlSupported() { 2182 return areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE); 2183 } 2184 2185 /** 2186 * Get max number of output raw streams and do the basic sanity check. 2187 * 2188 * @return reported max number of raw output stream 2189 */ getMaxNumOutputStreamsRawChecked()2190 public int getMaxNumOutputStreamsRawChecked() { 2191 Integer maxNumStreams = 2192 getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW); 2193 if (maxNumStreams == null) 2194 return 0; 2195 return maxNumStreams; 2196 } 2197 2198 /** 2199 * Get max number of output processed streams and do the basic sanity check. 2200 * 2201 * @return reported max number of processed output stream 2202 */ getMaxNumOutputStreamsProcessedChecked()2203 public int getMaxNumOutputStreamsProcessedChecked() { 2204 Integer maxNumStreams = 2205 getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC); 2206 if (maxNumStreams == null) 2207 return 0; 2208 return maxNumStreams; 2209 } 2210 2211 /** 2212 * Get max number of output stalling processed streams and do the basic sanity check. 2213 * 2214 * @return reported max number of stalling processed output stream 2215 */ getMaxNumOutputStreamsProcessedStallChecked()2216 public int getMaxNumOutputStreamsProcessedStallChecked() { 2217 Integer maxNumStreams = 2218 getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING); 2219 if (maxNumStreams == null) 2220 return 0; 2221 return maxNumStreams; 2222 } 2223 2224 /** 2225 * Get lens facing and do the sanity check 2226 * @return lens facing, return default value (BACK) if value is unavailable. 2227 */ getLensFacingChecked()2228 public int getLensFacingChecked() { 2229 Key<Integer> key = 2230 CameraCharacteristics.LENS_FACING; 2231 Integer facing = getValueFromKeyNonNull(key); 2232 2233 if (facing == null) { 2234 return CameraCharacteristics.LENS_FACING_BACK; 2235 } 2236 2237 checkTrueForKey(key, " value is out of range ", 2238 facing >= CameraCharacteristics.LENS_FACING_FRONT && 2239 facing <= CameraCharacteristics.LENS_FACING_EXTERNAL); 2240 return facing; 2241 } 2242 2243 /** 2244 * Get maxCaptureStall frames or default value (if value doesn't exist) 2245 * @return maxCaptureStall frames or default value. 2246 */ getMaxCaptureStallOrDefault()2247 public int getMaxCaptureStallOrDefault() { 2248 Key<Integer> key = 2249 CameraCharacteristics.REPROCESS_MAX_CAPTURE_STALL; 2250 Integer value = getValueFromKeyNonNull(key); 2251 2252 if (value == null) { 2253 return MAX_REPROCESS_MAX_CAPTURE_STALL; 2254 } 2255 2256 checkTrueForKey(key, " value is out of range ", 2257 value >= 0 && 2258 value <= MAX_REPROCESS_MAX_CAPTURE_STALL); 2259 2260 return value; 2261 } 2262 2263 /** 2264 * Get the scaler's cropping type (center only or freeform) 2265 * @return cropping type, return default value (CENTER_ONLY) if value is unavailable 2266 */ getScalerCroppingTypeChecked()2267 public int getScalerCroppingTypeChecked() { 2268 Key<Integer> key = 2269 CameraCharacteristics.SCALER_CROPPING_TYPE; 2270 Integer value = getValueFromKeyNonNull(key); 2271 2272 if (value == null) { 2273 return CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY; 2274 } 2275 2276 checkTrueForKey(key, " value is out of range ", 2277 value >= CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY && 2278 value <= CameraCharacteristics.SCALER_CROPPING_TYPE_FREEFORM); 2279 2280 return value; 2281 } 2282 2283 /** 2284 * Check if the constrained high speed video is supported by the camera device. 2285 * The high speed FPS ranges and sizes are sanitized in 2286 * ExtendedCameraCharacteristicsTest#testConstrainedHighSpeedCapability. 2287 * 2288 * @return true if the constrained high speed video is supported, false otherwise. 2289 */ isConstrainedHighSpeedVideoSupported()2290 public boolean isConstrainedHighSpeedVideoSupported() { 2291 List<Integer> availableCapabilities = getAvailableCapabilitiesChecked(); 2292 return (availableCapabilities.contains( 2293 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO)); 2294 } 2295 2296 /** 2297 * Check if this camera device is a logical multi-camera backed by multiple 2298 * physical cameras. 2299 * 2300 * @return true if this is a logical multi-camera. 2301 */ isLogicalMultiCamera()2302 public boolean isLogicalMultiCamera() { 2303 List<Integer> availableCapabilities = getAvailableCapabilitiesChecked(); 2304 return (availableCapabilities.contains( 2305 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)); 2306 } 2307 2308 /** 2309 * Check if this camera device is a monochrome camera with Y8 support. 2310 * 2311 * @return true if this is a monochrome camera with Y8 support. 2312 */ isMonochromeWithY8()2313 public boolean isMonochromeWithY8() { 2314 int[] supportedFormats = getAvailableFormats( 2315 StaticMetadata.StreamDirection.Output); 2316 return (isColorOutputSupported() 2317 && isCapabilitySupported( 2318 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) 2319 && CameraTestUtils.contains(supportedFormats, ImageFormat.Y8)); 2320 } 2321 2322 /** 2323 * Check if high speed video is supported (HIGH_SPEED_VIDEO scene mode is 2324 * supported, supported high speed fps ranges and sizes are valid). 2325 * 2326 * @return true if high speed video is supported. 2327 */ isHighSpeedVideoSupported()2328 public boolean isHighSpeedVideoSupported() { 2329 List<Integer> sceneModes = 2330 Arrays.asList(CameraTestUtils.toObject(getAvailableSceneModesChecked())); 2331 if (sceneModes.contains(CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO)) { 2332 StreamConfigurationMap config = 2333 getValueFromKeyNonNull(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 2334 if (config == null) { 2335 return false; 2336 } 2337 Size[] availableSizes = config.getHighSpeedVideoSizes(); 2338 if (availableSizes.length == 0) { 2339 return false; 2340 } 2341 2342 for (Size size : availableSizes) { 2343 Range<Integer>[] availableFpsRanges = config.getHighSpeedVideoFpsRangesFor(size); 2344 if (availableFpsRanges.length == 0) { 2345 return false; 2346 } 2347 } 2348 2349 return true; 2350 } else { 2351 return false; 2352 } 2353 } 2354 2355 /** 2356 * Check if depth output is supported, based on the depth capability 2357 */ isDepthOutputSupported()2358 public boolean isDepthOutputSupported() { 2359 return isCapabilitySupported( 2360 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT); 2361 } 2362 2363 /** 2364 * Check if standard outputs (PRIVATE, YUV, JPEG) outputs are supported, based on the 2365 * backwards-compatible capability 2366 */ isColorOutputSupported()2367 public boolean isColorOutputSupported() { 2368 return isCapabilitySupported( 2369 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE); 2370 } 2371 2372 /** 2373 * Check if this camera is a MONOCHROME camera. 2374 */ isMonochromeCamera()2375 public boolean isMonochromeCamera() { 2376 return isCapabilitySupported( 2377 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME); 2378 } 2379 2380 /** 2381 * Check if optical black regions key is supported. 2382 */ isOpticalBlackRegionSupported()2383 public boolean isOpticalBlackRegionSupported() { 2384 return areKeysAvailable(CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS); 2385 } 2386 2387 /** 2388 * Check if HEIC format is supported 2389 */ isHeicSupported()2390 public boolean isHeicSupported() { 2391 int[] formats = getAvailableFormats(StaticMetadata.StreamDirection.Output); 2392 return CameraTestUtils.contains(formats, ImageFormat.HEIC); 2393 } 2394 2395 /** 2396 * Check if the dynamic black level is supported. 2397 * 2398 * <p> 2399 * Note that: This also indicates if the white level is supported, as dynamic black and white 2400 * level must be all supported or none of them is supported. 2401 * </p> 2402 */ isDynamicBlackLevelSupported()2403 public boolean isDynamicBlackLevelSupported() { 2404 return areKeysAvailable(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL); 2405 } 2406 2407 /** 2408 * Check if the enable ZSL key is supported. 2409 */ isEnableZslSupported()2410 public boolean isEnableZslSupported() { 2411 return areKeysAvailable(CaptureRequest.CONTROL_ENABLE_ZSL); 2412 } 2413 2414 /** 2415 * Check if AF scene change key is supported. 2416 */ isAfSceneChangeSupported()2417 public boolean isAfSceneChangeSupported() { 2418 return areKeysAvailable(CaptureResult.CONTROL_AF_SCENE_CHANGE); 2419 } 2420 2421 /** 2422 * Check if OIS data mode is supported. 2423 */ isOisDataModeSupported()2424 public boolean isOisDataModeSupported() { 2425 int[] availableOisDataModes = mCharacteristics.get( 2426 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES); 2427 2428 if (availableOisDataModes == null) { 2429 return false; 2430 } 2431 2432 for (int mode : availableOisDataModes) { 2433 if (mode == CameraMetadata.STATISTICS_OIS_DATA_MODE_ON) { 2434 return true; 2435 } 2436 } 2437 2438 return false; 2439 } 2440 2441 /** 2442 * Check if distortion correction is supported. 2443 */ isDistortionCorrectionSupported()2444 public boolean isDistortionCorrectionSupported() { 2445 boolean distortionCorrectionSupported = false; 2446 int[] distortionModes = mCharacteristics.get( 2447 CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES); 2448 if (distortionModes == null) { 2449 return false; 2450 } 2451 2452 for (int mode : distortionModes) { 2453 if (mode != CaptureRequest.DISTORTION_CORRECTION_MODE_OFF) { 2454 return true; 2455 } 2456 } 2457 2458 return false; 2459 } 2460 2461 /** 2462 * Check if active physical camera Id metadata is supported. 2463 */ isActivePhysicalCameraIdSupported()2464 public boolean isActivePhysicalCameraIdSupported() { 2465 return areKeysAvailable(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID); 2466 } 2467 2468 /** 2469 * Get the value in index for a fixed-size array from a given key. 2470 * 2471 * <p>If the camera device is incorrectly reporting values, log a warning and return 2472 * the default value instead.</p> 2473 * 2474 * @param key Key to fetch 2475 * @param defaultValue Default value to return if camera device uses invalid values 2476 * @param name Human-readable name for the array index (logging only) 2477 * @param index Array index of the subelement 2478 * @param size Expected fixed size of the array 2479 * 2480 * @return The value reported by the camera device, or the defaultValue otherwise. 2481 */ getArrayElementOrDefault(Key<?> key, T defaultValue, String name, int index, int size)2482 private <T> T getArrayElementOrDefault(Key<?> key, T defaultValue, String name, int index, 2483 int size) { 2484 T elementValue = getArrayElementCheckRangeNonNull( 2485 key, 2486 index, 2487 size); 2488 2489 if (elementValue == null) { 2490 failKeyCheck(key, 2491 "had no valid " + name + " value; using default of " + defaultValue); 2492 elementValue = defaultValue; 2493 } 2494 2495 return elementValue; 2496 } 2497 2498 /** 2499 * Fetch an array sub-element from an array value given by a key. 2500 * 2501 * <p> 2502 * Prints a warning if the sub-element was null. 2503 * </p> 2504 * 2505 * <p>Use for variable-size arrays since this does not check the array size.</p> 2506 * 2507 * @param key Metadata key to look up 2508 * @param element A non-negative index value. 2509 * @return The array sub-element, or null if the checking failed. 2510 */ getArrayElementNonNull(Key<?> key, int element)2511 private <T> T getArrayElementNonNull(Key<?> key, int element) { 2512 return getArrayElementCheckRangeNonNull(key, element, IGNORE_SIZE_CHECK); 2513 } 2514 2515 /** 2516 * Fetch an array sub-element from an array value given by a key. 2517 * 2518 * <p> 2519 * Prints a warning if the array size does not match the size, or if the sub-element was null. 2520 * </p> 2521 * 2522 * @param key Metadata key to look up 2523 * @param element The index in [0,size) 2524 * @param size A positive size value or otherwise {@value #IGNORE_SIZE_CHECK} 2525 * @return The array sub-element, or null if the checking failed. 2526 */ getArrayElementCheckRangeNonNull(Key<?> key, int element, int size)2527 private <T> T getArrayElementCheckRangeNonNull(Key<?> key, int element, int size) { 2528 Object array = getValueFromKeyNonNull(key); 2529 2530 if (array == null) { 2531 // Warning already printed 2532 return null; 2533 } 2534 2535 if (size != IGNORE_SIZE_CHECK) { 2536 int actualLength = Array.getLength(array); 2537 if (actualLength != size) { 2538 failKeyCheck(key, 2539 String.format("had the wrong number of elements (%d), expected (%d)", 2540 actualLength, size)); 2541 return null; 2542 } 2543 } 2544 2545 @SuppressWarnings("unchecked") 2546 T val = (T) Array.get(array, element); 2547 2548 if (val == null) { 2549 failKeyCheck(key, "had a null element at index" + element); 2550 return null; 2551 } 2552 2553 return val; 2554 } 2555 2556 /** 2557 * Gets the key, logging warnings for null values. 2558 */ getValueFromKeyNonNull(Key<T> key)2559 public <T> T getValueFromKeyNonNull(Key<T> key) { 2560 if (key == null) { 2561 throw new IllegalArgumentException("key was null"); 2562 } 2563 2564 T value = mCharacteristics.get(key); 2565 2566 if (value == null) { 2567 failKeyCheck(key, "was null"); 2568 } 2569 2570 return value; 2571 } 2572 checkArrayValuesInRange(Key<int[]> key, int[] array, int min, int max)2573 private void checkArrayValuesInRange(Key<int[]> key, int[] array, int min, int max) { 2574 for (int value : array) { 2575 checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max), 2576 value <= max && value >= min); 2577 } 2578 } 2579 checkArrayValuesInRange(Key<byte[]> key, byte[] array, byte min, byte max)2580 private void checkArrayValuesInRange(Key<byte[]> key, byte[] array, byte min, byte max) { 2581 for (byte value : array) { 2582 checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max), 2583 value <= max && value >= min); 2584 } 2585 } 2586 2587 /** 2588 * Check the uniqueness of the values in a list. 2589 * 2590 * @param key The key to be checked 2591 * @param list The list contains the value of the key 2592 */ checkElementDistinct(Key<U> key, List<T> list)2593 private <U, T> void checkElementDistinct(Key<U> key, List<T> list) { 2594 // Each size must be distinct. 2595 Set<T> sizeSet = new HashSet<T>(list); 2596 checkTrueForKey(key, "Each size must be distinct", sizeSet.size() == list.size()); 2597 } 2598 checkTrueForKey(Key<T> key, String message, boolean condition)2599 private <T> void checkTrueForKey(Key<T> key, String message, boolean condition) { 2600 if (!condition) { 2601 failKeyCheck(key, message); 2602 } 2603 } 2604 2605 /* Helper function to check if the coupled modes are either all present or all non-present */ containsAllOrNone(Collection<T> observedModes, Collection<T> coupledModes)2606 private <T> boolean containsAllOrNone(Collection<T> observedModes, Collection<T> coupledModes) { 2607 if (observedModes.containsAll(coupledModes)) { 2608 return true; 2609 } 2610 for (T mode : coupledModes) { 2611 if (observedModes.contains(mode)) { 2612 return false; 2613 } 2614 } 2615 return true; 2616 } 2617 failKeyCheck(Key<T> key, String message)2618 private <T> void failKeyCheck(Key<T> key, String message) { 2619 // TODO: Consider only warning once per key/message combination if it's too spammy. 2620 // TODO: Consider offering other options such as throwing an assertion exception 2621 String failureCause = String.format("The static info key '%s' %s", key.getName(), message); 2622 switch (mLevel) { 2623 case WARN: 2624 Log.w(TAG, failureCause); 2625 break; 2626 case COLLECT: 2627 mCollector.addMessage(failureCause); 2628 break; 2629 case ASSERT: 2630 Assert.fail(failureCause); 2631 default: 2632 throw new UnsupportedOperationException("Unhandled level " + mLevel); 2633 } 2634 } 2635 } 2636