1 /*
2  * Copyright 2013 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 
17 package android.hardware.camera2.cts;
18 
19 import android.content.Context;
20 import android.graphics.ImageFormat;
21 import android.hardware.camera2.CameraCaptureSession;
22 import android.hardware.camera2.CameraCharacteristics;
23 import android.hardware.camera2.CameraDevice;
24 import android.hardware.camera2.CaptureFailure;
25 import android.hardware.camera2.CaptureRequest;
26 import android.hardware.camera2.CaptureResult;
27 import android.hardware.camera2.params.BlackLevelPattern;
28 import android.hardware.camera2.TotalCaptureResult;
29 import android.media.Image;
30 import android.media.ImageReader;
31 import android.os.Build;
32 import android.os.SystemClock;
33 import android.util.Pair;
34 import android.util.Size;
35 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
36 import android.hardware.camera2.cts.helpers.StaticMetadata;
37 import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
38 
39 import static android.hardware.camera2.cts.CameraTestUtils.*;
40 import static android.hardware.camera2.cts.helpers.CameraSessionUtils.*;
41 import static junit.framework.Assert.*;
42 
43 import android.util.Log;
44 import android.view.Surface;
45 
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.HashMap;
49 import java.util.HashSet;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Set;
53 import java.util.concurrent.LinkedBlockingQueue;
54 import java.util.concurrent.TimeUnit;
55 
56 import org.junit.runners.Parameterized;
57 import org.junit.runner.RunWith;
58 import org.junit.Test;
59 
60 @RunWith(Parameterized.class)
61 public class CaptureResultTest extends Camera2AndroidTestCase {
62     private static final String TAG = "CaptureResultTest";
63     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
64     private static final int MAX_NUM_IMAGES = MAX_READER_IMAGES;
65     private static final int NUM_FRAMES_VERIFIED = 30;
66     private static final long WAIT_FOR_RESULT_TIMEOUT_MS = 3000;
67 
68     /** Load validation jni on initialization. */
69     static {
70         System.loadLibrary("ctscamera2_jni");
71     }
72 
73     // List tracking the failed test keys.
74 
75     @Override
setUp()76     public void setUp() throws Exception {
77         super.setUp();
78     }
79 
80     @Override
tearDown()81     public void tearDown() throws Exception {
82         super.tearDown();
83     }
84 
85     /**
86      * <p>
87      * Basic non-null check test for multiple capture results.
88      * </p>
89      * <p>
90      * When capturing many frames, some camera devices may return some results that have null keys
91      * randomly, which is an API violation and could cause application crash randomly. This test
92      * runs a typical flexible yuv capture many times, and checks if there is any null entries in
93      * a capture result.
94      * </p>
95      */
96     @Test
testCameraCaptureResultAllKeys()97     public void testCameraCaptureResultAllKeys() throws Exception {
98         for (String id : mCameraIdsUnderTest) {
99             try {
100                 openDevice(id);
101                 if (mStaticInfo.isColorOutputSupported()) {
102                     // Create image reader and surface.
103                     Size size = mOrderedPreviewSizes.get(0);
104                     createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
105                             new ImageDropperListener());
106                 } else {
107                     Size size = getMaxDepthSize(id, mCameraManager);
108                     createDefaultImageReader(size, ImageFormat.DEPTH16, MAX_NUM_IMAGES,
109                             new ImageDropperListener());
110                 }
111 
112                 // Configure output streams.
113                 List<Surface> outputSurfaces = new ArrayList<Surface>(1);
114                 outputSurfaces.add(mReaderSurface);
115                 createSession(outputSurfaces);
116 
117                 CaptureRequest.Builder requestBuilder =
118                         mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
119                 assertNotNull("Failed to create capture request", requestBuilder);
120                 requestBuilder.addTarget(mReaderSurface);
121 
122                 // Start capture
123                 SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
124                 startCapture(requestBuilder.build(), /*repeating*/true, captureListener, mHandler);
125 
126                 // Verify results
127                 validateCaptureResult(mCollector, captureListener, mStaticInfo, mAllStaticInfo,
128                         null/*requestedPhysicalIds*/, requestBuilder, NUM_FRAMES_VERIFIED);
129 
130                 stopCapture(/*fast*/false);
131             } finally {
132                 closeDevice(id);
133                 closeDefaultImageReader();
134             }
135         }
136     }
137 
138     /**
139      * Check partial results conform to its specification.
140      * <p>
141      * The test is skipped if partial result is not supported on device. </p>
142      * <p>Test summary:<ul>
143      * <li>1. Number of partial results is less than or equal to
144      * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}.
145      * <li>2. Each key appeared in partial results must be unique across all partial results.
146      * <li>3. All keys appeared in partial results must be present in TotalCaptureResult
147      * <li>4. Also test onCaptureComplete callback always happen after onCaptureStart or
148      * onCaptureProgressed callbacks.
149      * </ul></p>
150      */
151     @Test
testPartialResult()152     public void testPartialResult() throws Exception {
153         final int NUM_FRAMES_TESTED = 30;
154         final int WAIT_FOR_RESULT_TIMOUT_MS = 2000;
155         for (String id : mCameraIdsUnderTest) {
156             try {
157                 // Skip the test if partial result is not supported
158                 int partialResultCount = mAllStaticInfo.get(id).getPartialResultCount();
159                 if (partialResultCount == 1) {
160                     continue;
161                 }
162 
163                 openDevice(id);
164                 // Create image reader and surface.
165                 if (mStaticInfo.isColorOutputSupported()) {
166                     Size size = mOrderedPreviewSizes.get(0);
167                     createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
168                             new ImageDropperListener());
169                 } else {
170                     Size size = getMaxDepthSize(id, mCameraManager);
171                     createDefaultImageReader(size, ImageFormat.DEPTH16, MAX_NUM_IMAGES,
172                             new ImageDropperListener());
173                 }
174 
175                 // Configure output streams.
176                 List<Surface> outputSurfaces = new ArrayList<Surface>(1);
177                 outputSurfaces.add(mReaderSurface);
178                 createSession(outputSurfaces);
179 
180                 CaptureRequest.Builder requestBuilder =
181                         mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
182                 assertNotNull("Failed to create capture request", requestBuilder);
183                 requestBuilder.addTarget(mReaderSurface);
184                 TotalAndPartialResultListener listener =
185                         new TotalAndPartialResultListener();
186 
187                 // Start capture
188                 for (Integer frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
189                     // Set a different tag for each request so the listener can group
190                     // partial results by each request
191                     requestBuilder.setTag(frame);
192                     startCapture(
193                             requestBuilder.build(), /*repeating*/false,
194                             listener, mHandler);
195                 }
196 
197                 // Verify capture results
198                 for (int frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
199                     Pair<TotalCaptureResult, List<CaptureResult>> resultPair =
200                             listener.getCaptureResultPairs(WAIT_FOR_RESULT_TIMOUT_MS);
201 
202                     List<CaptureResult> partialResults = resultPair.second;
203 
204                     if (partialResults == null) {
205                         // HAL only sends total result is legal
206                         partialResults = new ArrayList<>();
207                     }
208 
209                     TotalCaptureResult totalResult = resultPair.first;
210 
211                     mCollector.expectLessOrEqual("Too many partial results",
212                             partialResultCount, partialResults.size());
213                     Set<CaptureResult.Key<?>> appearedPartialKeys =
214                             new HashSet<CaptureResult.Key<?>>();
215                     for (CaptureResult partialResult : partialResults) {
216                         mCollector.expectEquals("Partial capture result camera ID must be correct",
217                                 partialResult.getCameraId(), id);
218                         List<CaptureResult.Key<?>> partialKeys = partialResult.getKeys();
219                         mCollector.expectValuesUnique("Partial result keys: ", partialKeys);
220                         for (CaptureResult.Key<?> key : partialKeys) {
221                             mCollector.expectTrue(
222                                     String.format("Key %s appears in multiple partial results",
223                                             key.getName()),
224                                     !appearedPartialKeys.contains(key));
225                         }
226                         appearedPartialKeys.addAll(partialKeys);
227                     }
228 
229                     // Test total result against the partial results
230                     mCollector.expectEquals("Total capture result camera ID must be correct",
231                             totalResult.getCameraId(), id);
232                     List<CaptureResult.Key<?>> totalResultKeys = totalResult.getKeys();
233                     mCollector.expectTrue(
234                             "TotalCaptureResult must be a super set of partial capture results",
235                             totalResultKeys.containsAll(appearedPartialKeys));
236 
237                     List<CaptureResult> totalResultPartials = totalResult.getPartialResults();
238                     mCollector.expectEquals("TotalCaptureResult's partial results must match " +
239                             "the ones observed by #onCaptureProgressed",
240                             partialResults, totalResultPartials);
241 
242                     if (VERBOSE) {
243                         Log.v(TAG, "testPartialResult - Observed " +
244                                 partialResults.size() + "; queried for " +
245                                 totalResultPartials.size());
246                     }
247                 }
248 
249                 int errorCode = listener.getErrorCode();
250                 if ((errorCode & TotalAndPartialResultListener.ERROR_DUPLICATED_REQUEST) != 0) {
251                     mCollector.addMessage("Listener received multiple onCaptureComplete" +
252                             " callback for the same request");
253                 }
254                 if ((errorCode & TotalAndPartialResultListener.ERROR_WRONG_CALLBACK_ORDER) != 0) {
255                     mCollector.addMessage("Listener received onCaptureStart or" +
256                             " onCaptureProgressed after onCaptureComplete");
257                 }
258 
259                 stopCapture(/*fast*/false);
260             } finally {
261                 closeDevice(id);
262                 closeDefaultImageReader();
263             }
264         }
265     }
266 
267     /**
268      * Check that the timestamps passed in the results, buffers, and capture callbacks match for
269      * a single request, and increase monotonically
270      */
271     @Test
testResultTimestamps()272     public void testResultTimestamps() throws Exception {
273         for (String id : mCameraIdsUnderTest) {
274             ImageReader previewReader = null;
275             ImageReader jpegReader = null;
276 
277             CaptureResult resultForNdk = null;
278 
279             SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
280             SimpleImageReaderListener prevListener = new SimpleImageReaderListener();
281             try {
282                 if (!mAllStaticInfo.get(id).isColorOutputSupported()) {
283                     Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
284                     continue;
285                 }
286 
287                 openDevice(id);
288                 CaptureRequest.Builder previewBuilder =
289                         mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
290                 CaptureRequest.Builder multiBuilder =
291                         mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
292 
293                 // Create image reader and surface.
294                 Size previewSize = mOrderedPreviewSizes.get(0);
295                 Size jpegSize = mOrderedStillSizes.get(0);
296 
297                 // Create ImageReaders.
298                 previewReader = makeImageReader(previewSize, ImageFormat.YUV_420_888,
299                         MAX_NUM_IMAGES, prevListener, mHandler);
300                 jpegReader = makeImageReader(jpegSize, ImageFormat.JPEG,
301                         MAX_NUM_IMAGES, jpegListener, mHandler);
302 
303                 // Configure output streams with preview and jpeg streams.
304                 List<Surface> outputSurfaces = new ArrayList<>(Arrays.asList(
305                         previewReader.getSurface(), jpegReader.getSurface()));
306 
307                 SessionListener mockSessionListener = getMockSessionListener();
308 
309                 CameraCaptureSession session = configureAndVerifySession(mockSessionListener,
310                         mCamera, outputSurfaces, mHandler);
311 
312                 // Configure the requests.
313                 previewBuilder.addTarget(previewReader.getSurface());
314                 multiBuilder.addTarget(previewReader.getSurface());
315                 multiBuilder.addTarget(jpegReader.getSurface());
316 
317                 if (mStaticInfo.isEnableZslSupported()) {
318                     // Turn off ZSL to ensure timestamps are increasing
319                     previewBuilder.set(CaptureRequest.CONTROL_ENABLE_ZSL, false);
320                     multiBuilder.set(CaptureRequest.CONTROL_ENABLE_ZSL, false);
321                 }
322 
323                 CaptureCallback mockCaptureCallback = getMockCaptureListener();
324 
325                 // Capture targeting only preview
326                 Pair<TotalCaptureResult, Long> result = captureAndVerifyResult(mockCaptureCallback,
327                         session, previewBuilder.build(), mHandler);
328 
329                 // Check if all timestamps are the same
330                 Image prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
331                 validateTimestamps("Result 1", result.first,
332                         prevImage, result.second);
333                 prevImage.close();
334 
335                 // Capture targeting both jpeg and preview
336                 Pair<TotalCaptureResult, Long> result2 = captureAndVerifyResult(mockCaptureCallback,
337                         session, multiBuilder.build(), mHandler);
338 
339                 // Check if all timestamps are the same
340                 prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
341                 Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
342                 validateTimestamps("Result 2 Preview", result2.first,
343                         prevImage, result2.second);
344                 validateTimestamps("Result 2 Jpeg", result2.first,
345                         jpegImage, result2.second);
346                 prevImage.close();
347                 jpegImage.close();
348 
349                 // Check if timestamps are increasing
350                 mCollector.expectGreater("Timestamps must be increasing.", result.second,
351                         result2.second);
352 
353                 // Capture two preview frames
354                 long startTime = SystemClock.elapsedRealtimeNanos();
355                 Pair<TotalCaptureResult, Long> result3 = captureAndVerifyResult(mockCaptureCallback,
356                         session, previewBuilder.build(), mHandler);
357                 Pair<TotalCaptureResult, Long> result4 = captureAndVerifyResult(mockCaptureCallback,
358                         session, previewBuilder.build(), mHandler);
359                 long clockDiff = SystemClock.elapsedRealtimeNanos() - startTime;
360                 long resultDiff = result4.second - result3.second;
361 
362                 // Check if all timestamps are the same
363                 prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
364                 validateTimestamps("Result 3", result3.first,
365                         prevImage, result3.second);
366                 prevImage.close();
367                 prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
368                 validateTimestamps("Result 4", result4.first,
369                         prevImage, result4.second);
370                 prevImage.close();
371 
372                 // Check that the timestamps monotonically increase at a reasonable rate
373                 mCollector.expectGreaterOrEqual("Timestamps increase faster than system clock.",
374                         resultDiff, clockDiff);
375                 mCollector.expectGreater("Timestamps must be increasing.", result3.second,
376                         result4.second);
377 
378                 resultForNdk = result.first;
379             } finally {
380                 closeDevice(id);
381                 closeImageReader(previewReader);
382                 closeImageReader(jpegReader);
383             }
384 
385             mCollector.expectTrue(
386                 "validateACameraMetadataFromCameraMetadataCriticalTagsNative failed",
387                 validateACameraMetadataFromCameraMetadataCriticalTagsNative(resultForNdk,
388                         resultForNdk.get(CaptureResult.SENSOR_TIMESTAMP)));
389 
390             long timestamp = resultForNdk.get(CaptureResult.SENSOR_TIMESTAMP);
391             mCollector.expectTrue(
392                 "stashACameraMetadataFromCameraMetadataNative failed",
393                 stashACameraMetadataFromCameraMetadataNative(resultForNdk));
394 
395             // Try to drop the Java side object here
396             resultForNdk = null;
397             int[] block = null;
398             final int count = 9;
399             for (int i = 0; i < count + 1; i++) {
400                 block = new int[1000000];
401                 block[1000 + i] = i;
402 
403                 Runtime.getRuntime().gc();
404                 Runtime.getRuntime().runFinalization();
405 
406                 mCollector.expectTrue("This should never fail", block[1000 + i] == i);
407             }
408             mCollector.expectTrue(
409                 "validateStashedACameraMetadataFromCameraMetadataNative failed",
410                 validateStashedACameraMetadataFromCameraMetadataNative(timestamp));
411             mCollector.expectTrue("This should never fail", block[1000 + count] == count);
412         }
413     }
414 
validateTimestamps(String msg, TotalCaptureResult result, Image resultImage, long captureTime)415     private void validateTimestamps(String msg, TotalCaptureResult result, Image resultImage,
416                                     long captureTime) {
417         mCollector.expectKeyValueEquals(result, CaptureResult.SENSOR_TIMESTAMP, captureTime);
418         mCollector.expectEquals(msg + ": Capture timestamp must be same as resultImage timestamp",
419                 resultImage.getTimestamp(), captureTime);
420     }
421 
validateCaptureResult(CameraErrorCollector errorCollector, SimpleCaptureCallback captureListener, StaticMetadata staticInfo, Map<String, StaticMetadata> allStaticInfo, List<String> requestedPhysicalIds, CaptureRequest.Builder requestBuilder, int numFramesVerified)422     public static void validateCaptureResult(CameraErrorCollector errorCollector,
423             SimpleCaptureCallback captureListener, StaticMetadata staticInfo,
424             Map<String, StaticMetadata> allStaticInfo, List<String> requestedPhysicalIds,
425             CaptureRequest.Builder requestBuilder, int numFramesVerified) throws Exception {
426         // List that includes all public keys from CaptureResult
427         List<CaptureResult.Key<?>> allKeys = getAllCaptureResultKeys();
428         // Get the waived keys for current camera device
429         List<CaptureResult.Key<?>> waiverKeys = getWaiverKeysForCamera(staticInfo);
430         if (requestedPhysicalIds == null) {
431             requestedPhysicalIds = new ArrayList<String>();
432         }
433 
434         HashMap<String, List<CaptureResult.Key<?>>> physicalWaiverKeys = new HashMap<>();
435         for (String physicalId : requestedPhysicalIds) {
436             StaticMetadata physicalStaticInfo = allStaticInfo.get(physicalId);
437             physicalWaiverKeys.put(physicalId, getWaiverKeysForCamera(physicalStaticInfo));
438         }
439 
440         TotalCaptureResult result = null;
441         // List of (frameNumber, physical camera Id) pairs
442         ArrayList<Pair<Long, String>> droppedPhysicalResults = new ArrayList<>();
443         for (int i = 0; i < numFramesVerified; i++) {
444             result = captureListener.getTotalCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
445 
446             Map<String, CaptureResult> physicalCaptureResults = result.getPhysicalCameraResults();
447             ArrayList<String> droppedIds = new ArrayList<String>(requestedPhysicalIds);
448             droppedIds.removeAll(physicalCaptureResults.keySet());
449             for (String droppedId : droppedIds) {
450                 droppedPhysicalResults.add(
451                         new Pair<Long, String>(result.getFrameNumber(), droppedId));
452             }
453 
454             validateOneCaptureResult(errorCollector, staticInfo, waiverKeys, allKeys,
455                     requestBuilder, result, null/*cameraId*/, i);
456             for (String physicalId : physicalCaptureResults.keySet()) {
457                 StaticMetadata physicalStaticInfo = allStaticInfo.get(physicalId);
458                 validateOneCaptureResult(errorCollector, physicalStaticInfo,
459                         physicalWaiverKeys.get(physicalId),
460                         allKeys, null/*requestBuilder*/, physicalCaptureResults.get(physicalId),
461                         physicalId, i);
462             }
463         }
464 
465         // Verify that all dropped physical camera results are notified via capture failure.
466         while (captureListener.hasMoreFailures()) {
467             ArrayList<CaptureFailure> failures =
468                     captureListener.getCaptureFailures(/*maxNumFailures*/ 1);
469             for (CaptureFailure failure : failures) {
470                 String failedPhysicalId = failure.getPhysicalCameraId();
471                 Long failedFrameNumber = failure.getFrameNumber();
472                 if (failedPhysicalId != null) {
473                     droppedPhysicalResults.removeIf(
474                             n -> n.equals(
475                             new Pair<Long, String>(failedFrameNumber, failedPhysicalId)));
476                 }
477             }
478         }
479         errorCollector.expectTrue("Not all dropped results for physical cameras are notified",
480                 droppedPhysicalResults.isEmpty());
481     }
482 
validateOneCaptureResult(CameraErrorCollector errorCollector, StaticMetadata staticInfo, List<CaptureResult.Key<?>> skippedKeys, List<CaptureResult.Key<?>> allKeys, CaptureRequest.Builder requestBuilder, CaptureResult result, String cameraId, int resultCount)483     private static void validateOneCaptureResult(CameraErrorCollector errorCollector,
484             StaticMetadata staticInfo, List<CaptureResult.Key<?>> skippedKeys,
485             List<CaptureResult.Key<?>> allKeys,
486             CaptureRequest.Builder requestBuilder, CaptureResult result, String cameraId,
487             int resultCount) throws Exception {
488         String failMsg = "Failed capture result " + resultCount + " test";
489         String cameraIdString = " ";
490         if (cameraId != null) {
491             cameraIdString += "for physical camera " + cameraId;
492         }
493         boolean verifyMatchRequest = (requestBuilder != null);
494         for (CaptureResult.Key<?> key : allKeys) {
495             if (!skippedKeys.contains(key)) {
496                 /**
497                  * Check the critical tags here.
498                  * TODO: Can use the same key for request and result when request/result
499                  * becomes symmetric (b/14059883). Then below check can be wrapped into
500                  * a generic function.
501                  */
502                 String msg = failMsg + cameraIdString + "for key " + key.getName();
503                 if (verifyMatchRequest) {
504                     if (key.equals(CaptureResult.CONTROL_AE_MODE)) {
505                         errorCollector.expectEquals(msg,
506                                 requestBuilder.get(CaptureRequest.CONTROL_AE_MODE),
507                                 result.get(CaptureResult.CONTROL_AE_MODE));
508                     } else if (key.equals(CaptureResult.CONTROL_AF_MODE)) {
509                         errorCollector.expectEquals(msg,
510                                 requestBuilder.get(CaptureRequest.CONTROL_AF_MODE),
511                                 result.get(CaptureResult.CONTROL_AF_MODE));
512                     } else if (key.equals(CaptureResult.CONTROL_AWB_MODE)) {
513                         errorCollector.expectEquals(msg,
514                                 requestBuilder.get(CaptureRequest.CONTROL_AWB_MODE),
515                                 result.get(CaptureResult.CONTROL_AWB_MODE));
516                     } else if (key.equals(CaptureResult.CONTROL_MODE)) {
517                         errorCollector.expectEquals(msg,
518                                 requestBuilder.get(CaptureRequest.CONTROL_MODE),
519                                 result.get(CaptureResult.CONTROL_MODE));
520                     } else if (key.equals(CaptureResult.STATISTICS_FACE_DETECT_MODE)) {
521                         errorCollector.expectEquals(msg,
522                                 requestBuilder.get(CaptureRequest.STATISTICS_FACE_DETECT_MODE),
523                                 result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE));
524                     } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
525                         errorCollector.expectEquals(msg,
526                                 requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
527                                 result.get(CaptureResult.NOISE_REDUCTION_MODE));
528                     } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
529                         errorCollector.expectEquals(msg,
530                                 requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
531                                 result.get(CaptureResult.NOISE_REDUCTION_MODE));
532                     } else if (key.equals(CaptureResult.REQUEST_PIPELINE_DEPTH)) {
533 
534                     } else if (key.equals(CaptureResult.STATISTICS_OIS_DATA_MODE)) {
535                         errorCollector.expectEquals(msg,
536                                 requestBuilder.get(CaptureRequest.STATISTICS_OIS_DATA_MODE),
537                                 result.get(CaptureResult.STATISTICS_OIS_DATA_MODE));
538                     } else if (key.equals(CaptureResult.DISTORTION_CORRECTION_MODE)) {
539                         errorCollector.expectEquals(msg,
540                                 requestBuilder.get(CaptureRequest.DISTORTION_CORRECTION_MODE),
541                                 result.get(CaptureResult.DISTORTION_CORRECTION_MODE));
542                     } else if (key.equals(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL)) {
543                         float[] blackLevel = errorCollector.expectKeyValueNotNull(
544                                 result, CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
545                         if (blackLevel != null && staticInfo.isMonochromeCamera()) {
546                             errorCollector.expectEquals(
547                                     "Monochrome camera dynamic blacklevel must be 2x2",
548                                     blackLevel.length, 4);
549                             for (int index = 1; index < blackLevel.length; index++) {
550                                 errorCollector.expectEquals(
551                                     "Monochrome camera 2x2 channels blacklevel value must be the same.",
552                                     blackLevel[index], blackLevel[0]);
553                             }
554                         }
555                     } else {
556                         // Only do non-null check for the rest of keys.
557                         errorCollector.expectKeyValueNotNull(failMsg, result, key);
558                     }
559                 } else {
560                     // Only do non-null check for the rest of keys.
561                     errorCollector.expectKeyValueNotNull(failMsg, result, key);
562                 }
563             } else {
564                 // These keys should always be null
565                 if (key.equals(CaptureResult.CONTROL_AE_REGIONS)) {
566                     errorCollector.expectNull(
567                             "Capture result contains AE regions but aeMaxRegions is 0"
568                             + cameraIdString,
569                             result.get(CaptureResult.CONTROL_AE_REGIONS));
570                 } else if (key.equals(CaptureResult.CONTROL_AWB_REGIONS)) {
571                     errorCollector.expectNull(
572                             "Capture result contains AWB regions but awbMaxRegions is 0"
573                             + cameraIdString,
574                             result.get(CaptureResult.CONTROL_AWB_REGIONS));
575                 } else if (key.equals(CaptureResult.CONTROL_AF_REGIONS)) {
576                     errorCollector.expectNull(
577                             "Capture result contains AF regions but afMaxRegions is 0"
578                             + cameraIdString,
579                             result.get(CaptureResult.CONTROL_AF_REGIONS));
580                 }
581             }
582         }
583     }
584 
585     /*
586      * Add waiver keys per camera device hardware level and capability.
587      *
588      * Must be called after camera device is opened.
589      */
getWaiverKeysForCamera(StaticMetadata staticInfo)590     private static List<CaptureResult.Key<?>> getWaiverKeysForCamera(StaticMetadata staticInfo) {
591         List<CaptureResult.Key<?>> waiverKeys = new ArrayList<>();
592 
593         // Global waiver keys
594         waiverKeys.add(CaptureResult.JPEG_GPS_LOCATION);
595         waiverKeys.add(CaptureResult.JPEG_ORIENTATION);
596         waiverKeys.add(CaptureResult.JPEG_QUALITY);
597         waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
598         waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
599 
600         if (!staticInfo.isUltraHighResolutionSensor()) {
601             waiverKeys.add(CaptureResult.SENSOR_PIXEL_MODE);
602             waiverKeys.add(CaptureResult.SENSOR_RAW_BINNING_FACTOR_USED);
603         }
604 
605         // Keys only present when corresponding control is on are being
606         // verified in its own functional test
607         // Only present in certain tonemap mode. Test in CaptureRequestTest.
608         waiverKeys.add(CaptureResult.TONEMAP_CURVE);
609         waiverKeys.add(CaptureResult.TONEMAP_GAMMA);
610         waiverKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
611         // Only present when test pattern mode is SOLID_COLOR.
612         // TODO: verify this key in test pattern test later
613         waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
614         // Only present when STATISTICS_LENS_SHADING_MAP_MODE is ON
615         waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
616         // Only present when STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES is ON
617         waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
618         // Only present when face detection is on
619         waiverKeys.add(CaptureResult.STATISTICS_FACES);
620         // Only present in reprocessing capture result.
621         waiverKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
622 
623         // LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID not required if key is not supported.
624         if (!staticInfo.isLogicalMultiCamera() ||
625                 !staticInfo.isActivePhysicalCameraIdSupported()) {
626             waiverKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
627         }
628 
629         //Keys not required if RAW is not supported
630         if (!staticInfo.isCapabilitySupported(
631                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
632             waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
633             waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
634             waiverKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
635         } else if (staticInfo.isMonochromeCamera()) {
636             waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
637             waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
638         }
639 
640         boolean calibrationReported = staticInfo.areKeysAvailable(
641                 CameraCharacteristics.LENS_POSE_ROTATION,
642                 CameraCharacteristics.LENS_POSE_TRANSLATION,
643                 CameraCharacteristics.LENS_INTRINSIC_CALIBRATION);
644 
645         // If any of distortion coefficients is reported in CameraCharacteristics, HAL must
646         // also report (one of) them in CaptureResult
647         boolean distortionReported =
648                 staticInfo.areKeysAvailable(
649                         CameraCharacteristics.LENS_RADIAL_DISTORTION) ||
650                 staticInfo.areKeysAvailable(
651                         CameraCharacteristics.LENS_DISTORTION);
652 
653         //Keys for lens distortion correction
654         boolean distortionCorrectionSupported = staticInfo.isDistortionCorrectionSupported();
655         if (!distortionCorrectionSupported) {
656             waiverKeys.add(CaptureResult.DISTORTION_CORRECTION_MODE);
657         }
658 
659         boolean mustReportDistortion = true;
660         // These keys must present on either DEPTH or distortion correction devices
661         if (!staticInfo.isCapabilitySupported(
662                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) &&
663                 !distortionCorrectionSupported &&
664                 !distortionReported) {
665             mustReportDistortion = false;
666             waiverKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
667             waiverKeys.add(CaptureResult.LENS_DISTORTION);
668         } else {
669             // Radial distortion doesn't need to be present for new devices, or old devices that
670             // opt in the new lens distortion tag.
671             CameraCharacteristics c = staticInfo.getCharacteristics();
672             if (Build.VERSION.DEVICE_INITIAL_SDK_INT > Build.VERSION_CODES.O_MR1 ||
673                     c.get(CameraCharacteristics.LENS_DISTORTION) != null) {
674                 waiverKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
675             }
676         }
677 
678         // Calibration keys must exist for
679         //   - DEPTH capable devices
680         //   - Devices that reports calibration keys in static metadata
681         //   - Devices that reports lens distortion keys in static metadata
682         if (!staticInfo.isCapabilitySupported(
683                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) &&
684                 !calibrationReported && !mustReportDistortion) {
685             waiverKeys.add(CaptureResult.LENS_POSE_ROTATION);
686             waiverKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
687             waiverKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
688         }
689 
690         // Waived if RAW output is not supported
691         int[] outputFormats = staticInfo.getAvailableFormats(
692                 StaticMetadata.StreamDirection.Output);
693         boolean supportRaw = false;
694         for (int format : outputFormats) {
695             if (format == ImageFormat.RAW_SENSOR || format == ImageFormat.RAW10 ||
696                     format == ImageFormat.RAW12 || format == ImageFormat.RAW_PRIVATE) {
697                 supportRaw = true;
698                 break;
699             }
700         }
701         if (!supportRaw) {
702             waiverKeys.add(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
703         }
704 
705         // Waived if MONOCHROME capability
706         if (staticInfo.isMonochromeCamera()) {
707             waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
708             waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
709             waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
710         }
711 
712         if (staticInfo.getAeMaxRegionsChecked() == 0) {
713             waiverKeys.add(CaptureResult.CONTROL_AE_REGIONS);
714         }
715         if (staticInfo.getAwbMaxRegionsChecked() == 0) {
716             waiverKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
717         }
718         if (staticInfo.getAfMaxRegionsChecked() == 0) {
719             waiverKeys.add(CaptureResult.CONTROL_AF_REGIONS);
720         }
721 
722         // Keys for dynamic black/white levels
723         if (!staticInfo.isOpticalBlackRegionSupported()) {
724             waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
725             waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
726         }
727 
728         if (!staticInfo.isEnableZslSupported()) {
729             waiverKeys.add(CaptureResult.CONTROL_ENABLE_ZSL);
730         }
731 
732         if (!staticInfo.isAfSceneChangeSupported()) {
733             waiverKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
734         }
735 
736         if (!staticInfo.isOisDataModeSupported()) {
737             waiverKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
738             waiverKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
739         }
740 
741         if (staticInfo.getAvailableExtendedSceneModeCapsChecked().length == 0) {
742             waiverKeys.add(CaptureResult.CONTROL_EXTENDED_SCENE_MODE);
743         }
744 
745         if (!staticInfo.isRotateAndCropSupported()) {
746             waiverKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
747         }
748 
749         if (staticInfo.isHardwareLevelAtLeastFull()) {
750             return waiverKeys;
751         }
752 
753         /*
754          * Hardware Level = LIMITED or LEGACY
755          */
756         // Key not present if certain control is not supported
757         if (!staticInfo.isColorCorrectionSupported()) {
758             waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
759             waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
760             waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
761         }
762 
763         if (!staticInfo.isManualColorAberrationControlSupported()) {
764             waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
765         }
766 
767         if (!staticInfo.isManualToneMapSupported()) {
768             waiverKeys.add(CaptureResult.TONEMAP_MODE);
769         }
770 
771         if (!staticInfo.isEdgeModeControlSupported()) {
772             waiverKeys.add(CaptureResult.EDGE_MODE);
773         }
774 
775         if (!staticInfo.isHotPixelMapModeControlSupported()) {
776             waiverKeys.add(CaptureResult.HOT_PIXEL_MODE);
777         }
778 
779         if (!staticInfo.isNoiseReductionModeControlSupported()) {
780             waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
781         }
782 
783         if (!staticInfo.isManualLensShadingMapSupported()) {
784             waiverKeys.add(CaptureResult.SHADING_MODE);
785         }
786 
787         //Keys not required if neither MANUAL_SENSOR nor READ_SENSOR_SETTINGS is supported
788         if (!staticInfo.isCapabilitySupported(
789                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) &&
790             !staticInfo.isCapabilitySupported(
791                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS)) {
792             waiverKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
793             waiverKeys.add(CaptureResult.SENSOR_SENSITIVITY);
794             waiverKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
795             waiverKeys.add(CaptureResult.LENS_APERTURE);
796         }
797 
798         if (!staticInfo.isCapabilitySupported(
799                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
800             waiverKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
801             waiverKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
802             waiverKeys.add(CaptureResult.LENS_FOCUS_RANGE);
803             waiverKeys.add(CaptureResult.LENS_STATE);
804             waiverKeys.add(CaptureResult.LENS_FILTER_DENSITY);
805         }
806 
807         if (staticInfo.isHardwareLevelLimited() && staticInfo.isColorOutputSupported()) {
808             return waiverKeys;
809         }
810 
811         /*
812          * Hardware Level = EXTERNAL
813          */
814         if (staticInfo.isExternalCamera()) {
815             waiverKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
816             waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
817             waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
818         }
819 
820         if (staticInfo.isExternalCamera() && staticInfo.isColorOutputSupported()) {
821             return waiverKeys;
822         }
823 
824         /*
825          * Hardware Level = LEGACY or no regular output is supported
826          */
827         waiverKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
828         waiverKeys.add(CaptureResult.CONTROL_AE_STATE);
829         waiverKeys.add(CaptureResult.CONTROL_AWB_STATE);
830         waiverKeys.add(CaptureResult.FLASH_STATE);
831         waiverKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
832         waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
833         waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
834         waiverKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
835         waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
836         waiverKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
837         waiverKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
838 
839         if (staticInfo.isHardwareLevelLegacy()) {
840             return waiverKeys;
841         }
842 
843         /*
844          * Regular output not supported, only depth, waive color-output-related keys
845          */
846         waiverKeys.add(CaptureResult.CONTROL_SCENE_MODE);
847         waiverKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
848         waiverKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
849         waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
850         waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
851         waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
852         waiverKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
853         waiverKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
854         waiverKeys.add(CaptureResult.CONTROL_AE_LOCK);
855         waiverKeys.add(CaptureResult.CONTROL_AE_MODE);
856         waiverKeys.add(CaptureResult.CONTROL_AF_MODE);
857         waiverKeys.add(CaptureResult.CONTROL_AWB_MODE);
858         waiverKeys.add(CaptureResult.CONTROL_AWB_LOCK);
859         waiverKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
860         waiverKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
861         waiverKeys.add(CaptureResult.FLASH_MODE);
862         waiverKeys.add(CaptureResult.SCALER_CROP_REGION);
863         waiverKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
864 
865         return waiverKeys;
866     }
867 
868     /**
869      * A capture listener implementation for collecting both partial and total results.
870      *
871      * <p> This is not a full-blown class and has some implicit assumptions. The class groups
872      * capture results by capture request, so the user must guarantee each request this listener
873      * is listening is unique. This class is not thread safe, so don't attach an instance object
874      * with multiple handlers.</p>
875      * */
876     private static class TotalAndPartialResultListener
877             extends CameraCaptureSession.CaptureCallback {
878         static final int ERROR_DUPLICATED_REQUEST = 1 << 0;
879         static final int ERROR_WRONG_CALLBACK_ORDER = 1 << 1;
880 
881         private final LinkedBlockingQueue<Pair<TotalCaptureResult, List<CaptureResult>> > mQueue =
882                 new LinkedBlockingQueue<>();
883         private final HashMap<CaptureRequest, List<CaptureResult>> mPartialResultsMap =
884                 new HashMap<CaptureRequest, List<CaptureResult>>();
885         private final HashSet<CaptureRequest> completedRequests = new HashSet<>();
886         private int errorCode = 0;
887 
888         @Override
onCaptureStarted( CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)889         public void onCaptureStarted(
890             CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)
891         {
892             checkCallbackOrder(request);
893             createMapEntryIfNecessary(request);
894         }
895 
896         @Override
onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result)897         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
898                 TotalCaptureResult result) {
899             try {
900                 List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
901                 if (partialResultsList == null) {
902                     Log.w(TAG, "onCaptureCompleted: unknown request");
903                 }
904                 mQueue.put(new Pair<TotalCaptureResult, List<CaptureResult>>(
905                         result, partialResultsList));
906                 mPartialResultsMap.remove(request);
907                 boolean newEntryAdded = completedRequests.add(request);
908                 if (!newEntryAdded) {
909                     Integer frame = (Integer) request.getTag();
910                     Log.e(TAG, "Frame " + frame + "ERROR_DUPLICATED_REQUEST");
911                     errorCode |= ERROR_DUPLICATED_REQUEST;
912                 }
913             } catch (InterruptedException e) {
914                 throw new UnsupportedOperationException(
915                         "Can't handle InterruptedException in onCaptureCompleted");
916             }
917         }
918 
919         @Override
onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult)920         public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
921                 CaptureResult partialResult) {
922             createMapEntryIfNecessary(request);
923             List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
924             partialResultsList.add(partialResult);
925         }
926 
createMapEntryIfNecessary(CaptureRequest request)927         private void createMapEntryIfNecessary(CaptureRequest request) {
928             if (!mPartialResultsMap.containsKey(request)) {
929                 // create a new entry in the map
930                 mPartialResultsMap.put(request, new ArrayList<CaptureResult>());
931             }
932         }
933 
checkCallbackOrder(CaptureRequest request)934         private void checkCallbackOrder(CaptureRequest request) {
935             if (completedRequests.contains(request)) {
936                 Integer frame = (Integer) request.getTag();
937                 Log.e(TAG, "Frame " + frame + "ERROR_WRONG_CALLBACK_ORDER");
938                 errorCode |= ERROR_WRONG_CALLBACK_ORDER;
939             }
940         }
941 
getCaptureResultPairs(long timeout)942         public Pair<TotalCaptureResult, List<CaptureResult>> getCaptureResultPairs(long timeout) {
943             try {
944                 Pair<TotalCaptureResult, List<CaptureResult>> result =
945                         mQueue.poll(timeout, TimeUnit.MILLISECONDS);
946                 assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
947                 return result;
948             } catch (InterruptedException e) {
949                 throw new UnsupportedOperationException("Unhandled interrupted exception", e);
950             }
951         }
952 
getErrorCode()953         public int getErrorCode() {
954             return errorCode;
955         }
956     }
957 
958     // Returns true if `result` has timestamp `sensorTimestamp` when queried from the NDK via
959     // ACameraMetadata_fromCameraMetadata().
validateACameraMetadataFromCameraMetadataCriticalTagsNative( CaptureResult result, long sensorTimestamp)960     private static native boolean validateACameraMetadataFromCameraMetadataCriticalTagsNative(
961         CaptureResult result, long sensorTimestamp);
962 
963     // First stash a native ACameraMetadata created from a capture result, then compare the stored value
964     // to the passed-in timestamp.
stashACameraMetadataFromCameraMetadataNative(CaptureResult result)965     private static native boolean stashACameraMetadataFromCameraMetadataNative(CaptureResult result);
validateStashedACameraMetadataFromCameraMetadataNative(long timestamp)966     private static native boolean validateStashedACameraMetadataFromCameraMetadataNative(long timestamp);
967 
968     /**
969      * TODO: Use CameraCharacteristics.getAvailableCaptureResultKeys() once we can filter out
970      * @hide keys.
971      *
972      */
973 
974     /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
975      * The key entries below this point are generated from metadata
976      * definitions in /system/media/camera/docs. Do not modify by hand or
977      * modify the comment blocks at the start or end.
978      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
979 
getAllCaptureResultKeys()980     private static List<CaptureResult.Key<?>> getAllCaptureResultKeys() {
981         ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
982         resultKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
983         resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
984         resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
985         resultKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
986         resultKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
987         resultKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
988         resultKeys.add(CaptureResult.CONTROL_AE_LOCK);
989         resultKeys.add(CaptureResult.CONTROL_AE_MODE);
990         resultKeys.add(CaptureResult.CONTROL_AE_REGIONS);
991         resultKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
992         resultKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
993         resultKeys.add(CaptureResult.CONTROL_AF_MODE);
994         resultKeys.add(CaptureResult.CONTROL_AF_REGIONS);
995         resultKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
996         resultKeys.add(CaptureResult.CONTROL_AWB_LOCK);
997         resultKeys.add(CaptureResult.CONTROL_AWB_MODE);
998         resultKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
999         resultKeys.add(CaptureResult.CONTROL_CAPTURE_INTENT);
1000         resultKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
1001         resultKeys.add(CaptureResult.CONTROL_MODE);
1002         resultKeys.add(CaptureResult.CONTROL_SCENE_MODE);
1003         resultKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
1004         resultKeys.add(CaptureResult.CONTROL_AE_STATE);
1005         resultKeys.add(CaptureResult.CONTROL_AF_STATE);
1006         resultKeys.add(CaptureResult.CONTROL_AWB_STATE);
1007         resultKeys.add(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
1008         resultKeys.add(CaptureResult.CONTROL_ENABLE_ZSL);
1009         resultKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
1010         resultKeys.add(CaptureResult.CONTROL_EXTENDED_SCENE_MODE);
1011         resultKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
1012         resultKeys.add(CaptureResult.EDGE_MODE);
1013         resultKeys.add(CaptureResult.FLASH_MODE);
1014         resultKeys.add(CaptureResult.FLASH_STATE);
1015         resultKeys.add(CaptureResult.HOT_PIXEL_MODE);
1016         resultKeys.add(CaptureResult.JPEG_GPS_LOCATION);
1017         resultKeys.add(CaptureResult.JPEG_ORIENTATION);
1018         resultKeys.add(CaptureResult.JPEG_QUALITY);
1019         resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
1020         resultKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
1021         resultKeys.add(CaptureResult.LENS_APERTURE);
1022         resultKeys.add(CaptureResult.LENS_FILTER_DENSITY);
1023         resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
1024         resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
1025         resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
1026         resultKeys.add(CaptureResult.LENS_POSE_ROTATION);
1027         resultKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
1028         resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
1029         resultKeys.add(CaptureResult.LENS_STATE);
1030         resultKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
1031         resultKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
1032         resultKeys.add(CaptureResult.LENS_DISTORTION);
1033         resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
1034         resultKeys.add(CaptureResult.REQUEST_PIPELINE_DEPTH);
1035         resultKeys.add(CaptureResult.SCALER_CROP_REGION);
1036         resultKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
1037         resultKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
1038         resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
1039         resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
1040         resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
1041         resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
1042         resultKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
1043         resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
1044         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
1045         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
1046         resultKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
1047         resultKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
1048         resultKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
1049         resultKeys.add(CaptureResult.SENSOR_PIXEL_MODE);
1050         resultKeys.add(CaptureResult.SENSOR_RAW_BINNING_FACTOR_USED);
1051         resultKeys.add(CaptureResult.SHADING_MODE);
1052         resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
1053         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
1054         resultKeys.add(CaptureResult.STATISTICS_FACES);
1055         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
1056         resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
1057         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
1058         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
1059         resultKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
1060         resultKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
1061         resultKeys.add(CaptureResult.TONEMAP_CURVE);
1062         resultKeys.add(CaptureResult.TONEMAP_MODE);
1063         resultKeys.add(CaptureResult.TONEMAP_GAMMA);
1064         resultKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
1065         resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
1066         resultKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
1067         resultKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
1068         resultKeys.add(CaptureResult.DISTORTION_CORRECTION_MODE);
1069 
1070         return resultKeys;
1071     }
1072 
1073     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
1074      * End generated code
1075      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
1076 }
1077