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