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