• 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.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