1 /*
2  * Copyright (C) 2016 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.devcamera;
17 
18 import android.app.Activity;
19 import android.content.Context;
20 import android.graphics.ImageFormat;
21 import android.graphics.Rect;
22 import android.graphics.SurfaceTexture;
23 import android.hardware.camera2.CameraCharacteristics;
24 import android.hardware.camera2.CameraManager;
25 import android.hardware.camera2.CameraMetadata;
26 import android.hardware.camera2.CaptureRequest;
27 import android.hardware.camera2.CaptureResult;
28 import android.hardware.camera2.params.StreamConfigurationMap;
29 import android.os.Build;
30 import android.util.DisplayMetrics;
31 import android.util.Log;
32 import android.util.Range;
33 import android.util.Size;
34 import android.util.SizeF;
35 import android.view.SurfaceHolder;
36 import android.view.WindowManager;
37 
38 public class CameraDeviceReport {
39     private static final String TAG = "DevCamera_INFO";
40 
41     // Note: we actually need the activity to get window information
printReport(Activity activity, boolean firstCameraOnly)42     public static void printReport(Activity activity, boolean firstCameraOnly) {
43         printDisplayInfo(activity);
44         printCameraSystemInfo(activity, firstCameraOnly);
45     }
46 
47     /**
48      * Print out information about all cameras.
49      */
printCameraSystemInfo(Activity activity, boolean firstCameraOnly)50     private static void printCameraSystemInfo(Activity activity, boolean firstCameraOnly) {
51         CameraManager cameraMgr = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); // "camera"
52         String[] cameralist;
53         try {
54             cameralist = cameraMgr.getCameraIdList();
55             Log.v(TAG, "Number of cameras:" + cameralist.length);
56         } catch (Exception e) {
57             Log.e(TAG, "Could not get camera ID list: "+e);
58             return;
59         }
60         for (String cameraId : cameralist) {
61             printCameraInfo(cameraMgr, cameraId);
62             if (firstCameraOnly) {
63                 break;
64             }
65         }
66     }
67 
68     /**
69      * Print out information about a specific camera.
70      */
printCameraInfo(CameraManager manager, String id)71     private static void printCameraInfo(CameraManager manager, String id) {
72         Log.v(TAG, "============= CAMERA " + id + " INFO =============");
73 
74         CameraCharacteristics p;
75         try {
76             p = manager.getCameraCharacteristics(id);
77         } catch (Exception e) {
78             Log.e(TAG, "Could not get getCameraCharacteristics");
79             return;
80         }
81         // dumpsys media.camera
82 
83         // Print out various CameraCharacteristics.
84         Rect size = p.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
85         if (size != null) {
86             Log.v(TAG, "SENSOR_INFO_ACTIVE_ARRAY_SIZE: "
87                     + size.width() + "x" + size.height());
88         } else {
89             Log.v(TAG, "SENSOR_INFO_ACTIVE_ARRAY_SIZE: null");
90         }
91 
92         Size size2 = p.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);
93         Log.v(TAG, "SENSOR_INFO_PIXEL_ARRAY_SIZE: " + size2.getWidth() + "x" + size2.getHeight());
94 
95         SizeF size3 = p.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
96         Log.v(TAG, "SENSOR_INFO_PHYSICAL_SIZE: " + size3.getWidth() + "x" + size3.getHeight());
97 
98 
99         int sensorOrientation = p.get(CameraCharacteristics.SENSOR_ORIENTATION);
100         Log.v(TAG, "SENSOR_ORIENTATION: " + sensorOrientation);
101 
102         Log.v(TAG, "SENSOR_INFO_TIMESTAMP_SOURCE: " +
103                 getTimestampSourceName(p.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE)));
104 
105         Log.v(TAG, "LENS_INFO_FOCUS_DISTANCE_CALIBRATION: " +
106                 getFocusDistanceCalibrationName(p.get(CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION)));
107 
108         int[] faceModes = p.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
109         Log.v(TAG, "STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES: ");
110         for (int i = 0; i < faceModes.length; i++) {
111             switch (faceModes[i]) {
112                 case CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_OFF:
113                     Log.v(TAG, "  STATISTICS_FACE_DETECT_MODE_OFF");
114                     break;
115                 case CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_SIMPLE:
116                     Log.v(TAG, "  STATISTICS_FACE_DETECT_MODE_SIMPLE");
117                     break;
118                 case CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_FULL:
119                     Log.v(TAG, "  STATISTICS_FACE_DETECT_MODE_FULL");
120                     break;
121                 default:
122                     Log.v(TAG, "  STATISTICS_FACE_DETECT_MODE_? (unknown)");
123             }
124         }
125 
126         Log.v(TAG, "STATISTICS_INFO_MAX_FACE_COUNT: " + p.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT));
127 
128         Log.v(TAG, "REQUEST_PIPELINE_MAX_DEPTH: "
129                 + p.get(CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH));
130 
131         Log.v(TAG, "REQUEST_MAX_NUM_OUTPUT_RAW: "
132                 + p.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW));
133         Log.v(TAG, "REQUEST_MAX_NUM_OUTPUT_PROC: "
134                 + p.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC));
135         Log.v(TAG, "REQUEST_MAX_NUM_OUTPUT_PROC_STALLING: "
136                 + p.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING));
137 
138         Log.v(TAG, "EDGE_AVAILABLE_EDGE_MODES: "
139                 + intsToString(p.get(CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES)));
140 
141         Log.v(TAG, "NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES: "
142                 + intsToString(p.get(CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)));
143 
144         Log.v(TAG, "REQUEST_MAX_NUM_OUTPUT_PROC_STALLING: "
145                 + p.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING));
146 
147 
148         // REQUEST_AVAILABLE_CAPABILITIES
149         boolean mHasReprocessing = false;
150         {
151             Log.v(TAG, "CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES:");
152             for (int item : p.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)) {
153                 Log.v(TAG, "  " + item + " = " + getCapabilityName(item));
154                 if (item == 4 || item == 7) {
155                     mHasReprocessing = true;
156                 }
157             }
158         }
159 
160         StreamConfigurationMap map = p.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
161         {
162             int[] formats = map.getOutputFormats();
163             Log.v(TAG, "number of output formats: " + formats.length);
164             for (int i = 0; i < formats.length; i++) {
165                 Log.v(TAG, "output sizes for format " + formats[i] +
166                         " = ImageFormat." + getFormatName(formats[i]) + " = " +
167                         ImageFormat.getBitsPerPixel(formats[i]) + " bits per pixel.");
168                 Size[] sizes = map.getOutputSizes(formats[i]);
169                 if (sizes != null) {
170                     Log.v(TAG, "    Size      Stall duration  Min frame duration");
171                     for (int j = 0; j < sizes.length; j++) {
172                         Log.v(TAG, String.format("  %10s  %7d ms %7d ms \n",
173                                 sizes[j].toString(),
174                                 map.getOutputStallDuration(formats[i], sizes[j]) / 1000000,
175                                 map.getOutputMinFrameDuration(formats[i], sizes[j]) / 1000000
176                         ));
177                     }
178                 }
179             }
180         }
181 
182         if (mHasReprocessing) {
183             int[] formats = map.getInputFormats();
184             Log.v(TAG, "number of input formats: " + formats.length);
185             for (int i = 0; i < formats.length; i++) {
186                 Size[] sizes = map.getInputSizes(formats[i]);
187                 Log.v(TAG, "input sizes for format " + formats[i] + " = ImageFormat."
188                         + getFormatName(formats[i]) + " are: " + sizesToString(sizes));
189             }
190         }
191 
192         {
193             Size[] sizes = map.getOutputSizes(SurfaceHolder.class);
194             Log.v(TAG, "output sizes for SurfaceHolder.class are: " + sizesToString(sizes));
195         }
196 
197         {
198             Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
199             Log.v(TAG, "output sizes for SurfaceTexture.class are: " + sizesToString(sizes));
200         }
201 
202         // JPEG thumbnail sizes
203         {
204             Size[] sizes = p.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES);
205             Log.v(TAG, "JPEG thumbnail sizes: " + sizesToString(sizes));
206         }
207 
208         // REQUEST HARDWARE LEVEL
209         {
210             int level = p.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
211             Log.v(TAG, "CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL: " + getHardwareLevelName(level));
212         }
213 
214 
215         // REQUEST CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
216         {
217             Log.v(TAG, "CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES:");
218             for (Range<Integer> item : p.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES)) {
219                 Log.v(TAG, "  " + item);
220             }
221         }
222         // SENSOR_INFO_EXPOSURE_TIME_RANGE
223         {
224             Range<Long> rr = p.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
225             Log.v(TAG, "CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE: " + rr);
226         }
227 
228 
229         // CAPTURE REQUEST KEYS
230         {
231             String keys = "";
232             for (CaptureRequest.Key key : p.getAvailableCaptureRequestKeys()) {
233                 keys += key.getName() + "   ";
234             }
235             Log.v(TAG, "CameraCharacteristics.getAvailableCaptureRequestKeys() = " + keys);
236         }
237 
238         // CAPTURE RESULT KEYS
239         {
240             String keys = "";
241             for (CaptureResult.Key key : p.getAvailableCaptureResultKeys()) {
242                 keys += key.getName() + "   ";
243             }
244             Log.v(TAG, "CameraCharacteristics.getAvailableCaptureResultKeys() = " + keys);
245         }
246 
247     }
248 
sizesToString(Size[] sizes)249     public static String sizesToString(Size[] sizes) {
250         String result = "";
251         if (sizes != null) {
252             for (int j = 0; j < sizes.length; j++) {
253                 result += sizes[j].toString() + " ";
254             }
255         }
256         return result;
257     }
258 
intsToString(int[] modes)259     public static String intsToString(int[] modes) {
260         String result = "";
261         if (modes != null) {
262             for (int j = 0; j < modes.length; j++) {
263                 result += modes[j] + " ";
264             }
265         }
266         return result;
267     }
268 
getTimestampSourceName(Integer level)269     public static String getTimestampSourceName(Integer level) {
270         if (level == null) return "null";
271         switch (level) {
272             case CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME:
273                 return "SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME";
274             case CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN:
275                 return "SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN";
276         }
277         return "Unknown";
278     }
279 
getFocusDistanceCalibrationName(Integer level)280     public static String getFocusDistanceCalibrationName(Integer level) {
281         if (level == null) return "null";
282         switch (level) {
283             case CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE:
284                 return "LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE";
285             case CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED:
286                 return "LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED";
287             case CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED:
288                 return "LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED";
289         }
290         return "Unknown";
291     }
292 
getCapabilityName(int format)293     public static String getCapabilityName(int format) {
294         switch (format) {
295             case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:
296                 return "REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE";
297             case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
298                 return "REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR";
299             case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
300                 return "REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING";
301             case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW:
302                 return "REQUEST_AVAILABLE_CAPABILITIES_RAW";
303             case 4:
304                 return "REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING";
305             case 5:
306                 return "REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS";
307             case 6:
308                 return "REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE";
309             case 7:
310                 return "REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING";
311             case 8:
312                 return "REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT";
313         }
314         return "Unknown";
315     }
316 
getHardwareLevelName(int level)317     public static String getHardwareLevelName(int level) {
318         switch (level) {
319             case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL:
320                 return "INFO_SUPPORTED_HARDWARE_LEVEL_FULL";
321             case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED:
322                 return "INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED";
323             case CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY:
324                 return "INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY";
325         }
326         return "Unknown";
327     }
328 
329 
getFormatName(int format)330     public static String getFormatName(int format) {
331         switch (format) {
332             // Android M
333             //case ImageFormat.PRIVATE:
334             //    return "PRIVATE";
335             // Android L
336             case ImageFormat.JPEG:
337                 return "JPEG";
338             case ImageFormat.RGB_565:
339                 return "RGB_565";
340             case ImageFormat.NV16:
341                 return "NV16";
342             case ImageFormat.YUY2:
343                 return "YUY2";
344             case ImageFormat.YV12:
345                 return "YV12";
346             case ImageFormat.NV21:
347                 return "NV21";
348             case ImageFormat.YUV_420_888:
349                 return "YUV_420_888";
350             case ImageFormat.RAW_SENSOR:
351                 return "RAW_SENSOR";
352             case ImageFormat.RAW10:
353                 return "RAW10";
354         }
355         return "Unknown";
356     }
357 
358 
359     /**
360      * Print out various information about the device display.
361      */
printDisplayInfo(Activity activity)362     private static void printDisplayInfo(Activity activity) {
363         Log.v(TAG, "============= DEVICE  INFO =============");
364         Log.v(TAG, "Build.DEVICE = " + Build.DEVICE);
365         Log.v(TAG, "Build.FINGERPRINT = " + Build.FINGERPRINT);
366         Log.v(TAG, "Build.BRAND = " + Build.BRAND);
367         Log.v(TAG, "Build.MODEL = " + Build.MODEL);
368         Log.v(TAG, "Build.PRODUCT = " + Build.PRODUCT);
369         Log.v(TAG, "Build.MANUFACTURER = " + Build.MANUFACTURER);
370         Log.v(TAG, "Build.VERSION.CODENAME = " + Build.VERSION.CODENAME);
371         Log.v(TAG, "Build.VERSION.SDK_INT = " + Build.VERSION.SDK_INT);
372 
373         Log.v(TAG, "============= DEVICE DISPLAY INFO =============");
374         WindowManager windowMgr = activity.getWindowManager();
375 
376         // Nexus 5 is 360dp * 567dp
377         // Each dp is 3 hardware pixels
378         Log.v(TAG, "screen width dp = " + activity.getResources().getConfiguration().screenWidthDp);
379         Log.v(TAG, "screen height dp = " + activity.getResources().getConfiguration().screenHeightDp);
380 
381         DisplayMetrics metrics = new DisplayMetrics();
382         // With chrome subtracted.
383         windowMgr.getDefaultDisplay().getMetrics(metrics);
384         Log.v(TAG, "screen width pixels = " + metrics.widthPixels);
385         Log.v(TAG, "screen height pixels = " + metrics.heightPixels);
386         // Native.
387         windowMgr.getDefaultDisplay().getRealMetrics(metrics);
388         Log.v(TAG, "real screen width pixels = " + metrics.widthPixels);
389         Log.v(TAG, "real screen height pixels = " + metrics.heightPixels);
390 
391         Log.v(TAG, "refresh rate = " + windowMgr.getDefaultDisplay().getRefreshRate() + " Hz");
392     }
393 
394 
395 
396 }
397