/*
 * Copyright 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.camera2.cts;

import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.SystemClock;
import android.util.Pair;
import android.util.Size;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;

import static android.hardware.camera2.cts.CameraTestUtils.*;
import static android.hardware.camera2.cts.helpers.CameraSessionUtils.*;

import android.util.Log;
import android.view.Surface;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class CaptureResultTest extends Camera2AndroidTestCase {
    private static final String TAG = "CaptureResultTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final int MAX_NUM_IMAGES = MAX_READER_IMAGES;
    private static final int NUM_FRAMES_VERIFIED = 30;
    private static final long WAIT_FOR_RESULT_TIMEOUT_MS = 3000;

    // List that includes all public keys from CaptureResult
    List<CaptureResult.Key<?>> mAllKeys;

    // List tracking the failed test keys.

    @Override
    public void setContext(Context context) {
        mAllKeys = getAllCaptureResultKeys();
        super.setContext(context);

        /**
         * Workaround for mockito and JB-MR2 incompatibility
         *
         * Avoid java.lang.IllegalArgumentException: dexcache == null
         * https://code.google.com/p/dexmaker/issues/detail?id=2
         */
        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    /**
     * <p>
     * Basic non-null check test for multiple capture results.
     * </p>
     * <p>
     * When capturing many frames, some camera devices may return some results that have null keys
     * randomly, which is an API violation and could cause application crash randomly. This test
     * runs a typical flexible yuv capture many times, and checks if there is any null entries in
     * a capture result.
     * </p>
     */
    public void testCameraCaptureResultAllKeys() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (mStaticInfo.isColorOutputSupported()) {
                    // Create image reader and surface.
                    Size size = mOrderedPreviewSizes.get(0);
                    createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
                            new ImageDropperListener());
                } else {
                    Size size = getMaxDepthSize(id, mCameraManager);
                    createDefaultImageReader(size, ImageFormat.DEPTH16, MAX_NUM_IMAGES,
                            new ImageDropperListener());
                }

                // Configure output streams.
                List<Surface> outputSurfaces = new ArrayList<Surface>(1);
                outputSurfaces.add(mReaderSurface);
                createSession(outputSurfaces);

                CaptureRequest.Builder requestBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                assertNotNull("Failed to create capture request", requestBuilder);
                requestBuilder.addTarget(mReaderSurface);

                // Start capture
                SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
                startCapture(requestBuilder.build(), /*repeating*/true, captureListener, mHandler);

                // Get the waived keys for current camera device
                List<CaptureResult.Key<?>> waiverkeys = getWaiverKeysForCamera();

                // Verify results
                validateCaptureResult(captureListener, waiverkeys, requestBuilder,
                        NUM_FRAMES_VERIFIED);

                stopCapture(/*fast*/false);
            } finally {
                closeDevice(id);
                closeDefaultImageReader();
            }
        }
    }

    /**
     * Check partial results conform to its specification.
     * <p>
     * The test is skipped if partial result is not supported on device. </p>
     * <p>Test summary:<ul>
     * <li>1. Number of partial results is less than or equal to
     * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}.
     * <li>2. Each key appeared in partial results must be unique across all partial results.
     * <li>3. All keys appeared in partial results must be present in TotalCaptureResult
     * <li>4. Also test onCaptureComplete callback always happen after onCaptureStart or
     * onCaptureProgressed callbacks.
     * </ul></p>
     */
    public void testPartialResult() throws Exception {
        final int NUM_FRAMES_TESTED = 30;
        final int WAIT_FOR_RESULT_TIMOUT_MS = 2000;
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                // Skip the test if partial result is not supported
                int partialResultCount = mStaticInfo.getPartialResultCount();
                if (partialResultCount == 1) {
                    continue;
                }

                // Create image reader and surface.
                if (mStaticInfo.isColorOutputSupported()) {
                    Size size = mOrderedPreviewSizes.get(0);
                    createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
                            new ImageDropperListener());
                } else {
                    Size size = getMaxDepthSize(id, mCameraManager);
                    createDefaultImageReader(size, ImageFormat.DEPTH16, MAX_NUM_IMAGES,
                            new ImageDropperListener());
                }

                // Configure output streams.
                List<Surface> outputSurfaces = new ArrayList<Surface>(1);
                outputSurfaces.add(mReaderSurface);
                createSession(outputSurfaces);

                CaptureRequest.Builder requestBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                assertNotNull("Failed to create capture request", requestBuilder);
                requestBuilder.addTarget(mReaderSurface);
                TotalAndPartialResultListener listener =
                        new TotalAndPartialResultListener();

                // Start capture
                for (Integer frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
                    // Set a different tag for each request so the listener can group
                    // partial results by each request
                    requestBuilder.setTag(frame);
                    startCapture(
                            requestBuilder.build(), /*repeating*/false,
                            listener, mHandler);
                }

                // Verify capture results
                for (int frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
                    Pair<TotalCaptureResult, List<CaptureResult>> resultPair =
                            listener.getCaptureResultPairs(WAIT_FOR_RESULT_TIMOUT_MS);

                    List<CaptureResult> partialResults = resultPair.second;

                    if (partialResults == null) {
                        // HAL only sends total result is legal
                        partialResults = new ArrayList<>();
                    }

                    TotalCaptureResult totalResult = resultPair.first;

                    mCollector.expectLessOrEqual("Too many partial results",
                            partialResultCount, partialResults.size());
                    Set<CaptureResult.Key<?>> appearedPartialKeys =
                            new HashSet<CaptureResult.Key<?>>();
                    for (CaptureResult partialResult : partialResults) {
                        List<CaptureResult.Key<?>> partialKeys = partialResult.getKeys();
                        mCollector.expectValuesUnique("Partial result keys: ", partialKeys);
                        for (CaptureResult.Key<?> key : partialKeys) {
                            mCollector.expectTrue(
                                    String.format("Key %s appears in multiple partial results",
                                            key.getName()),
                                    !appearedPartialKeys.contains(key));
                        }
                        appearedPartialKeys.addAll(partialKeys);
                    }

                    // Test total result against the partial results
                    List<CaptureResult.Key<?>> totalResultKeys = totalResult.getKeys();
                    mCollector.expectTrue(
                            "TotalCaptureResult must be a super set of partial capture results",
                            totalResultKeys.containsAll(appearedPartialKeys));

                    List<CaptureResult> totalResultPartials = totalResult.getPartialResults();
                    mCollector.expectEquals("TotalCaptureResult's partial results must match " +
                            "the ones observed by #onCaptureProgressed",
                            partialResults, totalResultPartials);

                    if (VERBOSE) {
                        Log.v(TAG, "testPartialResult - Observed " +
                                partialResults.size() + "; queried for " +
                                totalResultPartials.size());
                    }
                }

                int errorCode = listener.getErrorCode();
                if ((errorCode & TotalAndPartialResultListener.ERROR_DUPLICATED_REQUEST) != 0) {
                    mCollector.addMessage("Listener received multiple onCaptureComplete" +
                            " callback for the same request");
                }
                if ((errorCode & TotalAndPartialResultListener.ERROR_WRONG_CALLBACK_ORDER) != 0) {
                    mCollector.addMessage("Listener received onCaptureStart or" +
                            " onCaptureProgressed after onCaptureComplete");
                }

                stopCapture(/*fast*/false);
            } finally {
                closeDevice(id);
                closeDefaultImageReader();
            }
        }
    }

    /**
     * Check that the timestamps passed in the results, buffers, and capture callbacks match for
     * a single request, and increase monotonically
     */
    public void testResultTimestamps() throws Exception {
        for (String id : mCameraIds) {
            ImageReader previewReader = null;
            ImageReader jpegReader = null;

            SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
            SimpleImageReaderListener prevListener = new SimpleImageReaderListener();
            try {
                openDevice(id);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
                    continue;
                }

                CaptureRequest.Builder previewBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                CaptureRequest.Builder multiBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

                // Create image reader and surface.
                Size previewSize = mOrderedPreviewSizes.get(0);
                Size jpegSize = mOrderedStillSizes.get(0);

                // Create ImageReaders.
                previewReader = makeImageReader(previewSize, ImageFormat.YUV_420_888,
                        MAX_NUM_IMAGES, prevListener, mHandler);
                jpegReader = makeImageReader(jpegSize, ImageFormat.JPEG,
                        MAX_NUM_IMAGES, jpegListener, mHandler);

                // Configure output streams with preview and jpeg streams.
                List<Surface> outputSurfaces = new ArrayList<>(Arrays.asList(
                        previewReader.getSurface(), jpegReader.getSurface()));

                SessionListener mockSessionListener = getMockSessionListener();

                CameraCaptureSession session = configureAndVerifySession(mockSessionListener,
                        mCamera, outputSurfaces, mHandler);

                // Configure the requests.
                previewBuilder.addTarget(previewReader.getSurface());
                multiBuilder.addTarget(previewReader.getSurface());
                multiBuilder.addTarget(jpegReader.getSurface());

                CaptureCallback mockCaptureCallback = getMockCaptureListener();

                // Capture targeting only preview
                Pair<TotalCaptureResult, Long> result = captureAndVerifyResult(mockCaptureCallback,
                        session, previewBuilder.build(), mHandler);

                // Check if all timestamps are the same
                Image prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                validateTimestamps("Result 1", result.first,
                        prevImage, result.second);
                prevImage.close();

                // Capture targeting both jpeg and preview
                Pair<TotalCaptureResult, Long> result2 = captureAndVerifyResult(mockCaptureCallback,
                        session, multiBuilder.build(), mHandler);

                // Check if all timestamps are the same
                prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                validateTimestamps("Result 2 Preview", result2.first,
                        prevImage, result2.second);
                validateTimestamps("Result 2 Jpeg", result2.first,
                        jpegImage, result2.second);
                prevImage.close();
                jpegImage.close();

                // Check if timestamps are increasing
                mCollector.expectGreater("Timestamps must be increasing.", result.second,
                        result2.second);

                // Capture two preview frames
                long startTime = SystemClock.elapsedRealtimeNanos();
                Pair<TotalCaptureResult, Long> result3 = captureAndVerifyResult(mockCaptureCallback,
                        session, previewBuilder.build(), mHandler);
                Pair<TotalCaptureResult, Long> result4 = captureAndVerifyResult(mockCaptureCallback,
                        session, previewBuilder.build(), mHandler);
                long clockDiff = SystemClock.elapsedRealtimeNanos() - startTime;
                long resultDiff = result4.second - result3.second;

                // Check if all timestamps are the same
                prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                validateTimestamps("Result 3", result3.first,
                        prevImage, result3.second);
                prevImage.close();
                prevImage = prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                validateTimestamps("Result 4", result4.first,
                        prevImage, result4.second);
                prevImage.close();

                // Check that the timestamps monotonically increase at a reasonable rate
                mCollector.expectGreaterOrEqual("Timestamps increase faster than system clock.",
                        resultDiff, clockDiff);
                mCollector.expectGreater("Timestamps must be increasing.", result3.second,
                        result4.second);
            } finally {
                closeDevice(id);
                closeImageReader(previewReader);
                closeImageReader(jpegReader);
            }
        }
    }

    private void validateTimestamps(String msg, TotalCaptureResult result, Image resultImage,
                                    long captureTime) {
        mCollector.expectKeyValueEquals(result, CaptureResult.SENSOR_TIMESTAMP, captureTime);
        mCollector.expectEquals(msg + ": Capture timestamp must be same as resultImage timestamp",
                resultImage.getTimestamp(), captureTime);
    }

    private void validateCaptureResult(SimpleCaptureCallback captureListener,
            List<CaptureResult.Key<?>> skippedKeys, CaptureRequest.Builder requestBuilder,
            int numFramesVerified) throws Exception {
        CaptureResult result = null;
        for (int i = 0; i < numFramesVerified; i++) {
            String failMsg = "Failed capture result " + i + " test ";
            result = captureListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);

            for (CaptureResult.Key<?> key : mAllKeys) {
                if (!skippedKeys.contains(key)) {
                    /**
                     * Check the critical tags here.
                     * TODO: Can use the same key for request and result when request/result
                     * becomes symmetric (b/14059883). Then below check can be wrapped into
                     * a generic function.
                     */
                    String msg = failMsg + "for key " + key.getName();
                    if (key.equals(CaptureResult.CONTROL_AE_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.CONTROL_AE_MODE),
                                result.get(CaptureResult.CONTROL_AE_MODE));
                    } else if (key.equals(CaptureResult.CONTROL_AF_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.CONTROL_AF_MODE),
                                result.get(CaptureResult.CONTROL_AF_MODE));
                    } else if (key.equals(CaptureResult.CONTROL_AWB_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.CONTROL_AWB_MODE),
                                result.get(CaptureResult.CONTROL_AWB_MODE));
                    } else if (key.equals(CaptureResult.CONTROL_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.CONTROL_MODE),
                                result.get(CaptureResult.CONTROL_MODE));
                    } else if (key.equals(CaptureResult.STATISTICS_FACE_DETECT_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.STATISTICS_FACE_DETECT_MODE),
                                result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE));
                    } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
                                result.get(CaptureResult.NOISE_REDUCTION_MODE));
                    } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
                        mCollector.expectEquals(msg,
                                requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
                                result.get(CaptureResult.NOISE_REDUCTION_MODE));
                    } else if (key.equals(CaptureResult.REQUEST_PIPELINE_DEPTH)) {

                    } else {
                        // Only do non-null check for the rest of keys.
                        mCollector.expectKeyValueNotNull(failMsg, result, key);
                    }
                } else {
                    // These keys should always be null
                    if (key.equals(CaptureResult.CONTROL_AE_REGIONS)) {
                        mCollector.expectNull(
                                "Capture result contains AE regions but aeMaxRegions is 0",
                                result.get(CaptureResult.CONTROL_AE_REGIONS));
                    } else if (key.equals(CaptureResult.CONTROL_AWB_REGIONS)) {
                        mCollector.expectNull(
                                "Capture result contains AWB regions but awbMaxRegions is 0",
                                result.get(CaptureResult.CONTROL_AWB_REGIONS));
                    } else if (key.equals(CaptureResult.CONTROL_AF_REGIONS)) {
                        mCollector.expectNull(
                                "Capture result contains AF regions but afMaxRegions is 0",
                                result.get(CaptureResult.CONTROL_AF_REGIONS));
                    }
                }
            }
        }
    }

    /*
     * Add waiver keys per camera device hardware level and capability.
     *
     * Must be called after camera device is opened.
     */
    private List<CaptureResult.Key<?>> getWaiverKeysForCamera() {
        List<CaptureResult.Key<?>> waiverKeys = new ArrayList<>();

        // Global waiver keys
        waiverKeys.add(CaptureResult.JPEG_GPS_LOCATION);
        waiverKeys.add(CaptureResult.JPEG_ORIENTATION);
        waiverKeys.add(CaptureResult.JPEG_QUALITY);
        waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
        waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);

        // Keys only present when corresponding control is on are being
        // verified in its own functional test
        // Only present in certain tonemap mode. Test in CaptureRequestTest.
        waiverKeys.add(CaptureResult.TONEMAP_CURVE);
        waiverKeys.add(CaptureResult.TONEMAP_GAMMA);
        waiverKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
        // Only present when test pattern mode is SOLID_COLOR.
        // TODO: verify this key in test pattern test later
        waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
        // Only present when STATISTICS_LENS_SHADING_MAP_MODE is ON
        waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
        // Only present when STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES is ON
        waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
        // Only present when face detection is on
        waiverKeys.add(CaptureResult.STATISTICS_FACES);
        // Only present in reprocessing capture result.
        waiverKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);

        //Keys not required if RAW is not supported
        if (!mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
            waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
            waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
            waiverKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
        }

        //Keys for depth output capability
        if (!mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT)) {
            waiverKeys.add(CaptureResult.LENS_POSE_ROTATION);
            waiverKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
            waiverKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
            waiverKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
        }

        if (mStaticInfo.getAeMaxRegionsChecked() == 0) {
            waiverKeys.add(CaptureResult.CONTROL_AE_REGIONS);
        }
        if (mStaticInfo.getAwbMaxRegionsChecked() == 0) {
            waiverKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
        }
        if (mStaticInfo.getAfMaxRegionsChecked() == 0) {
            waiverKeys.add(CaptureResult.CONTROL_AF_REGIONS);
        }

        if (mStaticInfo.isHardwareLevelFull()) {
            return waiverKeys;
        }

        /*
         * Hardware Level = LIMITED or LEGACY
         */
        // Key not present if certain control is not supported
        if (!mStaticInfo.isColorCorrectionSupported()) {
            waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
            waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
            waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
        }

        if (!mStaticInfo.isManualColorAberrationControlSupported()) {
            waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
        }

        if (!mStaticInfo.isManualToneMapSupported()) {
            waiverKeys.add(CaptureResult.TONEMAP_MODE);
        }

        if (!mStaticInfo.isEdgeModeControlSupported()) {
            waiverKeys.add(CaptureResult.EDGE_MODE);
        }

        if (!mStaticInfo.isHotPixelMapModeControlSupported()) {
            waiverKeys.add(CaptureResult.HOT_PIXEL_MODE);
        }

        if (!mStaticInfo.isNoiseReductionModeControlSupported()) {
            waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
        }

        if (!mStaticInfo.isManualLensShadingMapSupported()) {
            waiverKeys.add(CaptureResult.SHADING_MODE);
        }

        //Keys not required if neither MANUAL_SENSOR nor READ_SENSOR_SETTINGS is supported
        if (!mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) &&
            !mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS)) {
            waiverKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
            waiverKeys.add(CaptureResult.SENSOR_SENSITIVITY);
            waiverKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
            waiverKeys.add(CaptureResult.LENS_APERTURE);
        }

        if (!mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
            waiverKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
            waiverKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
            waiverKeys.add(CaptureResult.LENS_FOCUS_RANGE);
            waiverKeys.add(CaptureResult.LENS_STATE);
            waiverKeys.add(CaptureResult.LENS_FILTER_DENSITY);
        }

        if (mStaticInfo.isHardwareLevelLimited() && mStaticInfo.isColorOutputSupported()) {
            return waiverKeys;
        }

        /*
         * Hardware Level = LEGACY or no regular output is supported
         */
        waiverKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
        waiverKeys.add(CaptureResult.CONTROL_AE_STATE);
        waiverKeys.add(CaptureResult.CONTROL_AWB_STATE);
        waiverKeys.add(CaptureResult.FLASH_STATE);
        waiverKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
        waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
        waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
        waiverKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
        waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
        waiverKeys.add(CaptureResult.CONTROL_AF_TRIGGER);

        if (mStaticInfo.isHardwareLevelLegacy()) {
            return waiverKeys;
        }

        /*
         * Regular output not supported, only depth, waive color-output-related keys
         */
        waiverKeys.add(CaptureResult.CONTROL_SCENE_MODE);
        waiverKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
        waiverKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
        waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
        waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
        waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
        waiverKeys.add(CaptureResult.CONTROL_AE_LOCK);
        waiverKeys.add(CaptureResult.CONTROL_AE_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AF_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AWB_MODE);
        waiverKeys.add(CaptureResult.CONTROL_AWB_LOCK);
        waiverKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
        waiverKeys.add(CaptureResult.FLASH_MODE);
        waiverKeys.add(CaptureResult.SCALER_CROP_REGION);

        return waiverKeys;
    }

    /**
     * A capture listener implementation for collecting both partial and total results.
     *
     * <p> This is not a full-blown class and has some implicit assumptions. The class groups
     * capture results by capture request, so the user must guarantee each request this listener
     * is listening is unique. This class is not thread safe, so don't attach an instance object
     * with multiple handlers.</p>
     * */
    private static class TotalAndPartialResultListener
            extends CameraCaptureSession.CaptureCallback {
        static final int ERROR_DUPLICATED_REQUEST = 1 << 0;
        static final int ERROR_WRONG_CALLBACK_ORDER = 1 << 1;

        private final LinkedBlockingQueue<Pair<TotalCaptureResult, List<CaptureResult>> > mQueue =
                new LinkedBlockingQueue<>();
        private final HashMap<CaptureRequest, List<CaptureResult>> mPartialResultsMap =
                new HashMap<CaptureRequest, List<CaptureResult>>();
        private final HashSet<CaptureRequest> completedRequests = new HashSet<>();
        private int errorCode = 0;

        @Override
        public void onCaptureStarted(
            CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)
        {
            checkCallbackOrder(request);
            createMapEntryIfNecessary(request);
        }

        @Override
        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                TotalCaptureResult result) {
            try {
                List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
                if (partialResultsList == null) {
                    Log.w(TAG, "onCaptureCompleted: unknown request");
                }
                mQueue.put(new Pair<TotalCaptureResult, List<CaptureResult>>(
                        result, partialResultsList));
                mPartialResultsMap.remove(request);
                boolean newEntryAdded = completedRequests.add(request);
                if (!newEntryAdded) {
                    Integer frame = (Integer) request.getTag();
                    Log.e(TAG, "Frame " + frame + "ERROR_DUPLICATED_REQUEST");
                    errorCode |= ERROR_DUPLICATED_REQUEST;
                }
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureCompleted");
            }
        }

        @Override
        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
                CaptureResult partialResult) {
            createMapEntryIfNecessary(request);
            List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
            partialResultsList.add(partialResult);
        }

        private void createMapEntryIfNecessary(CaptureRequest request) {
            if (!mPartialResultsMap.containsKey(request)) {
                // create a new entry in the map
                mPartialResultsMap.put(request, new ArrayList<CaptureResult>());
            }
        }

        private void checkCallbackOrder(CaptureRequest request) {
            if (completedRequests.contains(request)) {
                Integer frame = (Integer) request.getTag();
                Log.e(TAG, "Frame " + frame + "ERROR_WRONG_CALLBACK_ORDER");
                errorCode |= ERROR_WRONG_CALLBACK_ORDER;
            }
        }

        public Pair<TotalCaptureResult, List<CaptureResult>> getCaptureResultPairs(long timeout) {
            try {
                Pair<TotalCaptureResult, List<CaptureResult>> result =
                        mQueue.poll(timeout, TimeUnit.MILLISECONDS);
                assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
                return result;
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }
        }

        public int getErrorCode() {
            return errorCode;
        }
    }

    /**
     * TODO: Use CameraCharacteristics.getAvailableCaptureResultKeys() once we can filter out
     * @hide keys.
     *
     */

    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
     * The key entries below this point are generated from metadata
     * definitions in /system/media/camera/docs. Do not modify by hand or
     * modify the comment blocks at the start or end.
     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/

    private static List<CaptureResult.Key<?>> getAllCaptureResultKeys() {
        ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
        resultKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
        resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
        resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
        resultKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
        resultKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
        resultKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
        resultKeys.add(CaptureResult.CONTROL_AE_LOCK);
        resultKeys.add(CaptureResult.CONTROL_AE_MODE);
        resultKeys.add(CaptureResult.CONTROL_AE_REGIONS);
        resultKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
        resultKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
        resultKeys.add(CaptureResult.CONTROL_AF_MODE);
        resultKeys.add(CaptureResult.CONTROL_AF_REGIONS);
        resultKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
        resultKeys.add(CaptureResult.CONTROL_AWB_LOCK);
        resultKeys.add(CaptureResult.CONTROL_AWB_MODE);
        resultKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
        resultKeys.add(CaptureResult.CONTROL_CAPTURE_INTENT);
        resultKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
        resultKeys.add(CaptureResult.CONTROL_MODE);
        resultKeys.add(CaptureResult.CONTROL_SCENE_MODE);
        resultKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
        resultKeys.add(CaptureResult.CONTROL_AE_STATE);
        resultKeys.add(CaptureResult.CONTROL_AF_STATE);
        resultKeys.add(CaptureResult.CONTROL_AWB_STATE);
        resultKeys.add(CaptureResult.EDGE_MODE);
        resultKeys.add(CaptureResult.FLASH_MODE);
        resultKeys.add(CaptureResult.FLASH_STATE);
        resultKeys.add(CaptureResult.HOT_PIXEL_MODE);
        resultKeys.add(CaptureResult.JPEG_GPS_LOCATION);
        resultKeys.add(CaptureResult.JPEG_ORIENTATION);
        resultKeys.add(CaptureResult.JPEG_QUALITY);
        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
        resultKeys.add(CaptureResult.LENS_APERTURE);
        resultKeys.add(CaptureResult.LENS_FILTER_DENSITY);
        resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
        resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
        resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
        resultKeys.add(CaptureResult.LENS_POSE_ROTATION);
        resultKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
        resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
        resultKeys.add(CaptureResult.LENS_STATE);
        resultKeys.add(CaptureResult.LENS_INTRINSIC_CALIBRATION);
        resultKeys.add(CaptureResult.LENS_RADIAL_DISTORTION);
        resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
        resultKeys.add(CaptureResult.REQUEST_PIPELINE_DEPTH);
        resultKeys.add(CaptureResult.SCALER_CROP_REGION);
        resultKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
        resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
        resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
        resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
        resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
        resultKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
        resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
        resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
        resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_MODE);
        resultKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
        resultKeys.add(CaptureResult.SHADING_MODE);
        resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
        resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
        resultKeys.add(CaptureResult.STATISTICS_FACES);
        resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
        resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
        resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
        resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
        resultKeys.add(CaptureResult.TONEMAP_CURVE);
        resultKeys.add(CaptureResult.TONEMAP_MODE);
        resultKeys.add(CaptureResult.TONEMAP_GAMMA);
        resultKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
        resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
        resultKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);

        return resultKeys;
    }

    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
     * End generated code
     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
}
