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