1 /* 2 * Copyright (C) 2015 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 package com.android.cts.deviceinfo; 17 18 import android.content.Context; 19 import android.graphics.ColorSpace; 20 import android.graphics.ImageFormat; 21 import android.graphics.Rect; 22 import android.hardware.camera2.CameraAccessException; 23 import android.hardware.camera2.CameraCharacteristics; 24 import android.hardware.camera2.CameraManager; 25 import android.hardware.camera2.params.BlackLevelPattern; 26 import android.hardware.camera2.params.Capability; 27 import android.hardware.camera2.params.ColorSpaceProfiles; 28 import android.hardware.camera2.params.ColorSpaceTransform; 29 import android.hardware.camera2.params.DynamicRangeProfiles; 30 import android.hardware.camera2.params.MultiResolutionStreamConfigurationMap; 31 import android.hardware.camera2.params.MultiResolutionStreamInfo; 32 import android.hardware.camera2.params.StreamConfigurationMap; 33 import android.hardware.usb.UsbManager; 34 import android.media.CamcorderProfile; 35 import android.util.Log; 36 import android.util.Range; 37 import android.util.Rational; 38 import android.util.Size; 39 import android.util.SizeF; 40 41 import com.android.compatibility.common.deviceinfo.DeviceInfo; 42 import com.android.compatibility.common.util.DeviceInfoStore; 43 import com.android.internal.camera.flags.Flags; 44 45 import java.lang.reflect.Array; 46 import java.lang.reflect.Field; 47 import java.lang.reflect.GenericArrayType; 48 import java.lang.reflect.Modifier; 49 import java.lang.reflect.ParameterizedType; 50 import java.lang.reflect.Type; 51 import java.util.ArrayList; 52 import java.util.Collection; 53 import java.util.HashMap; 54 import java.util.HashSet; 55 import java.util.List; 56 import java.util.Set; 57 58 /** 59 * Camera information collector. 60 */ 61 public final class CameraDeviceInfo extends DeviceInfo { 62 private static final String TAG = "CameraDeviceInfo"; 63 64 private final static class CameraCharacteristicsStorer { 65 private CameraManager mCameraManager; 66 private DeviceInfoStore mStore; 67 CameraCharacteristicsStorer(CameraManager cameraManager, DeviceInfoStore store)68 public CameraCharacteristicsStorer(CameraManager cameraManager, DeviceInfoStore store) { 69 if (cameraManager == null || store == null) { 70 throw new IllegalArgumentException("can not create an CameraMetadataGetter object" 71 + " with null CameraManager or null DeviceInfoStore"); 72 } 73 74 mCameraManager = cameraManager; 75 mStore = store; 76 } 77 storeCameraInfo(String cameraId)78 public void storeCameraInfo(String cameraId) throws Exception { 79 try { 80 CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId); 81 mStore.startGroup(); // per camera chars 82 mStore.addResult("cameraId", cameraId); 83 storeCameraChars(chars); 84 mStore.endGroup(); // per camera chars 85 } catch (CameraAccessException e) { 86 Log.e(TAG, 87 "Unable to get camera camera static info, skip this camera, error: " 88 + e.getMessage()); 89 } 90 return; 91 } 92 storePhysicalCameraInfo(String cameraId, List<String> logicalCameras)93 public void storePhysicalCameraInfo(String cameraId, List<String> logicalCameras) 94 throws Exception { 95 try { 96 CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId); 97 mStore.startGroup(); // per camera chars 98 mStore.addResult("cameraId", cameraId); 99 mStore.addListResult("parentLogicalCameraIds", logicalCameras); 100 storeCameraChars(chars); 101 mStore.endGroup(); // per camera chars 102 } catch (CameraAccessException e) { 103 Log.e(TAG, 104 "Unable to get camera camera static info, skip this camera, error: " 105 + e.getMessage()); 106 } 107 return; 108 } 109 storeRational( Rational rat, String protoName)110 private void storeRational( 111 Rational rat, String protoName) throws Exception { 112 if (protoName == null) { 113 mStore.startGroup(); 114 } else { 115 mStore.startGroup(protoName); 116 } 117 mStore.addResult("numerator", rat.getNumerator()); 118 mStore.addResult("denominator", rat.getDenominator()); 119 mStore.endGroup(); 120 } 121 storeSize( Size size, String protoName)122 private void storeSize( 123 Size size, String protoName) throws Exception { 124 if (protoName == null) { 125 mStore.startGroup(); 126 } else { 127 mStore.startGroup(protoName); 128 } 129 mStore.addResult("width", size.getWidth()); 130 mStore.addResult("height", size.getHeight()); 131 mStore.endGroup(); 132 } 133 storeSizeF( SizeF size, String protoName)134 private void storeSizeF( 135 SizeF size, String protoName) throws Exception { 136 if (protoName == null) { 137 mStore.startGroup(); 138 } else { 139 mStore.startGroup(protoName); 140 } 141 mStore.addResult("width", size.getWidth()); 142 mStore.addResult("height", size.getHeight()); 143 mStore.endGroup(); 144 } 145 storeRect( Rect rect, String protoName)146 private void storeRect( 147 Rect rect, String protoName) throws Exception { 148 if (protoName == null) { 149 mStore.startGroup(); 150 } else { 151 mStore.startGroup(protoName); 152 } 153 mStore.addResult("left", rect.left); 154 mStore.addResult("right", rect.right); 155 mStore.addResult("top", rect.top); 156 mStore.addResult("bottom", rect.bottom); 157 mStore.endGroup(); 158 } 159 storeStreamConfigurationMap( StreamConfigurationMap map, String protoName)160 private void storeStreamConfigurationMap( 161 StreamConfigurationMap map, String protoName) throws Exception { 162 if (protoName == null) { 163 mStore.startGroup(); 164 } else { 165 mStore.startGroup(protoName); 166 } 167 168 int fmts[] = map.getOutputFormats(); 169 if (fmts != null) { 170 mStore.startArray("availableStreamConfigurations"); 171 for (int fi = 0; fi < Array.getLength(fmts); fi++) { 172 Size sizes[] = map.getOutputSizes(fmts[fi]); 173 if (sizes != null) { 174 for (int si = 0; si < Array.getLength(sizes); si++) { 175 mStore.startGroup(); 176 mStore.addResult("format", fmts[fi]); 177 mStore.addResult("width", sizes[si].getWidth()); 178 mStore.addResult("height", sizes[si].getHeight()); 179 mStore.addResult("input", false); 180 mStore.addResult("minFrameDuration", 181 map.getOutputMinFrameDuration(fmts[fi], sizes[si])); 182 mStore.endGroup(); 183 } 184 } 185 } 186 mStore.endArray(); 187 } 188 189 Size[] highSpeedVideoSizes = map.getHighSpeedVideoSizes(); 190 if (highSpeedVideoSizes != null && highSpeedVideoSizes.length > 0) { 191 mStore.startArray("availableHighSpeedVideoConfigurations"); 192 for (int i = 0; i < highSpeedVideoSizes.length; i++) { 193 Range<Integer>[] fpsRanges = map.getHighSpeedVideoFpsRangesFor( 194 highSpeedVideoSizes[i]); 195 if (fpsRanges != null && fpsRanges.length > 0) { 196 for (int j = 0; j < fpsRanges.length; j++) { 197 mStore.startGroup(); 198 mStore.addResult("width", highSpeedVideoSizes[i].getWidth()); 199 mStore.addResult("height", highSpeedVideoSizes[i].getHeight()); 200 mStore.addResult("minFps", fpsRanges[j].getLower()); 201 mStore.addResult("maxFps", fpsRanges[j].getUpper()); 202 mStore.endGroup(); 203 } 204 } 205 } 206 mStore.endArray(); 207 } 208 209 int inputFmts[] = map.getInputFormats(); 210 if (inputFmts != null && inputFmts.length > 0) { 211 mStore.startArray("availableInputConfigurations"); 212 for (int i = 0 ; i < inputFmts.length; i++) { 213 Size[] inputSizes = map.getInputSizes(inputFmts[i]); 214 if (inputSizes != null && inputSizes.length > 0) { 215 for (int j = 0; j < inputSizes.length; j++) { 216 mStore.startGroup(); 217 mStore.addResult("inputFormat", inputFmts[i]); 218 mStore.addResult("inputWidth", inputSizes[j].getWidth()); 219 mStore.addResult("inputHeight", inputSizes[j].getHeight()); 220 mStore.endGroup(); 221 } 222 } 223 } 224 mStore.endArray(); 225 226 mStore.startArray("availableInputOutputFormatsMap"); 227 for (int i = 0 ; i < inputFmts.length; i++) { 228 int[] outputFmts = map.getValidOutputFormatsForInput(inputFmts[i]); 229 if (outputFmts != null && outputFmts.length > 0) { 230 for (int j = 0; j < outputFmts.length; j++) { 231 mStore.startGroup(); 232 mStore.addResult("inputFormat", inputFmts[i]); 233 mStore.addResult("outputFormat", outputFmts[j]); 234 mStore.endGroup(); 235 } 236 } 237 } 238 mStore.endArray(); 239 } 240 241 mStore.endGroup(); 242 } 243 storeRangeFloat( Range<Float> range, String protoName)244 private void storeRangeFloat( 245 Range<Float> range, String protoName) throws Exception { 246 if (protoName == null) { 247 mStore.startGroup(); 248 } else { 249 mStore.startGroup(protoName); 250 } 251 mStore.addResult("lower", range.getLower()); 252 mStore.addResult("upper", range.getUpper()); 253 mStore.endGroup(); 254 } 255 storeRangeInt( Range<Integer> range, String protoName)256 private void storeRangeInt( 257 Range<Integer> range, String protoName) throws Exception { 258 if (protoName == null) { 259 mStore.startGroup(); 260 } else { 261 mStore.startGroup(protoName); 262 } 263 mStore.addResult("lower", range.getLower()); 264 mStore.addResult("upper", range.getUpper()); 265 mStore.endGroup(); 266 } 267 storeRangeLong( Range<Long> range, String protoName)268 private void storeRangeLong( 269 Range<Long> range, String protoName) throws Exception { 270 if (protoName == null) { 271 mStore.startGroup(); 272 } else { 273 mStore.startGroup(protoName); 274 } 275 mStore.addResult("lower", range.getLower()); 276 mStore.addResult("upper", range.getUpper()); 277 mStore.endGroup(); 278 } 279 storeColorSpaceProfiles( ColorSpaceProfiles profiles, String protoName)280 private void storeColorSpaceProfiles( 281 ColorSpaceProfiles profiles, String protoName) throws Exception { 282 if (protoName == null) { 283 mStore.startGroup(); 284 } else { 285 mStore.startGroup(protoName); 286 } 287 288 mStore.startArray("color_space_profiles"); 289 Set<ColorSpace.Named> supportedColorSpaces = profiles.getSupportedColorSpaces( 290 ImageFormat.UNKNOWN); 291 for (ColorSpace.Named colorSpace : supportedColorSpaces) { 292 mStore.startGroup(); 293 Set<Integer> supportedImageFormats = 294 profiles.getSupportedImageFormatsForColorSpace(colorSpace); 295 mStore.addResult("color_space", colorSpace.ordinal()); 296 mStore.startArray("image_formats"); 297 for (int imageFormat : supportedImageFormats) { 298 mStore.startGroup(); 299 Set<Long> supportedDynamicRangeProfiles = 300 profiles.getSupportedDynamicRangeProfiles(colorSpace, imageFormat); 301 mStore.addResult("image_format", imageFormat); 302 mStore.addArrayResult("dynamic_range_profiles", 303 supportedDynamicRangeProfiles.stream().mapToLong( 304 Long::longValue).toArray()); 305 mStore.endGroup(); 306 } 307 mStore.endArray(); 308 mStore.endGroup(); 309 } 310 mStore.endArray(); 311 mStore.endGroup(); 312 } 313 storeColorSpaceTransform( ColorSpaceTransform xform, String protoName)314 private void storeColorSpaceTransform( 315 ColorSpaceTransform xform, String protoName) throws Exception { 316 if (protoName == null) { 317 mStore.startGroup(); 318 } else { 319 mStore.startGroup(protoName); 320 } 321 322 mStore.startArray("elements"); 323 for (int row = 0; row < 3; row++) { 324 for (int col = 0; col < 3; col++) { 325 storeRational((Rational) xform.getElement(col, row), null); 326 } 327 } 328 mStore.endArray(); 329 mStore.endGroup(); 330 } 331 storeDynamicRangeProfiles( DynamicRangeProfiles profiles, String protoName)332 private void storeDynamicRangeProfiles( 333 DynamicRangeProfiles profiles, String protoName) throws Exception { 334 if (protoName == null) { 335 mStore.startGroup(); 336 } else { 337 mStore.startGroup(protoName); 338 } 339 mStore.addArrayResult("dynamic_range_profiles", 340 profiles.getSupportedProfiles().stream().mapToLong(Long::longValue).toArray()); 341 mStore.endGroup(); 342 } 343 storeBlackLevelPattern( BlackLevelPattern pat, String protoName)344 private void storeBlackLevelPattern( 345 BlackLevelPattern pat, String protoName) throws Exception { 346 if (protoName == null) { 347 mStore.startGroup(); 348 } else { 349 mStore.startGroup(protoName); 350 } 351 int patVals[] = new int[4]; 352 pat.copyTo(patVals, 0); 353 mStore.addArrayResult("black_level_pattern", patVals); 354 mStore.endGroup(); 355 } 356 storeExtendedSceneModeCapability(Capability cap, String protoName)357 private void storeExtendedSceneModeCapability(Capability cap, String protoName) 358 throws Exception { 359 if (protoName == null) { 360 mStore.startGroup(); 361 } else { 362 mStore.startGroup(protoName); 363 } 364 365 mStore.addResult("mode", cap.getMode()); 366 Size maxStreamingSize = cap.getMaxStreamingSize(); 367 mStore.addResult("maxStreamingWidth", maxStreamingSize.getWidth()); 368 mStore.addResult("maxStreamingHeight", maxStreamingSize.getHeight()); 369 Range<Float> zoomRatioRange = cap.getZoomRatioRange(); 370 mStore.addResult("minZoomRatio", zoomRatioRange.getLower()); 371 mStore.addResult("maxZoomRatio", zoomRatioRange.getUpper()); 372 mStore.endGroup(); 373 } 374 storeMultiResStreamConfigurationMap( MultiResolutionStreamConfigurationMap map, String protoName)375 private void storeMultiResStreamConfigurationMap( 376 MultiResolutionStreamConfigurationMap map, String protoName) throws Exception { 377 if (protoName == null) { 378 mStore.startGroup(); 379 } else { 380 mStore.startGroup(protoName); 381 } 382 383 mStore.startArray("availableMultiResolutionConfigurations"); 384 int[] fmts = map.getOutputFormats(); 385 if (fmts != null) { 386 for (int fi = 0; fi < Array.getLength(fmts); fi++) { 387 Collection<MultiResolutionStreamInfo> streamInfo = map.getOutputInfo(fmts[fi]); 388 if (streamInfo != null) { 389 for (MultiResolutionStreamInfo oneStream : streamInfo) { 390 mStore.startGroup(); 391 mStore.addResult("format", fmts[fi]); 392 mStore.addResult("width", oneStream.getWidth()); 393 mStore.addResult("height", oneStream.getHeight()); 394 mStore.addResult("cameraId", oneStream.getPhysicalCameraId()); 395 mStore.addResult("input", false); 396 mStore.endGroup(); 397 } 398 } 399 } 400 } 401 402 int[] inputFmts = map.getInputFormats(); 403 if (inputFmts != null) { 404 for (int fi = 0; fi < Array.getLength(inputFmts); fi++) { 405 Collection<MultiResolutionStreamInfo> streamInfo = 406 map.getInputInfo(inputFmts[fi]); 407 if (streamInfo != null) { 408 for (MultiResolutionStreamInfo oneStream : streamInfo) { 409 mStore.startGroup(); 410 mStore.addResult("format", inputFmts[fi]); 411 mStore.addResult("width", oneStream.getWidth()); 412 mStore.addResult("height", oneStream.getHeight()); 413 mStore.addResult("cameraId", oneStream.getPhysicalCameraId()); 414 mStore.addResult("input", true); 415 mStore.endGroup(); 416 } 417 } 418 } 419 } 420 mStore.endArray(); 421 mStore.endGroup(); 422 } 423 getKeyName(Object keyObj)424 private static String getKeyName(Object keyObj) { 425 return ((CameraCharacteristics.Key) keyObj).getName(); 426 } 427 getKeyValue(CameraCharacteristics chars, Object keyObj)428 private static Object getKeyValue(CameraCharacteristics chars, Object keyObj) { 429 return chars.get((CameraCharacteristics.Key) keyObj); 430 } 431 storeEntry(Type keyType, Object keyObj, CameraCharacteristics chars)432 private void storeEntry(Type keyType, Object keyObj, 433 CameraCharacteristics chars) throws Exception { 434 String keyName = getKeyName(keyObj); 435 String protoName = keyName.replace('.', '_'); 436 Object keyValue = getKeyValue(chars, keyObj); 437 if (keyValue == null) { 438 return; 439 } 440 441 if (keyType == int.class || keyType == Integer.class) { 442 mStore.addResult(protoName, (int) keyValue); 443 return; 444 } else if (keyType == float.class || keyType == Float.class) { 445 mStore.addResult(protoName, (float) keyValue); 446 return; 447 } else if (keyType == long.class || keyType == Long.class) { 448 mStore.addResult(protoName, (long) keyValue); 449 return; 450 } else if (keyType == double.class || keyType == Double.class) { 451 mStore.addResult(protoName, (double) keyValue); 452 return; 453 } else if (keyType == boolean.class || keyType == Boolean.class) { 454 mStore.addResult(protoName, (boolean) keyValue); 455 return; 456 } else if (keyType == byte.class || keyType == Byte.class) { 457 // Infostore does not support byte, convert to int32 and save 458 int intValue = (int) ((byte) keyValue); 459 mStore.addResult(protoName, intValue); 460 return; 461 } else if (keyType == Rational.class) { 462 storeRational((Rational) keyValue, protoName); 463 return; 464 } else if (keyType == Size.class) { 465 storeSize((Size) keyValue, protoName); 466 return; 467 } else if (keyType == SizeF.class) { 468 storeSizeF((SizeF) keyValue, protoName); 469 return; 470 } else if (keyType == Rect.class) { 471 storeRect((Rect) keyValue, protoName); 472 return; 473 } else if (keyType == StreamConfigurationMap.class) { 474 storeStreamConfigurationMap( 475 (StreamConfigurationMap) keyValue, protoName); 476 return; 477 } else if (keyType instanceof ParameterizedType && 478 ((ParameterizedType) keyType).getRawType() == Range.class && 479 ((ParameterizedType) keyType).getActualTypeArguments()[0] == Float.class) { 480 storeRangeFloat((Range<Float>) keyValue, protoName); 481 return; 482 } else if (keyType instanceof ParameterizedType && 483 ((ParameterizedType) keyType).getRawType() == Range.class && 484 ((ParameterizedType) keyType).getActualTypeArguments()[0] == Integer.class) { 485 storeRangeInt((Range<Integer>) keyValue, protoName); 486 return; 487 } else if (keyType instanceof ParameterizedType && 488 ((ParameterizedType) keyType).getRawType() == Range.class && 489 ((ParameterizedType) keyType).getActualTypeArguments()[0] == Long.class) { 490 storeRangeLong((Range<Long>) keyValue, protoName); 491 return; 492 } else if (keyType == ColorSpaceTransform.class) { 493 storeColorSpaceTransform((ColorSpaceTransform) keyValue, protoName); 494 return; 495 } else if (keyType == BlackLevelPattern.class) { 496 storeBlackLevelPattern((BlackLevelPattern) keyValue, protoName); 497 return; 498 } else if (keyType == MultiResolutionStreamConfigurationMap.class) { 499 storeMultiResStreamConfigurationMap( 500 (MultiResolutionStreamConfigurationMap) keyValue, protoName); 501 } else if (keyType == DynamicRangeProfiles.class) { 502 storeDynamicRangeProfiles((DynamicRangeProfiles) keyValue, protoName); 503 } else if (keyType == ColorSpaceProfiles.class) { 504 storeColorSpaceProfiles((ColorSpaceProfiles) keyValue, protoName); 505 } else { 506 Log.w(TAG, "Storing unsupported key type: " + keyType + 507 " for keyName: " + keyName); 508 return; 509 } 510 } 511 storeArrayEntry(Type keyType, Object keyObj, CameraCharacteristics chars)512 private void storeArrayEntry(Type keyType, Object keyObj, 513 CameraCharacteristics chars) throws Exception { 514 String keyName = getKeyName(keyObj); 515 String protoName = keyName.replace('.', '_'); 516 Object keyValue = getKeyValue(chars, keyObj); 517 if (keyValue == null) { 518 return; 519 } 520 521 int arrayLen = Array.getLength(keyValue); 522 if (arrayLen == 0) { 523 return; 524 } 525 Type elmtType = ((GenericArrayType) keyType).getGenericComponentType(); 526 527 if (elmtType == int.class) { 528 mStore.addArrayResult(protoName, (int[]) keyValue); 529 return; 530 } else if (elmtType == float.class) { 531 mStore.addArrayResult(protoName, (float[]) keyValue); 532 return; 533 } else if (elmtType == long.class) { 534 mStore.addArrayResult(protoName, (long[]) keyValue); 535 return; 536 } else if (elmtType == double.class) { 537 mStore.addArrayResult(protoName, (double[]) keyValue); 538 return; 539 } else if (elmtType == boolean.class) { 540 mStore.addArrayResult(protoName, (boolean[]) keyValue); 541 return; 542 } else if (elmtType == byte.class) { 543 // Infostore does not support byte, convert to int32 and save 544 int[] intValues = new int[arrayLen]; 545 for (int i = 0; i < arrayLen; i++) { 546 intValues[i] = (int) ((byte) Array.get(keyValue, i)); 547 } 548 mStore.addArrayResult(protoName, intValues); 549 return; 550 } else if (elmtType == Rational.class) { 551 mStore.startArray(protoName); 552 for (int i = 0; i < arrayLen; i++) { 553 storeRational((Rational) Array.get(keyValue, i), null); 554 } 555 mStore.endArray(); 556 return; 557 } else if (elmtType == Size.class) { 558 mStore.startArray(protoName); 559 for (int i = 0; i < arrayLen; i++) { 560 storeSize((Size) Array.get(keyValue, i), null); 561 } 562 mStore.endArray(); 563 return; 564 } else if (elmtType == Rect.class) { 565 mStore.startArray(protoName); 566 for (int i = 0; i < arrayLen; i++) { 567 storeRect((Rect) Array.get(keyValue, i), null); 568 } 569 mStore.endArray(); 570 return; 571 } else if (elmtType instanceof ParameterizedType && 572 ((ParameterizedType) elmtType).getRawType() == Range.class && 573 ((ParameterizedType) elmtType).getActualTypeArguments()[0] == Integer.class) { 574 mStore.startArray(protoName); 575 for (int i = 0; i < arrayLen; i++) { 576 storeRangeInt((Range<Integer>) Array.get(keyValue, i), null); 577 } 578 mStore.endArray(); 579 return; 580 } else if (elmtType == BlackLevelPattern.class) { 581 mStore.startArray(protoName); 582 for (int i = 0; i < arrayLen; i++) { 583 storeBlackLevelPattern((BlackLevelPattern) Array.get(keyValue, i), null); 584 } 585 mStore.endArray(); 586 return; 587 } else if (elmtType == Capability.class) { 588 mStore.startArray(protoName); 589 for (int i = 0; i < arrayLen; i++) { 590 storeExtendedSceneModeCapability((Capability) Array.get(keyValue, i), null); 591 } 592 mStore.endArray(); 593 return; 594 } else { 595 Log.w(TAG, "Storing unsupported array type: " + elmtType + 596 " for keyName: " + keyName); 597 return; 598 } 599 } 600 storeCameraChars( CameraCharacteristics chars)601 private void storeCameraChars( 602 CameraCharacteristics chars) throws Exception { 603 HashSet<String> charsKeyNames = getAllCharacteristicsKeyNames(); 604 Field[] allFields = chars.getClass().getDeclaredFields(); 605 for (Field field : allFields) { 606 if (Modifier.isPublic(field.getModifiers()) && 607 Modifier.isStatic(field.getModifiers()) && 608 field.getType() == CameraCharacteristics.Key.class && 609 field.getGenericType() instanceof ParameterizedType) { 610 ParameterizedType paramType = (ParameterizedType) field.getGenericType(); 611 Type[] argTypes = paramType.getActualTypeArguments(); 612 if (argTypes.length > 0) { 613 try { 614 Type keyType = argTypes[0]; 615 Object keyObj = field.get(chars); 616 String keyName = getKeyName(keyObj); 617 if (charsKeyNames.contains(keyName)) { 618 if (keyType instanceof GenericArrayType) { 619 storeArrayEntry(keyType, keyObj, chars); 620 } else { 621 storeEntry(keyType, keyObj, chars); 622 } 623 } 624 } catch (IllegalAccessException e) { 625 throw new IllegalStateException( 626 "Access error for field: " + field + ": ", e); 627 } 628 } 629 } 630 } 631 } 632 } 633 634 @Override collectDeviceInfo(DeviceInfoStore store)635 protected void collectDeviceInfo(DeviceInfoStore store) throws Exception { 636 store.addResult("profile_480p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)); 637 store.addResult("profile_720p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)); 638 store.addResult( 639 "profile_1080p", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)); 640 store.addResult("profile_cif", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF)); 641 store.addResult("profile_qcif", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QCIF)); 642 store.addResult("profile_qvga", CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)); 643 644 CameraManager cameraManager = (CameraManager) 645 getContext().getSystemService(Context.CAMERA_SERVICE); 646 647 UsbManager usbManager = getContext().getSystemService(UsbManager.class); 648 649 store.addResult("supports_device_webcam", usbManager.isUvcGadgetSupportEnabled()); 650 651 try { 652 String[] cameraIdList = cameraManager.getCameraIdList(); 653 HashMap<String, ArrayList<String>> physicalLogicalIdMap = 654 new HashMap<String, ArrayList<String>>(); 655 store.addResult("num_of_camera", cameraIdList.length); 656 if (cameraIdList.length > 0) { 657 CameraCharacteristicsStorer charsStorer = 658 new CameraCharacteristicsStorer(cameraManager, store); 659 store.startArray("per_camera_info"); 660 for (int i = 0; i < cameraIdList.length; i++) { 661 charsStorer.storeCameraInfo(cameraIdList[i]); 662 663 // Get the physical camera ids 664 CameraCharacteristics ch = cameraManager.getCameraCharacteristics( 665 cameraIdList[i]); 666 for (String physicalId : ch.getPhysicalCameraIds()) { 667 if (physicalLogicalIdMap.get(physicalId) == null) { 668 physicalLogicalIdMap.put(physicalId, new ArrayList<String>()); 669 } 670 physicalLogicalIdMap.get(physicalId).add(cameraIdList[i]); 671 } 672 } 673 store.endArray(); // per_camera_info 674 675 // Store characteristics for hidden physical camera ids 676 for (int i = 0; i < cameraIdList.length; ++i) { 677 physicalLogicalIdMap.remove(cameraIdList[i]); 678 } 679 if (physicalLogicalIdMap.size() > 0) { 680 store.addResult("num_of_hidden_physical_camera", physicalLogicalIdMap.size()); 681 store.startArray("per_hidden_physical_camera_info"); 682 for (String physicalId : physicalLogicalIdMap.keySet()) { 683 charsStorer.storePhysicalCameraInfo(physicalId, 684 physicalLogicalIdMap.get(physicalId)); 685 } 686 store.endArray(); // per_hidden_physical_camera_info 687 } 688 } 689 } catch (CameraAccessException e) { 690 Log.e(TAG, 691 "Unable to get camera camera ID list, error: " 692 + e.getMessage()); 693 } 694 } 695 696 /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ 697 * The key entries below this point are generated from metadata 698 * definitions in /system/media/camera/docs. Do not modify by hand or 699 * modify the comment blocks at the start or end. 700 *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/ 701 getAllCharacteristicsKeyNames()702 private static HashSet<String> getAllCharacteristicsKeyNames() { 703 HashSet<String> charsKeyNames = new HashSet<String>(); 704 charsKeyNames.add(CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES.getName()); 705 if (Flags.colorTemperature()) { 706 charsKeyNames.add(CameraCharacteristics.COLOR_CORRECTION_COLOR_TEMPERATURE_RANGE.getName()); 707 } 708 if (Flags.colorTemperature()) { 709 charsKeyNames.add(CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_MODES.getName()); 710 } 711 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES.getName()); 712 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES.getName()); 713 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES.getName()); 714 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE.getName()); 715 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP.getName()); 716 charsKeyNames.add(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES.getName()); 717 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS.getName()); 718 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES.getName()); 719 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES.getName()); 720 charsKeyNames.add(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES.getName()); 721 charsKeyNames.add(CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getName()); 722 charsKeyNames.add(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB.getName()); 723 charsKeyNames.add(CameraCharacteristics.CONTROL_MAX_REGIONS_AF.getName()); 724 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_LOCK_AVAILABLE.getName()); 725 charsKeyNames.add(CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE.getName()); 726 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_MODES.getName()); 727 charsKeyNames.add(CameraCharacteristics.CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE.getName()); 728 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_CAPABILITIES.getName()); 729 charsKeyNames.add(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE.getName()); 730 charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_SETTINGS_OVERRIDES.getName()); 731 charsKeyNames.add(CameraCharacteristics.CONTROL_AUTOFRAMING_AVAILABLE.getName()); 732 if (Flags.cameraAeModeLowLightBoost()) { 733 charsKeyNames.add(CameraCharacteristics.CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE.getName()); 734 } 735 if (Flags.aePriority()) { 736 charsKeyNames.add(CameraCharacteristics.CONTROL_AE_AVAILABLE_PRIORITY_MODES.getName()); 737 } 738 charsKeyNames.add(CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES.getName()); 739 charsKeyNames.add(CameraCharacteristics.FLASH_SINGLE_STRENGTH_MAX_LEVEL.getName()); 740 charsKeyNames.add(CameraCharacteristics.FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL.getName()); 741 charsKeyNames.add(CameraCharacteristics.FLASH_TORCH_STRENGTH_MAX_LEVEL.getName()); 742 charsKeyNames.add(CameraCharacteristics.FLASH_TORCH_STRENGTH_DEFAULT_LEVEL.getName()); 743 charsKeyNames.add(CameraCharacteristics.FLASH_INFO_AVAILABLE.getName()); 744 charsKeyNames.add(CameraCharacteristics.FLASH_INFO_STRENGTH_MAXIMUM_LEVEL.getName()); 745 charsKeyNames.add(CameraCharacteristics.FLASH_INFO_STRENGTH_DEFAULT_LEVEL.getName()); 746 charsKeyNames.add(CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES.getName()); 747 charsKeyNames.add(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES.getName()); 748 charsKeyNames.add(CameraCharacteristics.LENS_FACING.getName()); 749 charsKeyNames.add(CameraCharacteristics.LENS_POSE_REFERENCE.getName()); 750 charsKeyNames.add(CameraCharacteristics.LENS_DISTORTION_MAXIMUM_RESOLUTION.getName()); 751 charsKeyNames.add(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION.getName()); 752 charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES.getName()); 753 charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES.getName()); 754 charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS.getName()); 755 charsKeyNames.add(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION.getName()); 756 charsKeyNames.add(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE.getName()); 757 charsKeyNames.add(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE.getName()); 758 charsKeyNames.add(CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION.getName()); 759 charsKeyNames.add(CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES.getName()); 760 charsKeyNames.add(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW.getName()); 761 charsKeyNames.add(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC.getName()); 762 charsKeyNames.add(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING.getName()); 763 charsKeyNames.add(CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS.getName()); 764 charsKeyNames.add(CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH.getName()); 765 charsKeyNames.add(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT.getName()); 766 charsKeyNames.add(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES.getName()); 767 charsKeyNames.add(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES.getName()); 768 charsKeyNames.add(CameraCharacteristics.REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE.getName()); 769 charsKeyNames.add(CameraCharacteristics.REQUEST_AVAILABLE_COLOR_SPACE_PROFILES.getName()); 770 charsKeyNames.add(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM.getName()); 771 charsKeyNames.add(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP.getName()); 772 charsKeyNames.add(CameraCharacteristics.SCALER_CROPPING_TYPE.getName()); 773 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS.getName()); 774 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS.getName()); 775 charsKeyNames.add(CameraCharacteristics.SCALER_AVAILABLE_ROTATE_AND_CROP_MODES.getName()); 776 charsKeyNames.add(CameraCharacteristics.SCALER_DEFAULT_SECURE_IMAGE_SIZE.getName()); 777 charsKeyNames.add(CameraCharacteristics.SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP.getName()); 778 charsKeyNames.add(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION.getName()); 779 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_MAXIMUM_RESOLUTION_STREAM_COMBINATIONS.getName()); 780 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_TEN_BIT_OUTPUT_STREAM_COMBINATIONS.getName()); 781 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_PREVIEW_STABILIZATION_OUTPUT_STREAM_COMBINATIONS.getName()); 782 charsKeyNames.add(CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES.getName()); 783 charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_USE_CASE_STREAM_COMBINATIONS.getName()); 784 charsKeyNames.add(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1.getName()); 785 charsKeyNames.add(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2.getName()); 786 charsKeyNames.add(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1.getName()); 787 charsKeyNames.add(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2.getName()); 788 charsKeyNames.add(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1.getName()); 789 charsKeyNames.add(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2.getName()); 790 charsKeyNames.add(CameraCharacteristics.SENSOR_FORWARD_MATRIX1.getName()); 791 charsKeyNames.add(CameraCharacteristics.SENSOR_FORWARD_MATRIX2.getName()); 792 charsKeyNames.add(CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN.getName()); 793 charsKeyNames.add(CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY.getName()); 794 charsKeyNames.add(CameraCharacteristics.SENSOR_ORIENTATION.getName()); 795 charsKeyNames.add(CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES.getName()); 796 charsKeyNames.add(CameraCharacteristics.SENSOR_OPTICAL_BLACK_REGIONS.getName()); 797 charsKeyNames.add(CameraCharacteristics.SENSOR_READOUT_TIMESTAMP.getName()); 798 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE.getName()); 799 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE.getName()); 800 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT.getName()); 801 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE.getName()); 802 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION.getName()); 803 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE.getName()); 804 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE.getName()); 805 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL.getName()); 806 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE.getName()); 807 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_LENS_SHADING_APPLIED.getName()); 808 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE.getName()); 809 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION.getName()); 810 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION.getName()); 811 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION.getName()); 812 charsKeyNames.add(CameraCharacteristics.SENSOR_INFO_BINNING_FACTOR.getName()); 813 charsKeyNames.add(CameraCharacteristics.SHADING_AVAILABLE_MODES.getName()); 814 charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES.getName()); 815 charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT.getName()); 816 charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES.getName()); 817 charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES.getName()); 818 charsKeyNames.add(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES.getName()); 819 charsKeyNames.add(CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS.getName()); 820 charsKeyNames.add(CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES.getName()); 821 charsKeyNames.add(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL.getName()); 822 charsKeyNames.add(CameraCharacteristics.INFO_VERSION.getName()); 823 charsKeyNames.add(CameraCharacteristics.INFO_DEVICE_STATE_SENSOR_ORIENTATION_MAP.getName()); 824 charsKeyNames.add(CameraCharacteristics.INFO_SESSION_CONFIGURATION_QUERY_VERSION.getName()); 825 charsKeyNames.add(CameraCharacteristics.SYNC_MAX_LATENCY.getName()); 826 charsKeyNames.add(CameraCharacteristics.REPROCESS_MAX_CAPTURE_STALL.getName()); 827 charsKeyNames.add(CameraCharacteristics.DEPTH_DEPTH_IS_EXCLUSIVE.getName()); 828 charsKeyNames.add(CameraCharacteristics.LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE.getName()); 829 charsKeyNames.add(CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES.getName()); 830 charsKeyNames.add(CameraCharacteristics.AUTOMOTIVE_LOCATION.getName()); 831 charsKeyNames.add(CameraCharacteristics.AUTOMOTIVE_LENS_FACING.getName()); 832 833 return charsKeyNames; 834 } 835 836 /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ 837 * End generated code 838 *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ 839 } 840