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