1 /*
2  * Copyright 2020 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 android.hardware.camera2.cts;
17 
18 import android.content.Context;
19 import android.graphics.ImageFormat;
20 import android.graphics.SurfaceTexture;
21 import android.hardware.camera2.CameraCharacteristics;
22 import android.hardware.camera2.CameraExtensionCharacteristics;
23 import android.hardware.camera2.CameraMetadata;
24 import android.hardware.camera2.CaptureRequest;
25 import android.hardware.camera2.CaptureResult;
26 import android.hardware.camera2.ExtensionCaptureRequest;
27 import android.hardware.camera2.ExtensionCaptureResult;
28 import android.hardware.camera2.cts.helpers.StaticMetadata;
29 import android.hardware.camera2.cts.testcases.Camera2AndroidTestRule;
30 import android.hardware.camera2.params.StreamConfigurationMap;
31 import android.os.Build;
32 import android.platform.test.annotations.AppModeFull;
33 import android.platform.test.annotations.RequiresFlagsEnabled;
34 import android.util.ArraySet;
35 import android.util.FeatureFlagUtils;
36 import android.util.Log;
37 import android.util.Range;
38 import android.util.Size;
39 import android.view.SurfaceHolder;
40 import android.view.SurfaceView;
41 
42 import androidx.test.InstrumentationRegistry;
43 
44 import com.android.compatibility.common.util.PropertyUtil;
45 import com.android.internal.camera.flags.Flags;
46 
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collections;
50 import java.util.HashSet;
51 import java.util.List;
52 import java.util.Set;
53 import java.util.stream.Collectors;
54 
55 import static org.junit.Assert.*;
56 import static org.junit.Assume.assumeFalse;
57 
58 import org.junit.After;
59 import org.junit.Before;
60 import org.junit.Rule;
61 import org.junit.Test;
62 import org.junit.runner.RunWith;
63 import org.junit.runners.JUnit4;
64 
65 @RunWith(JUnit4.class)
66 public class CameraExtensionCharacteristicsTest {
67     private static final String TAG = "CameraExtensionManagerTest";
68     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
69     private ArrayList<Integer> mExtensionList = new ArrayList<>();
70 
71     private final Context mContext = InstrumentationRegistry.getTargetContext();
72 
73     private CaptureRequest.Key[] EYES_FREE_AUTO_ZOOM_REQUEST_SET = new CaptureRequest.Key[0];
74     private CaptureResult.Key[] EYES_FREE_AUTO_ZOOM_RESULT_SET =  new CaptureResult.Key[0];
75     private CaptureRequest.Key[] EYES_FREE_REQUEST_SET = new CaptureRequest.Key[0];
76     private CaptureResult.Key[] EYES_FREE_RESULT_SET = new CaptureResult.Key[0];
77 
78     private static final boolean EFV_API_SUPPORTED =
79             Build.VERSION.SDK_INT > Build.VERSION_CODES.UPSIDE_DOWN_CAKE && Flags.concertModeApi();
80     @Rule
81     public final Camera2AndroidTestRule mTestRule = new Camera2AndroidTestRule(mContext);
82 
83     @Before
setUp()84     public void setUp() throws Exception {
85         mExtensionList.addAll(Arrays.asList(
86                 CameraExtensionCharacteristics.EXTENSION_AUTOMATIC,
87                 CameraExtensionCharacteristics.EXTENSION_BEAUTY,
88                 CameraExtensionCharacteristics.EXTENSION_BOKEH,
89                 CameraExtensionCharacteristics.EXTENSION_HDR,
90                 CameraExtensionCharacteristics.EXTENSION_NIGHT));
91         if (EFV_API_SUPPORTED) {
92             mExtensionList.add(CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY);
93             EYES_FREE_AUTO_ZOOM_REQUEST_SET = new CaptureRequest.Key[] {
94                     ExtensionCaptureRequest.EFV_AUTO_ZOOM,
95                     ExtensionCaptureRequest.EFV_MAX_PADDING_ZOOM_FACTOR};
96             EYES_FREE_AUTO_ZOOM_RESULT_SET = new CaptureResult.Key[] {
97                     ExtensionCaptureResult.EFV_AUTO_ZOOM,
98                     ExtensionCaptureResult.EFV_AUTO_ZOOM_PADDING_REGION,
99                     ExtensionCaptureResult.EFV_MAX_PADDING_ZOOM_FACTOR};
100             EYES_FREE_REQUEST_SET = new CaptureRequest.Key[] {
101                     ExtensionCaptureRequest.EFV_PADDING_ZOOM_FACTOR,
102                     ExtensionCaptureRequest.EFV_STABILIZATION_MODE,
103                     ExtensionCaptureRequest.EFV_TRANSLATE_VIEWPORT,
104                     ExtensionCaptureRequest.EFV_ROTATE_VIEWPORT};
105             EYES_FREE_RESULT_SET = new CaptureResult.Key[] {
106             ExtensionCaptureResult.EFV_PADDING_REGION,
107                     ExtensionCaptureResult.EFV_TARGET_COORDINATES,
108                     ExtensionCaptureResult.EFV_PADDING_ZOOM_FACTOR,
109                     ExtensionCaptureResult.EFV_STABILIZATION_MODE,
110                     ExtensionCaptureResult.EFV_ROTATE_VIEWPORT,
111                     ExtensionCaptureResult.EFV_TRANSLATE_VIEWPORT};
112         }
113     }
114 
115     @After
tearDown()116     public void tearDown() throws Exception {
117         mExtensionList.clear();
118     }
119 
openDevice(String cameraId)120     private void openDevice(String cameraId) throws Exception {
121         mTestRule.setCamera(CameraTestUtils.openCamera(
122                 mTestRule.getCameraManager(), cameraId,
123                 mTestRule.getCameraListener(), mTestRule.getHandler()));
124         mTestRule.getCollector().setCameraId(cameraId);
125         mTestRule.setStaticInfo(new StaticMetadata(
126                 mTestRule.getCameraManager().getCameraCharacteristics(cameraId),
127                 StaticMetadata.CheckLevel.ASSERT, /*collector*/null));
128     }
129 
verifySupportedExtension(CameraExtensionCharacteristics chars, String cameraId, Integer extension, Class<T> klass)130     private <T> void verifySupportedExtension(CameraExtensionCharacteristics chars, String cameraId,
131             Integer extension, Class<T> klass) {
132         List<Size> availableSizes = chars.getExtensionSupportedSizes(extension, klass);
133         assertTrue(String.format("Supported extension %d on camera id: %s doesn't " +
134                         "include any valid resolutions!", extension, cameraId),
135                 (availableSizes != null) && (!availableSizes.isEmpty()));
136     }
137 
verifySupportedSizes(CameraExtensionCharacteristics chars, String cameraId, Integer extension, Class<T> klass)138     private <T> void verifySupportedSizes(CameraExtensionCharacteristics chars, String cameraId,
139             Integer extension, Class<T> klass) throws Exception {
140         verifySupportedExtension(chars, cameraId, extension, klass);
141         try {
142             openDevice(cameraId);
143             List<Size> extensionSizes = chars.getExtensionSupportedSizes(extension, klass);
144             List<Size> cameraSizes = Arrays.asList(
145                     mTestRule.getStaticInfo().getAvailableSizesForFormatChecked(ImageFormat.PRIVATE,
146                             StaticMetadata.StreamDirection.Output));
147             for (Size extensionSize : extensionSizes) {
148                 assertTrue(String.format("Supported extension %d on camera id: %s advertises " +
149                                 " resolution %s unsupported by camera", extension, cameraId,
150                         extensionSize), cameraSizes.contains(extensionSize));
151             }
152         } finally {
153             mTestRule.closeDevice(cameraId);
154         }
155     }
156 
verifySupportedSizes(CameraExtensionCharacteristics chars, String cameraId, Integer extension, int format)157     private void verifySupportedSizes(CameraExtensionCharacteristics chars, String cameraId,
158             Integer extension, int format) throws Exception {
159         List<Size> extensionSizes = chars.getExtensionSupportedSizes(extension, format);
160         assertFalse(String.format("No available sizes for extension %d on camera id: %s " +
161                 "using format: %x", extension, cameraId, format), extensionSizes.isEmpty());
162         try {
163             openDevice(cameraId);
164             List<Size> cameraSizes = Arrays.asList(
165                     mTestRule.getStaticInfo().getAvailableSizesForFormatChecked(format,
166                             StaticMetadata.StreamDirection.Output));
167             for (Size extensionSize : extensionSizes) {
168                 assertTrue(String.format("Supported extension %d on camera id: %s advertises " +
169                                 " resolution %s unsupported by camera", extension, cameraId,
170                         extensionSize), cameraSizes.contains(extensionSize));
171             }
172         } finally {
173             mTestRule.closeDevice(cameraId);
174         }
175     }
176 
verifyUnsupportedExtension(CameraExtensionCharacteristics chars, Integer extension, Class<T> klass)177     private <T> void verifyUnsupportedExtension(CameraExtensionCharacteristics chars,
178             Integer extension, Class<T> klass) {
179         try {
180             chars.getExtensionSupportedSizes(extension, klass);
181             fail("should get IllegalArgumentException due to unsupported extension");
182         } catch (IllegalArgumentException e) {
183             // Expected
184         }
185     }
186 
187     @Test
188     @AppModeFull(reason = "Instant apps can't access Test API")
testExtensionAvailability()189     public void testExtensionAvailability() throws Exception {
190         assumeFalse("Test is running on single overridden camera id, skipping",
191                      mTestRule.isCameraIdOverriddenForTest());
192         boolean extensionsAdvertised = false;
193         for (String id : mTestRule.getCameraIdsUnderTest()) {
194             StaticMetadata staticMeta =
195                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
196             if (!staticMeta.isColorOutputSupported()) {
197                 continue;
198             }
199             CameraExtensionCharacteristics extensionChars =
200                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
201             ArrayList<Integer> unsupportedExtensions = new ArrayList<>(mExtensionList);
202             List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
203             if (!extensionsAdvertised && !supportedExtensions.isEmpty()) {
204                 extensionsAdvertised = true;
205             }
206             for (Integer extension : supportedExtensions) {
207                 verifySupportedExtension(extensionChars, id, extension, SurfaceTexture.class);
208                 unsupportedExtensions.remove(extension);
209             }
210 
211             // Unsupported extension size queries must throw corresponding exception.
212             for (Integer extension : unsupportedExtensions) {
213                 verifyUnsupportedExtension(extensionChars, extension, SurfaceTexture.class);
214             }
215         }
216         boolean extensionsEnabledProp = PropertyUtil.areCameraXExtensionsEnabled();
217         assertEquals("Extensions system property : " + extensionsEnabledProp + " does not match " +
218                 "with the advertised extensions: " + extensionsAdvertised, extensionsEnabledProp,
219                 extensionsAdvertised);
220     }
221 
222     @Test
testExtensionSizes()223     public void testExtensionSizes() throws Exception {
224         for (String id : mTestRule.getCameraIdsUnderTest()) {
225             StaticMetadata staticMeta =
226                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
227             if (!staticMeta.isColorOutputSupported()) {
228                 continue;
229             }
230             CameraExtensionCharacteristics extensionChars =
231                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
232             List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
233             for (Integer extension : supportedExtensions) {
234                 verifySupportedSizes(extensionChars, id, extension, SurfaceTexture.class);
235                 verifySupportedSizes(extensionChars, id, extension, ImageFormat.JPEG);
236             }
237         }
238     }
239 
240     @Test
testIllegalArguments()241     public void testIllegalArguments() throws Exception {
242         try {
243             mTestRule.getCameraManager().getCameraExtensionCharacteristics("InvalidCameraId!");
244             fail("should get IllegalArgumentException due to invalid camera id");
245         } catch (IllegalArgumentException e) {
246             // Expected
247         }
248 
249         for (String id : mTestRule.getCameraIdsUnderTest()) {
250             CameraExtensionCharacteristics extensionChars =
251                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
252             List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
253             for (Integer extension : supportedExtensions) {
254                 try {
255                     extensionChars.getExtensionSupportedSizes(extension, ImageFormat.UNKNOWN);
256                     fail("should get IllegalArgumentException due to invalid pixel format");
257                 } catch (IllegalArgumentException e) {
258                     // Expected
259                 }
260 
261                 try {
262                     final class NotSupported {};
263                     List<Size> ret = extensionChars.getExtensionSupportedSizes(extension,
264                             NotSupported.class);
265                     assertTrue("should get empty resolution list for unsupported " +
266                             "surface type", ret.isEmpty());
267                 } catch (IllegalArgumentException e) {
268                     fail("should not get IllegalArgumentException due to unsupported surface " +
269                             "type");
270                 }
271             }
272         }
273     }
274 
275     @Test
testExtensionLatencyRanges()276     public void testExtensionLatencyRanges() throws Exception {
277         final int testFormat = ImageFormat.JPEG;
278         for (String id : mTestRule.getCameraIdsUnderTest()) {
279             StaticMetadata staticMeta =
280                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
281             if (!staticMeta.isColorOutputSupported()) {
282                 continue;
283             }
284 
285             CameraExtensionCharacteristics chars =
286                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
287             List<Integer> supportedExtensions = chars.getSupportedExtensions();
288             for (Integer extension : supportedExtensions) {
289                 List<Size> extensionSizes = chars.getExtensionSupportedSizes(extension, testFormat);
290                 for (Size sz : extensionSizes) {
291                     Range<Long> latencyRange = chars.getEstimatedCaptureLatencyRangeMillis(
292                             extension, sz, testFormat);
293                     if (latencyRange != null) {
294                         assertTrue("Negative range surface type", (latencyRange.getLower() > 0) &&
295                                 (latencyRange.getUpper() > 0));
296                         assertTrue("Lower range value must be smaller compared to the upper",
297                                 (latencyRange.getLower() < latencyRange.getUpper()));
298                     }
299                 }
300             }
301         }
302     }
303 
304     @Test
testExtensionRequestKeys()305     public void testExtensionRequestKeys() throws Exception {
306         ArraySet<CaptureRequest.Key> extensionRequestKeys = new ArraySet<>();
307         extensionRequestKeys.add(CaptureRequest.EXTENSION_STRENGTH);
308         extensionRequestKeys.addAll(Arrays.asList(EYES_FREE_REQUEST_SET));
309         extensionRequestKeys.addAll(Arrays.asList(EYES_FREE_AUTO_ZOOM_REQUEST_SET));
310 
311         for (String id : mTestRule.getCameraIdsUnderTest()) {
312             StaticMetadata staticMeta =
313                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
314             if (!staticMeta.isColorOutputSupported()) {
315                 continue;
316             }
317 
318             CameraExtensionCharacteristics chars =
319                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
320             List<Integer> supportedExtensions = chars.getSupportedExtensions();
321             for (Integer extension : supportedExtensions) {
322                 Set<CaptureRequest.Key> captureKeySet =
323                         chars.getAvailableCaptureRequestKeys(extension);
324                 ArraySet<CaptureRequest.Key> captureKeys = new ArraySet<>(captureKeySet);
325                 // No repeating keys allowed
326                 assertEquals(captureKeys.size(), captureKeySet.size());
327                 // Jpeg quality and jpeg orientation must always be available
328                 assertTrue(captureKeys.contains(CaptureRequest.JPEG_QUALITY));
329                 assertTrue(captureKeys.contains(CaptureRequest.JPEG_ORIENTATION));
330                 // The extension request keys must always match or be a subset of the regular keys
331                 for (CaptureRequest.Key captureKey : captureKeys) {
332                     String msg = String.format("Supported extension request key %s doesn't appear "
333                             + " int the regular camera characteristics list of supported keys!",
334                             captureKey.getName());
335                     assertTrue(msg, staticMeta.areKeysAvailable(captureKey) ||
336                             extensionRequestKeys.contains(captureKey));
337                 }
338 
339                 // Ensure eyes-free specific keys are only supported for eyes-free extension
340                 if (EFV_API_SUPPORTED && extension
341                         != CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) {
342                     CameraTestUtils.checkKeysAreSupported(Arrays.asList(EYES_FREE_REQUEST_SET,
343                             EYES_FREE_AUTO_ZOOM_REQUEST_SET), captureKeySet, false);
344                 }
345             }
346         }
347     }
348 
349     @Test
testExtensionResultKeys()350     public void testExtensionResultKeys() throws Exception {
351         ArraySet<CaptureResult.Key> extensionResultKeys = new ArraySet<>();
352         extensionResultKeys.add(CaptureResult.EXTENSION_STRENGTH);
353         extensionResultKeys.add(CaptureResult.EXTENSION_CURRENT_TYPE);
354         extensionResultKeys.addAll(Arrays.asList(EYES_FREE_RESULT_SET));
355         extensionResultKeys.addAll(Arrays.asList(EYES_FREE_AUTO_ZOOM_RESULT_SET));
356 
357         for (String id : mTestRule.getCameraIdsUnderTest()) {
358             StaticMetadata staticMeta =
359                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
360             if (!staticMeta.isColorOutputSupported()) {
361                 continue;
362             }
363 
364             CameraExtensionCharacteristics chars =
365                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
366             List<Integer> supportedExtensions = chars.getSupportedExtensions();
367             for (Integer extension : supportedExtensions) {
368                 Set<CaptureResult.Key> resultKeySet =
369                         chars.getAvailableCaptureResultKeys(extension);
370                 if (resultKeySet.isEmpty()) {
371                     // Extension capture result support is optional
372                     continue;
373                 }
374 
375                 ArraySet<CaptureResult.Key> resultKeys = new ArraySet<>(resultKeySet);
376                 ArraySet<String> resultKeyNames = new ArraySet<>(resultKeys.size());
377                 // No repeating keys allowed
378                 assertEquals(resultKeys.size(), resultKeySet.size());
379                 // Sensor timestamp, jpeg quality and jpeg orientation must always be available
380                 assertTrue(resultKeys.contains(CaptureResult.SENSOR_TIMESTAMP));
381                 assertTrue(resultKeys.contains(CaptureResult.JPEG_QUALITY));
382                 assertTrue(resultKeys.contains(CaptureResult.JPEG_ORIENTATION));
383                 // The extension result keys must always match or be a subset of the regular result
384                 // keys
385                 for (CaptureResult.Key resultKey : resultKeys) {
386                     String msg = String.format("Supported extension result key %s doesn't appear "
387                             + " in the regular camera characteristics list of supported keys!",
388                             resultKey.getName());
389                     assertTrue(msg, staticMeta.areKeysAvailable(resultKey) ||
390                             extensionResultKeys.contains(resultKey));
391                     resultKeyNames.add(resultKey.getName());
392                 }
393 
394                 ArraySet<CaptureRequest.Key> captureKeys = new ArraySet<>(
395                         chars.getAvailableCaptureRequestKeys(extension));
396                 for (CaptureRequest.Key requestKey : captureKeys) {
397                     String msg = String.format("Supported extension request key %s doesn't appear "
398                             + " in the corresponding supported extension result key list!",
399                             requestKey.getName());
400                     assertTrue(msg, resultKeyNames.contains(requestKey.getName()));
401                 }
402 
403                 // Ensure eyes-free specific keys are only supported for eyes-free extension
404                 if (EFV_API_SUPPORTED && extension
405                         != CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) {
406                     CameraTestUtils.checkKeysAreSupported(Arrays.asList(EYES_FREE_RESULT_SET,
407                             EYES_FREE_AUTO_ZOOM_RESULT_SET), resultKeySet, false);
408                 }
409             }
410         }
411     }
412 
413     @Test
414     @RequiresFlagsEnabled(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET)
testExtensionGetCharacteristics()415     public void testExtensionGetCharacteristics() throws Exception {
416         for (String id : mTestRule.getCameraIdsUnderTest()) {
417             StaticMetadata staticMeta =
418                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
419             if (!staticMeta.isColorOutputSupported()) {
420                 continue;
421             }
422 
423             CameraExtensionCharacteristics chars =
424                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
425 
426             List<Integer> supportedExtensions = chars.getSupportedExtensions();
427             for (Integer extension : supportedExtensions) {
428                 Set<CameraCharacteristics.Key> keys = chars.getKeys(extension);
429                 for (CameraCharacteristics.Key key : keys) {
430                     assertNotNull("Associated value for key cannot be null.",
431                             chars.get(extension, key));
432                 }
433             }
434         }
435     }
436 
437     @Test
438     @RequiresFlagsEnabled(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET)
testGetRequiredKeys()439     public void testGetRequiredKeys() throws Exception {
440         ArraySet<CameraCharacteristics.Key> requiredKeys = new ArraySet<>();
441         requiredKeys.add(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
442         requiredKeys.add(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
443 
444         for (String id : mTestRule.getCameraIdsUnderTest()) {
445             StaticMetadata staticMeta =
446                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
447             if (!staticMeta.isColorOutputSupported()) {
448                 continue;
449             }
450 
451             CameraExtensionCharacteristics chars =
452                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
453 
454             List<Integer> supportedExtensions = chars.getSupportedExtensions();
455             for (Integer extension : supportedExtensions) {
456                 Set<CameraCharacteristics.Key> keys = chars.getKeys(extension);
457                 if (keys.isEmpty()) {
458                     continue;
459                 }
460                 for (CameraCharacteristics.Key key : requiredKeys) {
461                     assertTrue(keys.contains(key));
462                 }
463             }
464         }
465     }
466 
467     @Test
468     @RequiresFlagsEnabled(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET)
testGetUnsupportedCharacteristics()469     public void testGetUnsupportedCharacteristics() throws Exception {
470         for (String id : mTestRule.getCameraIdsUnderTest()) {
471             StaticMetadata staticMeta =
472                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
473             if (!staticMeta.isColorOutputSupported()) {
474                 continue;
475             }
476 
477             Set<Integer> unsupportedCapabilities = new HashSet<>(Arrays.asList(
478                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
479                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
480                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING,
481                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
482                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
483                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW,
484                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
485                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA,
486                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA,
487                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
488                     CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
489             ));
490 
491             CameraExtensionCharacteristics chars =
492                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
493 
494             List<Integer> supportedExtensions = chars.getSupportedExtensions();
495             for (Integer extension : supportedExtensions) {
496                 int[] availableCapabilities =
497                         chars.get(extension, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
498                 if (availableCapabilities != null) {
499                     for (int c : availableCapabilities) {
500                         assertFalse("Capabilitiy is not supported by extensions",
501                                 unsupportedCapabilities.contains(c));
502                     }
503                 }
504                 StreamConfigurationMap map = chars.get(extension,
505                         CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
506                 assertNull("StreamConfigurationMap must not be present in get", map);
507             }
508         }
509     }
510 }
511