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