blob: 02dfccd72adf0a5fb48df7b0dc9c2d2e4c6fd144 [file] [log] [blame]
Ruben Brunkfc6a26e2014-06-13 18:28:09 -07001/*
2 * Copyright (C) 2014 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
17package android.hardware.camera2.cts;
18
19import android.content.Context;
20import android.graphics.ImageFormat;
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -080021import android.graphics.SurfaceTexture;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070022import android.hardware.camera2.CameraCharacteristics;
Igor Murashkin12921f62014-07-11 16:22:17 -070023import android.hardware.camera2.CameraCharacteristics.Key;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070024import android.hardware.camera2.CameraManager;
Igor Murashkin12921f62014-07-11 16:22:17 -070025import android.hardware.camera2.cts.helpers.CameraErrorCollector;
Ruben Brunk43e260f2014-07-09 12:56:02 -070026import android.hardware.camera2.params.BlackLevelPattern;
27import android.hardware.camera2.params.ColorSpaceTransform;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070028import android.hardware.camera2.params.StreamConfigurationMap;
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -080029import android.media.ImageReader;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070030import android.test.AndroidTestCase;
Igor Murashkin12921f62014-07-11 16:22:17 -070031import android.util.Log;
Ruben Brunk43e260f2014-07-09 12:56:02 -070032import android.util.Rational;
Eino-Ville Talvala35a52702014-11-13 13:36:58 -080033import android.util.Range;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070034import android.util.Size;
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -080035import android.view.Surface;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070036
37import java.util.ArrayList;
Igor Murashkin12921f62014-07-11 16:22:17 -070038import java.util.Arrays;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070039import java.util.List;
Igor Murashkin12921f62014-07-11 16:22:17 -070040import java.util.Objects;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070041
42import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
43
44/**
45 * Extended tests for static camera characteristics.
46 */
47public class ExtendedCameraCharacteristicsTest extends AndroidTestCase {
Igor Murashkin12921f62014-07-11 16:22:17 -070048 private static final String TAG = "ExChrsTest"; // must be short so next line doesn't throw
49 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
50
51 private static final String PREFIX_ANDROID = "android";
52 private static final String PREFIX_VENDOR = "com";
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070053
Ruben Brunk43e260f2014-07-09 12:56:02 -070054 /*
55 * Constants for static RAW metadata.
56 */
57 private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5
58
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070059 private CameraManager mCameraManager;
60 private List<CameraCharacteristics> mCharacteristics;
61 private String[] mIds;
Igor Murashkin12921f62014-07-11 16:22:17 -070062 private CameraErrorCollector mCollector;
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070063
64 private static final Size VGA = new Size(640, 480);
65
Igor Murashkin12921f62014-07-11 16:22:17 -070066 /*
67 * HW Levels short hand
68 */
69 private static final int LEGACY = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
70 private static final int LIMITED = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
71 private static final int FULL = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
Yin-Chia Yeh84cbfd32014-09-18 10:16:12 -070072 private static final int OPT = Integer.MAX_VALUE; // For keys that are optional on all hardware levels.
Igor Murashkin12921f62014-07-11 16:22:17 -070073
74 /*
75 * Capabilities short hand
76 */
77 private static final int NONE = -1;
78 private static final int BC =
79 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
80 private static final int MANUAL_SENSOR =
81 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR;
Yin-Chia Yeha8237002014-12-18 10:20:19 -080082 private static final int MANUAL_POSTPROC =
83 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING;
Igor Murashkinb64273e2014-07-22 14:24:05 -070084 private static final int RAW =
85 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW;
Igor Murashkin12921f62014-07-11 16:22:17 -070086
Ruben Brunkfc6a26e2014-06-13 18:28:09 -070087 @Override
88 public void setContext(Context context) {
89 super.setContext(context);
90 mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
91 assertNotNull("Can't connect to camera manager", mCameraManager);
92 }
93
94 @Override
95 protected void setUp() throws Exception {
96 super.setUp();
97 mIds = mCameraManager.getCameraIdList();
98 mCharacteristics = new ArrayList<>();
Igor Murashkin12921f62014-07-11 16:22:17 -070099 mCollector = new CameraErrorCollector();
Ruben Brunkfc6a26e2014-06-13 18:28:09 -0700100 for (int i = 0; i < mIds.length; i++) {
101 CameraCharacteristics props = mCameraManager.getCameraCharacteristics(mIds[i]);
102 assertNotNull(String.format("Can't get camera characteristics from: ID %s", mIds[i]),
103 props);
104 mCharacteristics.add(props);
105 }
106 }
107
108 @Override
109 protected void tearDown() throws Exception {
Ruben Brunkfc6a26e2014-06-13 18:28:09 -0700110 mCharacteristics = null;
111
Igor Murashkin12921f62014-07-11 16:22:17 -0700112 try {
113 mCollector.verify();
114 } catch (Throwable e) {
115 // When new Exception(e) is used, exception info will be printed twice.
116 throw new Exception(e.getMessage());
117 } finally {
118 super.tearDown();
119 }
Ruben Brunkfc6a26e2014-06-13 18:28:09 -0700120 }
121
122 /**
123 * Test that the available stream configurations contain a few required formats and sizes.
124 */
125 public void testAvailableStreamConfigs() {
Ruben Brunkfc6a26e2014-06-13 18:28:09 -0700126 int counter = 0;
127 for (CameraCharacteristics c : mCharacteristics) {
128 StreamConfigurationMap config =
129 c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
130 assertNotNull(String.format("No stream configuration map found for: ID %s",
131 mIds[counter]), config);
132 int[] outputFormats = config.getOutputFormats();
133
134 // Check required formats exist (JPEG, and YUV_420_888).
135 assertArrayContains(
136 String.format("No valid YUV_420_888 preview formats found for: ID %s",
137 mIds[counter]), outputFormats, ImageFormat.YUV_420_888);
138 assertArrayContains(String.format("No JPEG image format for: ID %s",
139 mIds[counter]), outputFormats, ImageFormat.JPEG);
140
141 Size[] sizes = config.getOutputSizes(ImageFormat.YUV_420_888);
142 CameraTestUtils.assertArrayNotEmpty(sizes,
143 String.format("No sizes for preview format %x for: ID %s",
144 ImageFormat.YUV_420_888, mIds[counter]));
145
146 assertArrayContains(String.format(
147 "Required VGA size not found for format %x for: ID %s",
148 ImageFormat.YUV_420_888, mIds[counter]), sizes, VGA);
149
150 counter++;
151 }
152 }
Igor Murashkin12921f62014-07-11 16:22:17 -0700153
154 /**
155 * Test {@link CameraCharacteristics#getKeys}
156 */
157 public void testKeys() {
158 int counter = 0;
159 for (CameraCharacteristics c : mCharacteristics) {
160 mCollector.setCameraId(mIds[counter]);
161
162 if (VERBOSE) {
163 Log.v(TAG, "testKeys - testing characteristics for camera " + mIds[counter]);
164 }
165
166 List<CameraCharacteristics.Key<?>> allKeys = c.getKeys();
167 assertNotNull("Camera characteristics keys must not be null", allKeys);
168 assertFalse("Camera characteristics keys must have at least 1 key",
169 allKeys.isEmpty());
170
171 for (CameraCharacteristics.Key<?> key : allKeys) {
172 assertKeyPrefixValid(key.getName());
173
174 // All characteristics keys listed must never be null
175 mCollector.expectKeyValueNotNull(c, key);
176
177 // TODO: add a check that key must not be @hide
178 }
179
180 /*
181 * List of keys that must be present in camera characteristics (not null).
182 *
183 * Keys for LIMITED, FULL devices might be available despite lacking either
184 * the hardware level or the capability. This is *OK*. This only lists the
185 * *minimal* requirements for a key to be listed.
186 *
187 * LEGACY devices are a bit special since they map to api1 devices, so we know
188 * for a fact most keys are going to be illegal there so they should never be
189 * available.
190 *
191 * (TODO: Codegen this)
192 */
193 {
194 // (Key Name) (HW Level) (Capabilities <Var-Arg>)
Eino-Ville Talvalaafe590e2014-08-29 08:58:20 -0700195 expectKeyAvailable(c, CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES , LEGACY , BC );
Igor Murashkin12921f62014-07-11 16:22:17 -0700196 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES , LEGACY , BC );
197 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES , LEGACY , BC );
198 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES , LEGACY , BC );
199 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE , LEGACY , BC );
200 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP , LEGACY , BC );
201 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES , LEGACY , BC );
202 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS , LEGACY , BC );
203 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES , LEGACY , BC );
204 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES , LEGACY , BC );
205 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES , LEGACY , BC );
206 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AE , LEGACY , BC );
207 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AF , LEGACY , BC );
208 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB , LEGACY , BC );
209 expectKeyAvailable(c, CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES , FULL , NONE );
210 expectKeyAvailable(c, CameraCharacteristics.FLASH_INFO_AVAILABLE , LEGACY , BC );
Ruben Brunk43e260f2014-07-09 12:56:02 -0700211 expectKeyAvailable(c, CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES , OPT , RAW );
Igor Murashkin12921f62014-07-11 16:22:17 -0700212 expectKeyAvailable(c, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL , LEGACY , BC );
213 expectKeyAvailable(c, CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES , LEGACY , BC );
214 expectKeyAvailable(c, CameraCharacteristics.LENS_FACING , LEGACY , BC );
215 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES , FULL , MANUAL_SENSOR );
216 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES , FULL , MANUAL_SENSOR );
217 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS , LEGACY , BC );
218 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION , LIMITED , MANUAL_SENSOR );
219 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION , LIMITED , MANUAL_SENSOR );
220 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE , LIMITED , MANUAL_SENSOR );
221 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE , LIMITED , NONE );
Eino-Ville Talvalaafe590e2014-08-29 08:58:20 -0700222 expectKeyAvailable(c, CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , LEGACY , BC );
Igor Murashkin12921f62014-07-11 16:22:17 -0700223 expectKeyAvailable(c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES , LEGACY , BC );
224 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC , LEGACY , BC );
225 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING , LEGACY , BC );
226 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW , LEGACY , BC );
227 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT , LEGACY , BC );
228 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH , LEGACY , BC );
229 expectKeyAvailable(c, CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM , LEGACY , BC );
230 expectKeyAvailable(c, CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP , LEGACY , BC );
231 expectKeyAvailable(c, CameraCharacteristics.SCALER_CROPPING_TYPE , LEGACY , BC );
232 expectKeyAvailable(c, CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES , LEGACY , NONE );
Ruben Brunk43e260f2014-07-09 12:56:02 -0700233 expectKeyAvailable(c, CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN , FULL , MANUAL_SENSOR, RAW );
234 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1 , OPT , RAW );
235 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2 , OPT , RAW );
236 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM1 , OPT , RAW );
237 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM2 , OPT , RAW );
238 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX1 , OPT , RAW );
239 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX2 , OPT , RAW );
240 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE , LEGACY , BC, RAW );
Igor Murashkinb64273e2014-07-22 14:24:05 -0700241 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT , FULL , RAW );
Igor Murashkin12921f62014-07-11 16:22:17 -0700242 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE , FULL , MANUAL_SENSOR );
243 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION , FULL , MANUAL_SENSOR );
244 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE , LEGACY , BC );
245 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE , LEGACY , BC );
246 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE , FULL , MANUAL_SENSOR );
Ruben Brunk43e260f2014-07-09 12:56:02 -0700247 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL , OPT , RAW );
Eino-Ville Talvalaafe590e2014-08-29 08:58:20 -0700248 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE , LEGACY , BC );
Igor Murashkin12921f62014-07-11 16:22:17 -0700249 expectKeyAvailable(c, CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY , FULL , MANUAL_SENSOR );
250 expectKeyAvailable(c, CameraCharacteristics.SENSOR_ORIENTATION , LEGACY , BC );
Ruben Brunk43e260f2014-07-09 12:56:02 -0700251 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1 , OPT , RAW );
252 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2 , OPT , RAW );
Igor Murashkin12921f62014-07-11 16:22:17 -0700253 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES , LEGACY , BC );
Ruben Brunk43e260f2014-07-09 12:56:02 -0700254 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES , OPT , RAW );
Igor Murashkin12921f62014-07-11 16:22:17 -0700255 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT , LEGACY , BC );
256 expectKeyAvailable(c, CameraCharacteristics.SYNC_MAX_LATENCY , LEGACY , BC );
Yin-Chia Yeha8237002014-12-18 10:20:19 -0800257 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES , FULL , MANUAL_POSTPROC );
258 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS , FULL , MANUAL_POSTPROC );
Igor Murashkin12921f62014-07-11 16:22:17 -0700259
260 // Future: Use column editors for modifying above, ignore line length to keep 1 key per line
261
262 // TODO: check that no other 'android' keys are listed in #getKeys if they aren't in the above list
263 }
264
265 counter++;
266 }
267 }
268
269 /**
Ruben Brunk43e260f2014-07-09 12:56:02 -0700270 * Test values for static metadata used by the RAW capability.
271 */
272 public void testStaticRawCharacteristics() {
273 int counter = 0;
274 for (CameraCharacteristics c : mCharacteristics) {
275 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
Eino-Ville Talvala35a52702014-11-13 13:36:58 -0800276 assertNotNull("android.request.availableCapabilities must never be null",
277 actualCapabilities);
Ruben Brunk43e260f2014-07-09 12:56:02 -0700278 if (!arrayContains(actualCapabilities,
279 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
280 Log.i(TAG, "RAW capability is not supported in camera " + counter++ +
281 ". Skip the test.");
282 continue;
283 }
284
285 Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
286 if (actualHwLevel != null && actualHwLevel == FULL) {
287 mCollector.expectKeyValueContains(c,
288 CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
289 CameraCharacteristics.HOT_PIXEL_MODE_FAST);
290 }
291 mCollector.expectKeyValueContains(c,
292 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, false);
293 mCollector.expectKeyValueGreaterThan(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL,
294 MIN_ALLOWABLE_WHITELEVEL);
295
296 mCollector.expectKeyValueIsIn(c,
297 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
298 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
299 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
300 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
301 CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR);
302 // TODO: SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB isn't supported yet.
303
304 mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1,
305 CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
306 CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
307 mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2,
308 (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
309 (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
310
311 Rational[] zeroes = new Rational[9];
312 Arrays.fill(zeroes, Rational.ZERO);
313
314 ColorSpaceTransform zeroed = new ColorSpaceTransform(zeroes);
315 mCollector.expectNotEquals("Forward Matrix1 should not contain all zeroes.", zeroed,
316 c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX1));
317 mCollector.expectNotEquals("Forward Matrix2 should not contain all zeroes.", zeroed,
318 c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX2));
319 mCollector.expectNotEquals("Calibration Transform1 should not contain all zeroes.",
320 zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1));
321 mCollector.expectNotEquals("Calibration Transform2 should not contain all zeroes.",
322 zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2));
323 mCollector.expectNotEquals("Color Transform1 should not contain all zeroes.",
324 zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1));
325 mCollector.expectNotEquals("Color Transform2 should not contain all zeroes.",
326 zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2));
327
328 BlackLevelPattern blackLevel = mCollector.expectKeyValueNotNull(c,
329 CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
330 if (blackLevel != null) {
331 int[] blackLevelPattern = new int[BlackLevelPattern.COUNT];
332 blackLevel.copyTo(blackLevelPattern, /*offset*/0);
333 Integer whitelevel = c.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
334 if (whitelevel != null) {
335 mCollector.expectValuesInRange("BlackLevelPattern", blackLevelPattern, 0,
336 whitelevel);
337 } else {
338 mCollector.addMessage(
339 "No WhiteLevel available, cannot check BlackLevelPattern range.");
340 }
341 }
342
343 // TODO: profileHueSatMap, and profileToneCurve aren't supported yet.
344 counter++;
345 }
346 }
347
348 /**
Eino-Ville Talvala35a52702014-11-13 13:36:58 -0800349 * Test values for static metadata used by the BURST capability.
350 */
351 public void testStaticBurstCharacteristics() {
352 int counter = 0;
353 for (CameraCharacteristics c : mCharacteristics) {
354 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
355 assertNotNull("android.request.availableCapabilities must never be null",
356 actualCapabilities);
357
358 // Check if the burst capability is defined
359 boolean haveBurstCapability = arrayContains(actualCapabilities,
360 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
361
362 StreamConfigurationMap config =
363 c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
364 assertNotNull(String.format("No stream configuration map found for: ID %s",
365 mIds[counter]), config);
366
367 // Ensure that max YUV size matches max JPEG size
368 Size maxYuvSize = CameraTestUtils.getMaxSize(
369 config.getOutputSizes(ImageFormat.YUV_420_888));
370 Size maxJpegSize = CameraTestUtils.getMaxSize(config.getOutputSizes(ImageFormat.JPEG));
371
372 boolean haveMaxYuv = maxYuvSize != null ?
373 (maxJpegSize.getWidth() <= maxYuvSize.getWidth() &&
374 maxJpegSize.getHeight() <= maxYuvSize.getHeight()) : false;
375
376 // Ensure that YUV output is fast enough - needs to be at least 20 fps
377
378 long maxYuvRate =
379 config.getOutputMinFrameDuration(ImageFormat.YUV_420_888, maxYuvSize);
380 final long MIN_DURATION_BOUND_NS = 50000000; // 50 ms, 20 fps
381
382 boolean haveMaxYuvRate = maxYuvRate <= MIN_DURATION_BOUND_NS;
383
384 // Ensure that there's an FPS range that's fast enough to capture at above
385 // minFrameDuration, for full-auto bursts
386 Range[] fpsRanges = c.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
387 float minYuvFps = 1.f / maxYuvRate;
388
389 boolean haveFastAeTargetFps = false;
390 for (Range<Integer> r : fpsRanges) {
391 if (r.getLower() >= minYuvFps) {
392 haveFastAeTargetFps = true;
393 break;
394 }
395 }
396
397 // Ensure that maximum sync latency is small enough for fast setting changes, even if
398 // it's not quite per-frame
399
400 Integer maxSyncLatencyValue = c.get(CameraCharacteristics.SYNC_MAX_LATENCY);
401 assertNotNull(String.format("No sync latency declared for ID %s", mIds[counter]),
402 maxSyncLatencyValue);
403
404 int maxSyncLatency = maxSyncLatencyValue;
405 final long MAX_LATENCY_BOUND = 4;
406 boolean haveFastSyncLatency =
407 (maxSyncLatency <= MAX_LATENCY_BOUND) && (maxSyncLatency >= 0);
408
409 if (haveBurstCapability) {
410 assertTrue(
411 String.format("BURST-capable camera device %s does not have maximum YUV " +
412 "size that is at least max JPEG size",
413 mIds[counter]),
414 haveMaxYuv);
415 assertTrue(
416 String.format("BURST-capable camera device %s YUV frame rate is too slow" +
417 "(%d ns min frame duration reported, less than %d ns expected)",
418 mIds[counter], maxYuvRate, MIN_DURATION_BOUND_NS),
419 haveMaxYuvRate);
420 assertTrue(
421 String.format("BURST-capable camera device %s does not list an AE target " +
422 " FPS range with min FPS >= %f, for full-AUTO bursts",
423 mIds[counter], minYuvFps),
424 haveFastAeTargetFps);
425 assertTrue(
426 String.format("BURST-capable camera device %s YUV sync latency is too long" +
427 "(%d frames reported, [0, %d] frames expected)",
428 mIds[counter], maxSyncLatency, MAX_LATENCY_BOUND),
429 haveFastSyncLatency);
430 } else {
431 assertTrue(
432 String.format("Camera device %s has all the requirements for BURST" +
433 " capability but does not report it!", mIds[counter]),
434 !(haveMaxYuv && haveMaxYuvRate &&
435 haveFastAeTargetFps && haveFastSyncLatency));
436 }
437
438 counter++;
439 }
440 }
441
442 /**
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -0800443 * Cross-check StreamConfigurationMap output
444 */
445 public void testStreamConfigurationMap() {
446 int counter = 0;
447 for (CameraCharacteristics c : mCharacteristics) {
448 Log.i(TAG, "testStreamConfigurationMap: Testing camera ID " + mIds[counter]);
449 StreamConfigurationMap config =
450 c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
451 assertNotNull(String.format("No stream configuration map found for: ID %s",
452 mIds[counter]), config);
453
454 assertTrue("ImageReader must be supported",
455 config.isOutputSupportedFor(android.media.ImageReader.class));
456 assertTrue("MediaRecorder must be supported",
457 config.isOutputSupportedFor(android.media.MediaRecorder.class));
458 assertTrue("MediaCodec must be supported",
459 config.isOutputSupportedFor(android.media.MediaCodec.class));
460 assertTrue("Allocation must be supported",
461 config.isOutputSupportedFor(android.renderscript.Allocation.class));
462 assertTrue("SurfaceHolder must be supported",
463 config.isOutputSupportedFor(android.view.SurfaceHolder.class));
464 assertTrue("SurfaceTexture must be supported",
465 config.isOutputSupportedFor(android.graphics.SurfaceTexture.class));
466
467 assertTrue("YUV_420_888 must be supported",
468 config.isOutputSupportedFor(ImageFormat.YUV_420_888));
469 assertTrue("JPEG must be supported",
470 config.isOutputSupportedFor(ImageFormat.JPEG));
471
472 // Legacy YUV formats should not be listed
473 assertTrue("NV21 must not be supported",
474 !config.isOutputSupportedFor(ImageFormat.NV21));
475
476 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
477 assertNotNull("android.request.availableCapabilities must never be null",
478 actualCapabilities);
479 if (arrayContains(actualCapabilities,
480 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
481 assertTrue("RAW_SENSOR must be supported if RAW capability is advertised",
482 config.isOutputSupportedFor(ImageFormat.RAW_SENSOR));
483 }
484
485 // Cross check public formats and sizes
486
487 int[] supportedFormats = config.getOutputFormats();
488 for (int format : supportedFormats) {
489 assertTrue("Format " + format + " fails cross check",
490 config.isOutputSupportedFor(format));
491 Size[] supportedSizes = config.getOutputSizes(format);
492 assertTrue("Supported format " + format + " has no sizes listed",
493 supportedSizes.length > 0);
494 for (Size size : supportedSizes) {
495 if (VERBOSE) {
496 Log.v(TAG,
497 String.format("Testing camera %s, format %d, size %s",
498 mIds[counter], format, size.toString()));
499 }
500
501 long stallDuration = config.getOutputStallDuration(format, size);
502 switch(format) {
503 case ImageFormat.YUV_420_888:
504 assertTrue("YUV_420_888 may not have a non-zero stall duration",
505 stallDuration == 0);
506 break;
507 default:
508 assertTrue("Negative stall duration for format " + format,
509 stallDuration >= 0);
510 break;
511 }
512 long minDuration = config.getOutputMinFrameDuration(format, size);
513 if (arrayContains(actualCapabilities,
514 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
515 assertTrue("MANUAL_SENSOR capability, need positive min frame duration for"
Zhijun He503da802015-02-04 14:35:38 -0800516 + "format " + format + " for size " + size + " minDuration " +
517 minDuration,
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -0800518 minDuration > 0);
519 } else {
520 assertTrue("Need non-negative min frame duration for format " + format,
521 minDuration >= 0);
522 }
523
524 ImageReader testReader = ImageReader.newInstance(
525 size.getWidth(),
526 size.getHeight(),
527 format,
528 1);
529 Surface testSurface = testReader.getSurface();
530
531 assertTrue(
532 String.format("isOutputSupportedFor fails for config %s, format %d",
533 size.toString(), format),
534 config.isOutputSupportedFor(testSurface));
535
536 testReader.close();
537
538 } // sizes
539
540 // Try an invalid size in this format, should round
541 Size invalidSize = findInvalidSize(supportedSizes);
542 int MAX_ROUNDING_WIDTH = 1920;
543 if (invalidSize.getWidth() <= MAX_ROUNDING_WIDTH) {
544 ImageReader testReader = ImageReader.newInstance(
545 invalidSize.getWidth(),
546 invalidSize.getHeight(),
547 format,
548 1);
549 Surface testSurface = testReader.getSurface();
550
551 assertTrue(
552 String.format("isOutputSupportedFor fails for config %s, %d",
553 invalidSize.toString(), format),
554 config.isOutputSupportedFor(testSurface));
555
556 testReader.close();
557 }
558 } // formats
559
560 // Cross-check opaque format and sizes
561
562 SurfaceTexture st = new SurfaceTexture(1);
563 Surface surf = new Surface(st);
564
565 Size[] opaqueSizes = config.getOutputSizes(SurfaceTexture.class);
566 assertTrue("Opaque format has no sizes listed",
567 opaqueSizes.length > 0);
568 for (Size size : opaqueSizes) {
569 long stallDuration = config.getOutputStallDuration(SurfaceTexture.class, size);
570 assertTrue("Opaque output may not have a non-zero stall duration",
571 stallDuration == 0);
572
573 long minDuration = config.getOutputMinFrameDuration(SurfaceTexture.class, size);
574 if (arrayContains(actualCapabilities,
575 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
576 assertTrue("MANUAL_SENSOR capability, need positive min frame duration for"
577 + "opaque format",
578 minDuration > 0);
579 } else {
580 assertTrue("Need non-negative min frame duration for opaque format ",
581 minDuration >= 0);
582 }
583 st.setDefaultBufferSize(size.getWidth(), size.getHeight());
584
585 assertTrue(
586 String.format("isOutputSupportedFor fails for SurfaceTexture config %s",
587 size.toString()),
588 config.isOutputSupportedFor(surf));
589
590 } // opaque sizes
591
592 // Try invalid opaque size, should get rounded
593 Size invalidSize = findInvalidSize(opaqueSizes);
594 st.setDefaultBufferSize(invalidSize.getWidth(), invalidSize.getHeight());
595 assertTrue(
596 String.format("isOutputSupportedFor fails for SurfaceTexture config %s",
597 invalidSize.toString()),
598 config.isOutputSupportedFor(surf));
599
600 counter++;
601 } // mCharacteristics
602
603 }
604
605 /**
606 * Create an invalid size that's close to one of the good sizes in the list, but not one of them
607 */
608 private Size findInvalidSize(Size[] goodSizes) {
609 Size invalidSize = new Size(goodSizes[0].getWidth() + 1, goodSizes[0].getHeight());
610 while(arrayContains(goodSizes, invalidSize)) {
611 invalidSize = new Size(invalidSize.getWidth() + 1, invalidSize.getHeight());
612 }
613 return invalidSize;
614 }
615
616 /**
Igor Murashkin12921f62014-07-11 16:22:17 -0700617 * Check key is present in characteristics if the hardware level is at least {@code hwLevel};
Yin-Chia Yehb21ede92014-09-22 14:38:15 -0700618 * check that the key is present if the actual capabilities are one of {@code capabilities}.
Igor Murashkin12921f62014-07-11 16:22:17 -0700619 *
620 * @return value of the {@code key} from {@code c}
621 */
622 private <T> T expectKeyAvailable(CameraCharacteristics c, CameraCharacteristics.Key<T> key,
623 int hwLevel, int... capabilities) {
624
625 Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
626 assertNotNull("android.info.supportedHardwareLevel must never be null", actualHwLevel);
627
628 int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
Eino-Ville Talvala35a52702014-11-13 13:36:58 -0800629 assertNotNull("android.request.availableCapabilities must never be null",
630 actualCapabilities);
Igor Murashkin12921f62014-07-11 16:22:17 -0700631
632 List<Key<?>> allKeys = c.getKeys();
633
634 T value = c.get(key);
635
636 if (compareHardwareLevel(actualHwLevel, hwLevel) >= 0) {
637 mCollector.expectTrue(
638 String.format("Key (%s) must be in characteristics for this hardware level " +
639 "(required minimal HW level %s, actual HW level %s)",
640 key.getName(), toStringHardwareLevel(hwLevel),
641 toStringHardwareLevel(actualHwLevel)),
642 value != null);
643 mCollector.expectTrue(
644 String.format("Key (%s) must be in characteristics list of keys for this " +
645 "hardware level (required minimal HW level %s, actual HW level %s)",
646 key.getName(), toStringHardwareLevel(hwLevel),
647 toStringHardwareLevel(actualHwLevel)),
648 allKeys.contains(key));
649 } else if (arrayContainsAnyOf(actualCapabilities, capabilities)) {
650 mCollector.expectTrue(
651 String.format("Key (%s) must be in characteristics for these capabilities " +
652 "(required capabilities %s, actual capabilities %s)",
653 key.getName(), Arrays.toString(capabilities),
654 Arrays.toString(actualCapabilities)),
655 value != null);
656 mCollector.expectTrue(
657 String.format("Key (%s) must be in characteristics list of keys for " +
658 "these capabilities (required capabilities %s, actual capabilities %s)",
659 key.getName(), Arrays.toString(capabilities),
660 Arrays.toString(actualCapabilities)),
661 allKeys.contains(key));
662 } else {
Ruben Brunk43e260f2014-07-09 12:56:02 -0700663 if (actualHwLevel == LEGACY && hwLevel != OPT) {
Yin-Chia Yehb21ede92014-09-22 14:38:15 -0700664 if (value != null || allKeys.contains(key)) {
665 Log.w(TAG, String.format(
666 "Key (%s) is not required for LEGACY devices but still appears",
667 key.getName()));
668 }
Igor Murashkin12921f62014-07-11 16:22:17 -0700669 }
Igor Murashkin12921f62014-07-11 16:22:17 -0700670 // OK: Key may or may not be present.
671 }
Igor Murashkin12921f62014-07-11 16:22:17 -0700672 return value;
673 }
674
675 private static boolean arrayContains(int[] arr, int needle) {
676 if (arr == null) {
677 return false;
678 }
679
680 for (int elem : arr) {
681 if (elem == needle) {
682 return true;
683 }
684 }
685
686 return false;
687 }
688
Eino-Ville Talvala599b8bd2015-01-20 13:30:54 -0800689 private static <T> boolean arrayContains(T[] arr, T needle) {
690 if (arr == null) {
691 return false;
692 }
693
694 for (T elem : arr) {
695 if (elem.equals(needle)) {
696 return true;
697 }
698 }
699
700 return false;
701 }
702
Igor Murashkin12921f62014-07-11 16:22:17 -0700703 private static boolean arrayContainsAnyOf(int[] arr, int[] needles) {
704 for (int needle : needles) {
705 if (arrayContains(arr, needle)) {
706 return true;
707 }
708 }
709 return false;
710 }
711
712 /**
713 * The key name has a prefix of either "android." or "com."; other prefixes are not valid.
714 */
715 private static void assertKeyPrefixValid(String keyName) {
716 assertStartsWithAnyOf(
717 "All metadata keys must start with 'android.' (built-in keys) " +
718 "or 'com.' (vendor-extended keys)", new String[] {
719 PREFIX_ANDROID + ".",
720 PREFIX_VENDOR + ".",
721 }, keyName);
722 }
723
724 private static void assertTrueForKey(String msg, CameraCharacteristics.Key<?> key,
725 boolean actual) {
726 assertTrue(msg + " (key = '" + key.getName() + "')", actual);
727 }
728
729 private static <T> void assertOneOf(String msg, T[] expected, T actual) {
730 for (int i = 0; i < expected.length; ++i) {
731 if (Objects.equals(expected[i], actual)) {
732 return;
733 }
734 }
735
736 fail(String.format("%s: (expected one of %s, actual %s)",
737 msg, Arrays.toString(expected), actual));
738 }
739
740 private static <T> void assertStartsWithAnyOf(String msg, String[] expected, String actual) {
741 for (int i = 0; i < expected.length; ++i) {
742 if (actual.startsWith(expected[i])) {
743 return;
744 }
745 }
746
747 fail(String.format("%s: (expected to start with any of %s, but value was %s)",
748 msg, Arrays.toString(expected), actual));
749 }
750
751 /** Return a positive int if left > right, 0 if left==right, negative int if left < right */
752 private static int compareHardwareLevel(int left, int right) {
753 return remapHardwareLevel(left) - remapHardwareLevel(right);
754 }
755
756 /** Remap HW levels worst<->best, 0 = worst, 2 = best */
757 private static int remapHardwareLevel(int level) {
758 switch (level) {
Ruben Brunk43e260f2014-07-09 12:56:02 -0700759 case OPT:
Yin-Chia Yeh84cbfd32014-09-18 10:16:12 -0700760 return Integer.MAX_VALUE;
Igor Murashkin12921f62014-07-11 16:22:17 -0700761 case LEGACY:
762 return 0; // lowest
763 case LIMITED:
764 return 1; // second lowest
765 case FULL:
766 return 2; // best
767 }
768
769 fail("Unknown HW level: " + level);
770 return -1;
771 }
772
773 private static String toStringHardwareLevel(int level) {
774 switch (level) {
775 case LEGACY:
776 return "LEGACY";
777 case LIMITED:
778 return "LIMITED";
779 case FULL:
780 return "FULL";
781 }
782
783 // unknown
784 Log.w(TAG, "Unknown hardware level " + level);
785 return Integer.toString(level);
786 }
Ruben Brunkfc6a26e2014-06-13 18:28:09 -0700787}