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