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 on devices capable of reporting intra-frame statistics
631         waiverKeys.add(CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES);
632         // Only present on logical cameras that switch between lenses when going trhough zoom ratios
633         waiverKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION);
634 
635         // Only present on devices that support low light boose AE mode
636         if (!staticInfo.isAeModeLowLightBoostSupported()) {
637             waiverKeys.add(CaptureResult.CONTROL_LOW_LIGHT_BOOST_STATE);
638         }
639 
640         // LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID not required if key is not supported.
641         if (!staticInfo.isLogicalMultiCamera() ||
642                 !staticInfo.isActivePhysicalCameraIdSupported()) {
643             waiverKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
644         }
645 
646         //Keys not required if RAW is not supported
647         if (!staticInfo.isCapabilitySupported(
648                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
649             waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
650             waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
651             waiverKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
652         } else if (staticInfo.isMonochromeCamera()) {
653             waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
654             waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
655         }
656 
657         boolean calibrationReported = staticInfo.areKeysAvailable(
658                 CameraCharacteristics.LENS_POSE_ROTATION,
659                 CameraCharacteristics.LENS_POSE_TRANSLATION,
660                 CameraCharacteristics.LENS_INTRINSIC_CALIBRATION);
661 
662         // If any of distortion coefficients is reported in CameraCharacteristics, HAL must
663         // also report (one of) them in CaptureResult
664         boolean distortionReported =
665                 staticInfo.areKeysAvailable(
666                         CameraCharacteristics.LENS_RADIAL_DISTORTION) ||
667                 staticInfo.areKeysAvailable(
668                         CameraCharacteristics.LENS_DISTORTION);
669 
670         //Keys for lens distortion correction
671         boolean distortionCorrectionSupported = staticInfo.isDistortionCorrectionSupported();
672         if (!distortionCorrectionSupported) {
673             waiverKeys.add(CaptureResult.DISTORTION_CORRECTION_MODE);
674         }
675 
676         boolean mustReportDistortion = true;
677         // These keys must present on either DEPTH or distortion correction devices
678         if (!staticInfo.isCapabilitySupported(
679                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) &&
680                 !distortionCorrectionSupported &&
681                 !distortionReported) {
682             mustReportDistortion = false;
683             waiverKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
684             waiverKeys.add(CaptureResult.LENS_DISTORTION);
685         } else {
686             // Radial distortion doesn't need to be present for new devices, or old devices that
687             // opt in the new lens distortion tag.
688             CameraCharacteristics c = staticInfo.getCharacteristics();
689             if (Build.VERSION.DEVICE_INITIAL_SDK_INT > Build.VERSION_CODES.O_MR1 ||
690                     c.get(CameraCharacteristics.LENS_DISTORTION) != null) {
691                 waiverKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
692             }
693         }
694 
695         // Calibration keys must exist for
696         //   - DEPTH capable devices
697         //   - Devices that reports calibration keys in static metadata
698         //   - Devices that reports lens distortion keys in static metadata
699         if (!staticInfo.isCapabilitySupported(
700                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) &&
701                 !calibrationReported && !mustReportDistortion) {
702             waiverKeys.add(CaptureResult.LENS_POSE_ROTATION);
703             waiverKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
704             waiverKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
705         }
706 
707         // Waived if RAW output is not supported
708         int[] outputFormats = staticInfo.getAvailableFormats(
709                 StaticMetadata.StreamDirection.Output);
710         boolean supportRaw = false;
711         for (int format : outputFormats) {
712             if (format == ImageFormat.RAW_SENSOR || format == ImageFormat.RAW10 ||
713                     format == ImageFormat.RAW12 || format == ImageFormat.RAW_PRIVATE) {
714                 supportRaw = true;
715                 break;
716             }
717         }
718         if (!supportRaw) {
719             waiverKeys.add(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
720         }
721 
722         // Waived if MONOCHROME capability
723         if (staticInfo.isMonochromeCamera()) {
724             waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
725             waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
726             waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
727         }
728 
729         if (staticInfo.getAeMaxRegionsChecked() == 0) {
730             waiverKeys.add(CaptureResult.CONTROL_AE_REGIONS);
731         }
732         if (staticInfo.getAwbMaxRegionsChecked() == 0) {
733             waiverKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
734         }
735         if (staticInfo.getAfMaxRegionsChecked() == 0) {
736             waiverKeys.add(CaptureResult.CONTROL_AF_REGIONS);
737         }
738 
739         // Keys for dynamic black/white levels
740         if (!staticInfo.isOpticalBlackRegionSupported()) {
741             waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
742             waiverKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
743         }
744 
745         if (!staticInfo.isEnableZslSupported()) {
746             waiverKeys.add(CaptureResult.CONTROL_ENABLE_ZSL);
747         }
748 
749         if (!staticInfo.isAfSceneChangeSupported()) {
750             waiverKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
751         }
752 
753         if (!staticInfo.isOisDataModeSupported()) {
754             waiverKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
755             waiverKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
756         }
757 
758         if (staticInfo.getAvailableExtendedSceneModeCapsChecked().length == 0) {
759             waiverKeys.add(CaptureResult.CONTROL_EXTENDED_SCENE_MODE);
760         }
761 
762         if (!staticInfo.isRotateAndCropSupported()) {
763             waiverKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
764         }
765 
766         if (!staticInfo.isSettingsOverrideSupported()) {
767             waiverKeys.add(CaptureResult.CONTROL_SETTINGS_OVERRIDE);
768         }
769 
770         if (staticInfo.isHardwareLevelAtLeastFull()) {
771             return waiverKeys;
772         }
773 
774         /*
775          * Hardware Level = LIMITED or LEGACY
776          */
777         // Key not present if certain control is not supported
778         if (!staticInfo.isColorCorrectionSupported()) {
779             waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
780             waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
781             waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
782         }
783 
784         if (!staticInfo.isManualColorAberrationControlSupported()) {
785             waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
786         }
787 
788         if (!staticInfo.isManualToneMapSupported()) {
789             waiverKeys.add(CaptureResult.TONEMAP_MODE);
790         }
791 
792         if (!staticInfo.isEdgeModeControlSupported()) {
793             waiverKeys.add(CaptureResult.EDGE_MODE);
794         }
795 
796         if (!staticInfo.isHotPixelMapModeControlSupported()) {
797             waiverKeys.add(CaptureResult.HOT_PIXEL_MODE);
798         }
799 
800         if (!staticInfo.isNoiseReductionModeControlSupported()) {
801             waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
802         }
803 
804         if (!staticInfo.isManualLensShadingMapSupported()) {
805             waiverKeys.add(CaptureResult.SHADING_MODE);
806         }
807 
808         //Keys not required if neither MANUAL_SENSOR nor READ_SENSOR_SETTINGS is supported
809         if (!staticInfo.isCapabilitySupported(
810                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) &&
811             !staticInfo.isCapabilitySupported(
812                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS)) {
813             waiverKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
814             waiverKeys.add(CaptureResult.SENSOR_SENSITIVITY);
815             waiverKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
816             waiverKeys.add(CaptureResult.LENS_APERTURE);
817         }
818 
819         if (!staticInfo.isCapabilitySupported(
820                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
821             waiverKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
822             waiverKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
823             waiverKeys.add(CaptureResult.LENS_FOCUS_RANGE);
824             waiverKeys.add(CaptureResult.LENS_STATE);
825             waiverKeys.add(CaptureResult.LENS_FILTER_DENSITY);
826         }
827 
828         if (staticInfo.isHardwareLevelLimited() && staticInfo.isColorOutputSupported()) {
829             return waiverKeys;
830         }
831 
832         /*
833          * Hardware Level = EXTERNAL
834          */
835         if (staticInfo.isExternalCamera()) {
836             waiverKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
837             waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
838             waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
839         }
840 
841         if (staticInfo.isExternalCamera() && staticInfo.isColorOutputSupported()) {
842             return waiverKeys;
843         }
844 
845         /*
846          * Hardware Level = LEGACY or no regular output is supported
847          */
848         waiverKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
849         waiverKeys.add(CaptureResult.CONTROL_AE_STATE);
850         waiverKeys.add(CaptureResult.CONTROL_AWB_STATE);
851         waiverKeys.add(CaptureResult.FLASH_STATE);
852         waiverKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
853         waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
854         waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
855         waiverKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
856         waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
857         waiverKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
858         waiverKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
859 
860         if (staticInfo.isHardwareLevelLegacy()) {
861             return waiverKeys;
862         }
863 
864         /*
865          * Regular output not supported, only depth, waive color-output-related keys
866          */
867         waiverKeys.add(CaptureResult.CONTROL_SCENE_MODE);
868         waiverKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
869         waiverKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
870         waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
871         waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
872         waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
873         waiverKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
874         waiverKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
875         waiverKeys.add(CaptureResult.CONTROL_AE_LOCK);
876         waiverKeys.add(CaptureResult.CONTROL_AE_MODE);
877         waiverKeys.add(CaptureResult.CONTROL_AF_MODE);
878         waiverKeys.add(CaptureResult.CONTROL_AWB_MODE);
879         waiverKeys.add(CaptureResult.CONTROL_AWB_LOCK);
880         waiverKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
881         waiverKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
882         waiverKeys.add(CaptureResult.FLASH_MODE);
883         waiverKeys.add(CaptureResult.SCALER_CROP_REGION);
884         waiverKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
885 
886         return waiverKeys;
887     }
888 
889     /**
890      * A capture listener implementation for collecting both partial and total results.
891      *
892      * <p> This is not a full-blown class and has some implicit assumptions. The class groups
893      * capture results by capture request, so the user must guarantee each request this listener
894      * is listening is unique. This class is not thread safe, so don't attach an instance object
895      * with multiple handlers.</p>
896      * */
897     private static class TotalAndPartialResultListener
898             extends CameraCaptureSession.CaptureCallback {
899         static final int ERROR_DUPLICATED_REQUEST = 1 << 0;
900         static final int ERROR_WRONG_CALLBACK_ORDER = 1 << 1;
901 
902         private final LinkedBlockingQueue<Pair<TotalCaptureResult, List<CaptureResult>> > mQueue =
903                 new LinkedBlockingQueue<>();
904         private final HashMap<CaptureRequest, List<CaptureResult>> mPartialResultsMap =
905                 new HashMap<CaptureRequest, List<CaptureResult>>();
906         private final HashSet<CaptureRequest> completedRequests = new HashSet<>();
907         private int errorCode = 0;
908 
909         @Override
onCaptureStarted( CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)910         public void onCaptureStarted(
911             CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)
912         {
913             checkCallbackOrder(request);
914             createMapEntryIfNecessary(request);
915         }
916 
917         @Override
onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result)918         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
919                 TotalCaptureResult result) {
920             try {
921                 List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
922                 if (partialResultsList == null) {
923                     Log.w(TAG, "onCaptureCompleted: unknown request");
924                 }
925                 mQueue.put(new Pair<TotalCaptureResult, List<CaptureResult>>(
926                         result, partialResultsList));
927                 mPartialResultsMap.remove(request);
928                 boolean newEntryAdded = completedRequests.add(request);
929                 if (!newEntryAdded) {
930                     Integer frame = (Integer) request.getTag();
931                     Log.e(TAG, "Frame " + frame + "ERROR_DUPLICATED_REQUEST");
932                     errorCode |= ERROR_DUPLICATED_REQUEST;
933                 }
934             } catch (InterruptedException e) {
935                 throw new UnsupportedOperationException(
936                         "Can't handle InterruptedException in onCaptureCompleted");
937             }
938         }
939 
940         @Override
onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult)941         public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
942                 CaptureResult partialResult) {
943             createMapEntryIfNecessary(request);
944             List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
945             partialResultsList.add(partialResult);
946         }
947 
createMapEntryIfNecessary(CaptureRequest request)948         private void createMapEntryIfNecessary(CaptureRequest request) {
949             if (!mPartialResultsMap.containsKey(request)) {
950                 // create a new entry in the map
951                 mPartialResultsMap.put(request, new ArrayList<CaptureResult>());
952             }
953         }
954 
checkCallbackOrder(CaptureRequest request)955         private void checkCallbackOrder(CaptureRequest request) {
956             if (completedRequests.contains(request)) {
957                 Integer frame = (Integer) request.getTag();
958                 Log.e(TAG, "Frame " + frame + "ERROR_WRONG_CALLBACK_ORDER");
959                 errorCode |= ERROR_WRONG_CALLBACK_ORDER;
960             }
961         }
962 
getCaptureResultPairs(long timeout)963         public Pair<TotalCaptureResult, List<CaptureResult>> getCaptureResultPairs(long timeout) {
964             try {
965                 Pair<TotalCaptureResult, List<CaptureResult>> result =
966                         mQueue.poll(timeout, TimeUnit.MILLISECONDS);
967                 assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
968                 return result;
969             } catch (InterruptedException e) {
970                 throw new UnsupportedOperationException("Unhandled interrupted exception", e);
971             }
972         }
973 
getErrorCode()974         public int getErrorCode() {
975             return errorCode;
976         }
977     }
978 
979     // Returns true if `result` has timestamp `sensorTimestamp` when queried from the NDK via
980     // ACameraMetadata_fromCameraMetadata().
validateACameraMetadataFromCameraMetadataCriticalTagsNative( CaptureResult result, long sensorTimestamp)981     private static native boolean validateACameraMetadataFromCameraMetadataCriticalTagsNative(
982         CaptureResult result, long sensorTimestamp);
983 
984     // First stash a native ACameraMetadata created from a capture result, then compare the stored value
985     // to the passed-in timestamp.
stashACameraMetadataFromCameraMetadataNative(CaptureResult result)986     private static native boolean stashACameraMetadataFromCameraMetadataNative(CaptureResult result);
validateStashedACameraMetadataFromCameraMetadataNative(long timestamp)987     private static native boolean validateStashedACameraMetadataFromCameraMetadataNative(long timestamp);
988 
989     /**
990      * TODO: Use CameraCharacteristics.getAvailableCaptureResultKeys() once we can filter out
991      * @hide keys.
992      *
993      */
994 
995     /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
996      * The key entries below this point are generated from metadata
997      * definitions in /system/media/camera/docs. Do not modify by hand or
998      * modify the comment blocks at the start or end.
999      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
1000 
getAllCaptureResultKeys()1001     private static List<CaptureResult.Key<?>> getAllCaptureResultKeys() {
1002         ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
1003         resultKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
1004         resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
1005         resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
1006         resultKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
1007         resultKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
1008         resultKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
1009         resultKeys.add(CaptureResult.CONTROL_AE_LOCK);
1010         resultKeys.add(CaptureResult.CONTROL_AE_MODE);
1011         resultKeys.add(CaptureResult.CONTROL_AE_REGIONS);
1012         resultKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
1013         resultKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
1014         resultKeys.add(CaptureResult.CONTROL_AF_MODE);
1015         resultKeys.add(CaptureResult.CONTROL_AF_REGIONS);
1016         resultKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
1017         resultKeys.add(CaptureResult.CONTROL_AWB_LOCK);
1018         resultKeys.add(CaptureResult.CONTROL_AWB_MODE);
1019         resultKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
1020         resultKeys.add(CaptureResult.CONTROL_CAPTURE_INTENT);
1021         resultKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
1022         resultKeys.add(CaptureResult.CONTROL_MODE);
1023         resultKeys.add(CaptureResult.CONTROL_SCENE_MODE);
1024         resultKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
1025         resultKeys.add(CaptureResult.CONTROL_AE_STATE);
1026         resultKeys.add(CaptureResult.CONTROL_AF_STATE);
1027         resultKeys.add(CaptureResult.CONTROL_AWB_STATE);
1028         resultKeys.add(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
1029         resultKeys.add(CaptureResult.CONTROL_ENABLE_ZSL);
1030         resultKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
1031         resultKeys.add(CaptureResult.CONTROL_EXTENDED_SCENE_MODE);
1032         resultKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
1033         resultKeys.add(CaptureResult.CONTROL_SETTINGS_OVERRIDE);
1034         resultKeys.add(CaptureResult.CONTROL_AUTOFRAMING);
1035         resultKeys.add(CaptureResult.CONTROL_AUTOFRAMING_STATE);
1036         if (Flags.cameraAeModeLowLightBoost()) {
1037             resultKeys.add(CaptureResult.CONTROL_LOW_LIGHT_BOOST_STATE);
1038         }
1039         resultKeys.add(CaptureResult.EDGE_MODE);
1040         resultKeys.add(CaptureResult.FLASH_MODE);
1041         resultKeys.add(CaptureResult.FLASH_STATE);
1042         if (Flags.cameraManualFlashStrengthControl()) {
1043             resultKeys.add(CaptureResult.FLASH_STRENGTH_LEVEL);
1044         }
1045         resultKeys.add(CaptureResult.HOT_PIXEL_MODE);
1046         resultKeys.add(CaptureResult.JPEG_GPS_LOCATION);
1047         resultKeys.add(CaptureResult.JPEG_ORIENTATION);
1048         resultKeys.add(CaptureResult.JPEG_QUALITY);
1049         resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
1050         resultKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
1051         resultKeys.add(CaptureResult.LENS_APERTURE);
1052         resultKeys.add(CaptureResult.LENS_FILTER_DENSITY);
1053         resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
1054         resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
1055         resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
1056         resultKeys.add(CaptureResult.LENS_POSE_ROTATION);
1057         resultKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
1058         resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
1059         resultKeys.add(CaptureResult.LENS_STATE);
1060         resultKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
1061         resultKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
1062         resultKeys.add(CaptureResult.LENS_DISTORTION);
1063         resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
1064         resultKeys.add(CaptureResult.REQUEST_PIPELINE_DEPTH);
1065         resultKeys.add(CaptureResult.SCALER_CROP_REGION);
1066         resultKeys.add(CaptureResult.SCALER_ROTATE_AND_CROP);
1067         resultKeys.add(CaptureResult.SCALER_RAW_CROP_REGION);
1068         resultKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
1069         resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
1070         resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
1071         resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
1072         resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
1073         resultKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
1074         resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
1075         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
1076         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
1077         resultKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
1078         resultKeys.add(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL);
1079         resultKeys.add(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL);
1080         resultKeys.add(CaptureResult.SENSOR_PIXEL_MODE);
1081         resultKeys.add(CaptureResult.SENSOR_RAW_BINNING_FACTOR_USED);
1082         resultKeys.add(CaptureResult.SHADING_MODE);
1083         resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
1084         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
1085         resultKeys.add(CaptureResult.STATISTICS_FACES);
1086         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
1087         resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
1088         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
1089         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
1090         resultKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
1091         resultKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
1092         if (Flags.concertMode()) {
1093             resultKeys.add(CaptureResult.STATISTICS_LENS_INTRINSICS_SAMPLES);
1094         }
1095         resultKeys.add(CaptureResult.TONEMAP_CURVE);
1096         resultKeys.add(CaptureResult.TONEMAP_MODE);
1097         resultKeys.add(CaptureResult.TONEMAP_GAMMA);
1098         resultKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
1099         resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
1100         resultKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
1101         resultKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
1102         if (Flags.concertMode()) {
1103             resultKeys.add(CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION);
1104         }
1105         resultKeys.add(CaptureResult.DISTORTION_CORRECTION_MODE);
1106 
1107         return resultKeys;
1108     }
1109 
1110     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
1111      * End generated code
1112      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
1113 }
1114