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