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