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