1 /* 2 * Copyright (C) 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; 18 19 import android.content.Context; 20 import android.graphics.ImageFormat; 21 import android.hardware.camera2.CameraCharacteristics; 22 import android.hardware.camera2.CameraCharacteristics.Key; 23 import android.hardware.camera2.CameraManager; 24 import android.hardware.camera2.cts.helpers.CameraErrorCollector; 25 import android.hardware.camera2.params.BlackLevelPattern; 26 import android.hardware.camera2.params.ColorSpaceTransform; 27 import android.hardware.camera2.params.StreamConfigurationMap; 28 import android.test.AndroidTestCase; 29 import android.util.Log; 30 import android.util.Rational; 31 import android.util.Size; 32 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.List; 36 import java.util.Objects; 37 38 import static android.hardware.camera2.cts.helpers.AssertHelpers.*; 39 40 /** 41 * Extended tests for static camera characteristics. 42 */ 43 public class ExtendedCameraCharacteristicsTest extends AndroidTestCase { 44 private static final String TAG = "ExChrsTest"; // must be short so next line doesn't throw 45 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 46 47 private static final String PREFIX_ANDROID = "android"; 48 private static final String PREFIX_VENDOR = "com"; 49 50 /* 51 * Constants for static RAW metadata. 52 */ 53 private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5 54 55 private CameraManager mCameraManager; 56 private List<CameraCharacteristics> mCharacteristics; 57 private String[] mIds; 58 private CameraErrorCollector mCollector; 59 60 private static final Size VGA = new Size(640, 480); 61 62 /* 63 * HW Levels short hand 64 */ 65 private static final int LEGACY = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY; 66 private static final int LIMITED = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED; 67 private static final int FULL = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL; 68 private static final int OPT = Integer.MAX_VALUE; // For keys that are optional on all hardware levels. 69 70 /* 71 * Capabilities short hand 72 */ 73 private static final int NONE = -1; 74 private static final int BC = 75 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE; 76 private static final int MANUAL_SENSOR = 77 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR; 78 private static final int RAW = 79 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW; 80 81 @Override 82 public void setContext(Context context) { 83 super.setContext(context); 84 mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE); 85 assertNotNull("Can't connect to camera manager", mCameraManager); 86 } 87 88 @Override 89 protected void setUp() throws Exception { 90 super.setUp(); 91 mIds = mCameraManager.getCameraIdList(); 92 mCharacteristics = new ArrayList<>(); 93 mCollector = new CameraErrorCollector(); 94 for (int i = 0; i < mIds.length; i++) { 95 CameraCharacteristics props = mCameraManager.getCameraCharacteristics(mIds[i]); 96 assertNotNull(String.format("Can't get camera characteristics from: ID %s", mIds[i]), 97 props); 98 mCharacteristics.add(props); 99 } 100 } 101 102 @Override 103 protected void tearDown() throws Exception { 104 mCharacteristics = null; 105 106 try { 107 mCollector.verify(); 108 } catch (Throwable e) { 109 // When new Exception(e) is used, exception info will be printed twice. 110 throw new Exception(e.getMessage()); 111 } finally { 112 super.tearDown(); 113 } 114 } 115 116 /** 117 * Test that the available stream configurations contain a few required formats and sizes. 118 */ 119 public void testAvailableStreamConfigs() { 120 int counter = 0; 121 for (CameraCharacteristics c : mCharacteristics) { 122 StreamConfigurationMap config = 123 c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 124 assertNotNull(String.format("No stream configuration map found for: ID %s", 125 mIds[counter]), config); 126 int[] outputFormats = config.getOutputFormats(); 127 128 // Check required formats exist (JPEG, and YUV_420_888). 129 assertArrayContains( 130 String.format("No valid YUV_420_888 preview formats found for: ID %s", 131 mIds[counter]), outputFormats, ImageFormat.YUV_420_888); 132 assertArrayContains(String.format("No JPEG image format for: ID %s", 133 mIds[counter]), outputFormats, ImageFormat.JPEG); 134 135 Size[] sizes = config.getOutputSizes(ImageFormat.YUV_420_888); 136 CameraTestUtils.assertArrayNotEmpty(sizes, 137 String.format("No sizes for preview format %x for: ID %s", 138 ImageFormat.YUV_420_888, mIds[counter])); 139 140 assertArrayContains(String.format( 141 "Required VGA size not found for format %x for: ID %s", 142 ImageFormat.YUV_420_888, mIds[counter]), sizes, VGA); 143 144 counter++; 145 } 146 } 147 148 /** 149 * Test {@link CameraCharacteristics#getKeys} 150 */ 151 public void testKeys() { 152 int counter = 0; 153 for (CameraCharacteristics c : mCharacteristics) { 154 mCollector.setCameraId(mIds[counter]); 155 156 if (VERBOSE) { 157 Log.v(TAG, "testKeys - testing characteristics for camera " + mIds[counter]); 158 } 159 160 List<CameraCharacteristics.Key<?>> allKeys = c.getKeys(); 161 assertNotNull("Camera characteristics keys must not be null", allKeys); 162 assertFalse("Camera characteristics keys must have at least 1 key", 163 allKeys.isEmpty()); 164 165 for (CameraCharacteristics.Key<?> key : allKeys) { 166 assertKeyPrefixValid(key.getName()); 167 168 // All characteristics keys listed must never be null 169 mCollector.expectKeyValueNotNull(c, key); 170 171 // TODO: add a check that key must not be @hide 172 } 173 174 /* 175 * List of keys that must be present in camera characteristics (not null). 176 * 177 * Keys for LIMITED, FULL devices might be available despite lacking either 178 * the hardware level or the capability. This is *OK*. This only lists the 179 * *minimal* requirements for a key to be listed. 180 * 181 * LEGACY devices are a bit special since they map to api1 devices, so we know 182 * for a fact most keys are going to be illegal there so they should never be 183 * available. 184 * 185 * (TODO: Codegen this) 186 */ 187 { 188 // (Key Name) (HW Level) (Capabilities <Var-Arg>) 189 expectKeyAvailable(c, CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES , LEGACY , BC ); 190 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES , LEGACY , BC ); 191 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES , LEGACY , BC ); 192 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES , LEGACY , BC ); 193 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE , LEGACY , BC ); 194 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP , LEGACY , BC ); 195 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES , LEGACY , BC ); 196 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS , LEGACY , BC ); 197 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES , LEGACY , BC ); 198 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES , LEGACY , BC ); 199 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES , LEGACY , BC ); 200 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AE , LEGACY , BC ); 201 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AF , LEGACY , BC ); 202 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB , LEGACY , BC ); 203 expectKeyAvailable(c, CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES , FULL , NONE ); 204 expectKeyAvailable(c, CameraCharacteristics.FLASH_INFO_AVAILABLE , LEGACY , BC ); 205 expectKeyAvailable(c, CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES , OPT , RAW ); 206 expectKeyAvailable(c, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL , LEGACY , BC ); 207 expectKeyAvailable(c, CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES , LEGACY , BC ); 208 expectKeyAvailable(c, CameraCharacteristics.LENS_FACING , LEGACY , BC ); 209 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES , FULL , MANUAL_SENSOR ); 210 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES , FULL , MANUAL_SENSOR ); 211 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS , LEGACY , BC ); 212 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION , LIMITED , MANUAL_SENSOR ); 213 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION , LIMITED , MANUAL_SENSOR ); 214 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE , LIMITED , MANUAL_SENSOR ); 215 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE , LIMITED , NONE ); 216 expectKeyAvailable(c, CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , LEGACY , BC ); 217 expectKeyAvailable(c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES , LEGACY , BC ); 218 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC , LEGACY , BC ); 219 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING , LEGACY , BC ); 220 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW , LEGACY , BC ); 221 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT , LEGACY , BC ); 222 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH , LEGACY , BC ); 223 expectKeyAvailable(c, CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM , LEGACY , BC ); 224 expectKeyAvailable(c, CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP , LEGACY , BC ); 225 expectKeyAvailable(c, CameraCharacteristics.SCALER_CROPPING_TYPE , LEGACY , BC ); 226 expectKeyAvailable(c, CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES , LEGACY , NONE ); 227 expectKeyAvailable(c, CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN , FULL , MANUAL_SENSOR, RAW ); 228 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1 , OPT , RAW ); 229 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2 , OPT , RAW ); 230 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM1 , OPT , RAW ); 231 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM2 , OPT , RAW ); 232 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX1 , OPT , RAW ); 233 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX2 , OPT , RAW ); 234 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE , LEGACY , BC, RAW ); 235 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT , FULL , RAW ); 236 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE , FULL , MANUAL_SENSOR ); 237 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION , FULL , MANUAL_SENSOR ); 238 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE , LEGACY , BC ); 239 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE , LEGACY , BC ); 240 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE , FULL , MANUAL_SENSOR ); 241 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL , OPT , RAW ); 242 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE , LEGACY , BC ); 243 expectKeyAvailable(c, CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY , FULL , MANUAL_SENSOR ); 244 expectKeyAvailable(c, CameraCharacteristics.SENSOR_ORIENTATION , LEGACY , BC ); 245 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1 , OPT , RAW ); 246 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2 , OPT , RAW ); 247 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES , LEGACY , BC ); 248 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES , OPT , RAW ); 249 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT , LEGACY , BC ); 250 expectKeyAvailable(c, CameraCharacteristics.SYNC_MAX_LATENCY , LEGACY , BC ); 251 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES , FULL , MANUAL_SENSOR ); 252 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS , FULL , MANUAL_SENSOR ); 253 254 // Future: Use column editors for modifying above, ignore line length to keep 1 key per line 255 256 // TODO: check that no other 'android' keys are listed in #getKeys if they aren't in the above list 257 } 258 259 counter++; 260 } 261 } 262 263 /** 264 * Test values for static metadata used by the RAW capability. 265 */ 266 public void testStaticRawCharacteristics() { 267 int counter = 0; 268 for (CameraCharacteristics c : mCharacteristics) { 269 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); 270 assertNotNull("android.request.availableCapabilities must never be null"); 271 if (!arrayContains(actualCapabilities, 272 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 273 Log.i(TAG, "RAW capability is not supported in camera " + counter++ + 274 ". Skip the test."); 275 continue; 276 } 277 278 Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 279 if (actualHwLevel != null && actualHwLevel == FULL) { 280 mCollector.expectKeyValueContains(c, 281 CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, 282 CameraCharacteristics.HOT_PIXEL_MODE_FAST); 283 } 284 mCollector.expectKeyValueContains(c, 285 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, false); 286 mCollector.expectKeyValueGreaterThan(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL, 287 MIN_ALLOWABLE_WHITELEVEL); 288 289 mCollector.expectKeyValueIsIn(c, 290 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT, 291 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB, 292 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG, 293 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG, 294 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR); 295 // TODO: SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB isn't supported yet. 296 297 mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1, 298 CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT, 299 CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN); 300 mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2, 301 (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT, 302 (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN); 303 304 Rational[] zeroes = new Rational[9]; 305 Arrays.fill(zeroes, Rational.ZERO); 306 307 ColorSpaceTransform zeroed = new ColorSpaceTransform(zeroes); 308 mCollector.expectNotEquals("Forward Matrix1 should not contain all zeroes.", zeroed, 309 c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX1)); 310 mCollector.expectNotEquals("Forward Matrix2 should not contain all zeroes.", zeroed, 311 c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX2)); 312 mCollector.expectNotEquals("Calibration Transform1 should not contain all zeroes.", 313 zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1)); 314 mCollector.expectNotEquals("Calibration Transform2 should not contain all zeroes.", 315 zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2)); 316 mCollector.expectNotEquals("Color Transform1 should not contain all zeroes.", 317 zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1)); 318 mCollector.expectNotEquals("Color Transform2 should not contain all zeroes.", 319 zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2)); 320 321 BlackLevelPattern blackLevel = mCollector.expectKeyValueNotNull(c, 322 CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN); 323 if (blackLevel != null) { 324 int[] blackLevelPattern = new int[BlackLevelPattern.COUNT]; 325 blackLevel.copyTo(blackLevelPattern, /*offset*/0); 326 Integer whitelevel = c.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL); 327 if (whitelevel != null) { 328 mCollector.expectValuesInRange("BlackLevelPattern", blackLevelPattern, 0, 329 whitelevel); 330 } else { 331 mCollector.addMessage( 332 "No WhiteLevel available, cannot check BlackLevelPattern range."); 333 } 334 } 335 336 // TODO: profileHueSatMap, and profileToneCurve aren't supported yet. 337 counter++; 338 } 339 } 340 341 /** 342 * Check key is present in characteristics if the hardware level is at least {@code hwLevel}; 343 * check that the key is present if the actual capabilities are one of {@code capabilities}. 344 * 345 * @return value of the {@code key} from {@code c} 346 */ 347 private <T> T expectKeyAvailable(CameraCharacteristics c, CameraCharacteristics.Key<T> key, 348 int hwLevel, int... capabilities) { 349 350 Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 351 assertNotNull("android.info.supportedHardwareLevel must never be null", actualHwLevel); 352 353 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); 354 assertNotNull("android.request.availableCapabilities must never be null"); 355 356 List<Key<?>> allKeys = c.getKeys(); 357 358 T value = c.get(key); 359 360 if (compareHardwareLevel(actualHwLevel, hwLevel) >= 0) { 361 mCollector.expectTrue( 362 String.format("Key (%s) must be in characteristics for this hardware level " + 363 "(required minimal HW level %s, actual HW level %s)", 364 key.getName(), toStringHardwareLevel(hwLevel), 365 toStringHardwareLevel(actualHwLevel)), 366 value != null); 367 mCollector.expectTrue( 368 String.format("Key (%s) must be in characteristics list of keys for this " + 369 "hardware level (required minimal HW level %s, actual HW level %s)", 370 key.getName(), toStringHardwareLevel(hwLevel), 371 toStringHardwareLevel(actualHwLevel)), 372 allKeys.contains(key)); 373 } else if (arrayContainsAnyOf(actualCapabilities, capabilities)) { 374 mCollector.expectTrue( 375 String.format("Key (%s) must be in characteristics for these capabilities " + 376 "(required capabilities %s, actual capabilities %s)", 377 key.getName(), Arrays.toString(capabilities), 378 Arrays.toString(actualCapabilities)), 379 value != null); 380 mCollector.expectTrue( 381 String.format("Key (%s) must be in characteristics list of keys for " + 382 "these capabilities (required capabilities %s, actual capabilities %s)", 383 key.getName(), Arrays.toString(capabilities), 384 Arrays.toString(actualCapabilities)), 385 allKeys.contains(key)); 386 } else { 387 if (actualHwLevel == LEGACY && hwLevel != OPT) { 388 if (value != null || allKeys.contains(key)) { 389 Log.w(TAG, String.format( 390 "Key (%s) is not required for LEGACY devices but still appears", 391 key.getName())); 392 } 393 } 394 // OK: Key may or may not be present. 395 } 396 return value; 397 } 398 399 private static boolean arrayContains(int[] arr, int needle) { 400 if (arr == null) { 401 return false; 402 } 403 404 for (int elem : arr) { 405 if (elem == needle) { 406 return true; 407 } 408 } 409 410 return false; 411 } 412 413 private static boolean arrayContainsAnyOf(int[] arr, int[] needles) { 414 for (int needle : needles) { 415 if (arrayContains(arr, needle)) { 416 return true; 417 } 418 } 419 return false; 420 } 421 422 /** 423 * The key name has a prefix of either "android." or "com."; other prefixes are not valid. 424 */ 425 private static void assertKeyPrefixValid(String keyName) { 426 assertStartsWithAnyOf( 427 "All metadata keys must start with 'android.' (built-in keys) " + 428 "or 'com.' (vendor-extended keys)", new String[] { 429 PREFIX_ANDROID + ".", 430 PREFIX_VENDOR + ".", 431 }, keyName); 432 } 433 434 private static void assertTrueForKey(String msg, CameraCharacteristics.Key<?> key, 435 boolean actual) { 436 assertTrue(msg + " (key = '" + key.getName() + "')", actual); 437 } 438 439 private static <T> void assertOneOf(String msg, T[] expected, T actual) { 440 for (int i = 0; i < expected.length; ++i) { 441 if (Objects.equals(expected[i], actual)) { 442 return; 443 } 444 } 445 446 fail(String.format("%s: (expected one of %s, actual %s)", 447 msg, Arrays.toString(expected), actual)); 448 } 449 450 private static <T> void assertStartsWithAnyOf(String msg, String[] expected, String actual) { 451 for (int i = 0; i < expected.length; ++i) { 452 if (actual.startsWith(expected[i])) { 453 return; 454 } 455 } 456 457 fail(String.format("%s: (expected to start with any of %s, but value was %s)", 458 msg, Arrays.toString(expected), actual)); 459 } 460 461 /** Return a positive int if left > right, 0 if left==right, negative int if left < right */ 462 private static int compareHardwareLevel(int left, int right) { 463 return remapHardwareLevel(left) - remapHardwareLevel(right); 464 } 465 466 /** Remap HW levels worst<->best, 0 = worst, 2 = best */ 467 private static int remapHardwareLevel(int level) { 468 switch (level) { 469 case OPT: 470 return Integer.MAX_VALUE; 471 case LEGACY: 472 return 0; // lowest 473 case LIMITED: 474 return 1; // second lowest 475 case FULL: 476 return 2; // best 477 } 478 479 fail("Unknown HW level: " + level); 480 return -1; 481 } 482 483 private static String toStringHardwareLevel(int level) { 484 switch (level) { 485 case LEGACY: 486 return "LEGACY"; 487 case LIMITED: 488 return "LIMITED"; 489 case FULL: 490 return "FULL"; 491 } 492 493 // unknown 494 Log.w(TAG, "Unknown hardware level " + level); 495 return Integer.toString(level); 496 } 497 } 498