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