/*
 * Copyright 2015 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 static android.hardware.camera2.cts.CameraTestUtils.*;

import android.graphics.ImageFormat;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.InputConfiguration;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;

import com.android.ex.camera2.blocking.BlockingSessionCallback;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>Tests for Reprocess API.</p>
 */
@AppModeFull
public class ReprocessCaptureTest extends Camera2SurfaceViewTestCase  {
    private static final String TAG = "ReprocessCaptureTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final int CAPTURE_TIMEOUT_FRAMES = 100;
    private static final int CAPTURE_TIMEOUT_MS = 3000;
    private static final int WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS = 1000;
    private static final int CAPTURE_TEMPLATE = CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG;
    private static final int ZSL_TEMPLATE = CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG;
    private static final int NUM_REPROCESS_TEST_LOOP = 3;
    private static final int NUM_REPROCESS_CAPTURES = 3;
    private static final int NUM_REPROCESS_BURST = 3;
    private int mDumpFrameCount = 0;

    // The image reader for the first regular capture
    private ImageReader mFirstImageReader;
    // The image reader for the reprocess capture
    private ImageReader mSecondImageReader;
    // A flag indicating whether the regular capture and the reprocess capture share the same image
    // reader. If it's true, mFirstImageReader should be used for regular and reprocess outputs.
    private boolean mShareOneImageReader;
    private SimpleImageReaderListener mFirstImageReaderListener;
    private SimpleImageReaderListener mSecondImageReaderListener;
    private Surface mInputSurface;
    private ImageWriter mImageWriter;
    private SimpleImageWriterListener mImageWriterListener;

    private enum CaptureTestCase {
        SINGLE_SHOT,
        BURST,
        MIXED_BURST,
        ABORT_CAPTURE,
        TIMESTAMPS,
        JPEG_EXIF,
        REQUEST_KEYS,
    }

    /**
     * Test YUV_420_888 -> YUV_420_888 with maximal supported sizes
     */
    public void testBasicYuvToYuvReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id)) {
                continue;
            }

            // YUV_420_888 -> YUV_420_888 must be supported.
            testBasicReprocessing(id, ImageFormat.YUV_420_888, ImageFormat.YUV_420_888);
        }
    }

    /**
     * Test YUV_420_888 -> JPEG with maximal supported sizes
     */
    public void testBasicYuvToJpegReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id)) {
                continue;
            }

            // YUV_420_888 -> JPEG must be supported.
            testBasicReprocessing(id, ImageFormat.YUV_420_888, ImageFormat.JPEG);
        }
    }

    /**
     * Test OPAQUE -> YUV_420_888 with maximal supported sizes
     */
    public void testBasicOpaqueToYuvReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isOpaqueReprocessSupported(id)) {
                continue;
            }

            // Opaque -> YUV_420_888 must be supported.
            testBasicReprocessing(id, ImageFormat.PRIVATE, ImageFormat.YUV_420_888);
        }
    }

    /**
     * Test OPAQUE -> JPEG with maximal supported sizes
     */
    public void testBasicOpaqueToJpegReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isOpaqueReprocessSupported(id)) {
                continue;
            }

            // OPAQUE -> JPEG must be supported.
            testBasicReprocessing(id, ImageFormat.PRIVATE, ImageFormat.JPEG);
        }
    }

    /**
     * Test all supported size and format combinations.
     */
    public void testReprocessingSizeFormat() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);
                // no preview
                testReprocessingAllCombinations(id, /*previewSize*/null,
                        CaptureTestCase.SINGLE_SHOT);
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test all supported size and format combinations with preview.
     */
    public void testReprocessingSizeFormatWithPreview() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);
                testReprocessingAllCombinations(id, mOrderedPreviewSizes.get(0),
                        CaptureTestCase.SINGLE_SHOT);
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test recreating reprocessing sessions.
     */
    public void testRecreateReprocessingSessions() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                openDevice(id);

                // Test supported input/output formats with the largest sizes.
                int[] inputFormats =
                        mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
                for (int inputFormat : inputFormats) {
                    int[] reprocessOutputFormats =
                            mStaticInfo.getValidOutputFormatsForInput(inputFormat);
                    for (int reprocessOutputFormat : reprocessOutputFormats) {
                        Size maxInputSize =
                                getMaxSize(inputFormat, StaticMetadata.StreamDirection.Input);
                        Size maxReprocessOutputSize = getMaxSize(reprocessOutputFormat,
                                StaticMetadata.StreamDirection.Output);

                        for (int i = 0; i < NUM_REPROCESS_TEST_LOOP; i++) {
                            testReprocess(id, maxInputSize, inputFormat, maxReprocessOutputSize,
                                    reprocessOutputFormat,
                                    /* previewSize */null, NUM_REPROCESS_CAPTURES);
                        }
                    }
                }
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Verify issuing cross session capture requests is invalid.
     */
    public void testCrossSessionCaptureException() throws Exception {
        for (String id : mCameraIds) {
            // Test one supported input format -> JPEG
            int inputFormat;
            int reprocessOutputFormat = ImageFormat.JPEG;

            if (isOpaqueReprocessSupported(id)) {
                inputFormat = ImageFormat.PRIVATE;
            } else if (isYuvReprocessSupported(id)) {
                inputFormat = ImageFormat.YUV_420_888;
            } else {
                continue;
            }

            openDevice(id);

            // Test the largest sizes
            Size inputSize =
                    getMaxSize(inputFormat, StaticMetadata.StreamDirection.Input);
            Size reprocessOutputSize =
                    getMaxSize(reprocessOutputFormat, StaticMetadata.StreamDirection.Output);

            try {
                if (VERBOSE) {
                    Log.v(TAG, "testCrossSessionCaptureException: cameraId: " + id +
                            " inputSize: " + inputSize + " inputFormat: " + inputFormat +
                            " reprocessOutputSize: " + reprocessOutputSize +
                            " reprocessOutputFormat: " + reprocessOutputFormat);
                }

                setupImageReaders(inputSize, inputFormat, reprocessOutputSize,
                        reprocessOutputFormat, /*maxImages*/1);
                setupReprocessableSession(/*previewSurface*/null, /*numImageWriterImages*/1);

                TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                        /*inputResult*/null);
                Image image = mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS);

                // queue the image to image writer
                mImageWriter.queueInputImage(image);

                // recreate the session
                closeReprossibleSession();
                setupReprocessableSession(/*previewSurface*/null, /*numImageWriterImages*/1);
                try {
                    TotalCaptureResult reprocessResult;
                    // issue and wait on reprocess capture request
                    reprocessResult = submitCaptureRequest(
                            getReprocessOutputImageReader().getSurface(), result);
                    fail("Camera " + id + ": should get IllegalArgumentException for cross " +
                            "session reprocess captrue.");
                } catch (IllegalArgumentException e) {
                    // expected
                    if (DEBUG) {
                        Log.d(TAG, "Camera " + id + ": get IllegalArgumentException for cross " +
                                "session reprocess capture as expected: " + e.getMessage());
                    }
                }
            } finally {
                closeReprossibleSession();
                closeImageReaders();
                closeDevice();
            }
        }
    }

    /**
     * Test burst reprocessing captures with and without preview.
     */
    public void testBurstReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);
                // no preview
                testReprocessingAllCombinations(id, /*previewSize*/null, CaptureTestCase.BURST);
                // with preview
                testReprocessingAllCombinations(id, mOrderedPreviewSizes.get(0),
                        CaptureTestCase.BURST);
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test burst captures mixed with regular and reprocess captures with and without preview.
     */
    public void testMixedBurstReprocessing() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);
                // no preview
                testReprocessingAllCombinations(id, /*previewSize*/null,
                        CaptureTestCase.MIXED_BURST);
                // with preview
                testReprocessingAllCombinations(id, mOrderedPreviewSizes.get(0),
                        CaptureTestCase.MIXED_BURST);
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test aborting reprocess capture requests of the largest input and output sizes for each
     * supported format.
     */
    public void testReprocessAbort() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);

                int[] supportedInputFormats =
                    mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
                for (int inputFormat : supportedInputFormats) {
                    int[] supportedReprocessOutputFormats =
                            mStaticInfo.getValidOutputFormatsForInput(inputFormat);
                    for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
                        testReprocessingMaxSizes(id, inputFormat, reprocessOutputFormat,
                                /*previewSize*/null, CaptureTestCase.ABORT_CAPTURE);
                    }
                }
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test reprocess timestamps for the largest input and output sizes for each supported format.
     */
    public void testReprocessTimestamps() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);

                int[] supportedInputFormats =
                    mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
                for (int inputFormat : supportedInputFormats) {
                    int[] supportedReprocessOutputFormats =
                            mStaticInfo.getValidOutputFormatsForInput(inputFormat);
                    for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
                        testReprocessingMaxSizes(id, inputFormat, reprocessOutputFormat,
                                /*previewSize*/null, CaptureTestCase.TIMESTAMPS);
                    }
                }
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test reprocess jpeg output's exif data for the largest input and output sizes for each
     * supported format.
     */
    public void testReprocessJpegExif() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);

                int[] supportedInputFormats =
                    mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);

                for (int inputFormat : supportedInputFormats) {
                    int[] supportedReprocessOutputFormats =
                            mStaticInfo.getValidOutputFormatsForInput(inputFormat);

                    for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
                        if (reprocessOutputFormat == ImageFormat.JPEG) {
                            testReprocessingMaxSizes(id, inputFormat, ImageFormat.JPEG,
                                    /*previewSize*/null, CaptureTestCase.JPEG_EXIF);
                        }
                    }
                }
            } finally {
                closeDevice();
            }
        }
    }

    public void testReprocessRequestKeys() throws Exception {
        for (String id : mCameraIds) {
            if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
                continue;
            }

            try {
                // open Camera device
                openDevice(id);

                int[] supportedInputFormats =
                    mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
                for (int inputFormat : supportedInputFormats) {
                    int[] supportedReprocessOutputFormats =
                            mStaticInfo.getValidOutputFormatsForInput(inputFormat);
                    for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
                        testReprocessingMaxSizes(id, inputFormat, reprocessOutputFormat,
                                /*previewSize*/null, CaptureTestCase.REQUEST_KEYS);
                    }
                }
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test the input format and output format with the largest input and output sizes.
     */
    private void testBasicReprocessing(String cameraId, int inputFormat,
            int reprocessOutputFormat) throws Exception {
        try {
            openDevice(cameraId);

            testReprocessingMaxSizes(cameraId, inputFormat, reprocessOutputFormat,
                    /* previewSize */null, CaptureTestCase.SINGLE_SHOT);
        } finally {
            closeDevice();
        }
    }

    /**
     * Test the input format and output format with the largest input and output sizes for a
     * certain test case.
     */
    private void testReprocessingMaxSizes(String cameraId, int inputFormat,
            int reprocessOutputFormat, Size previewSize, CaptureTestCase captureTestCase)
            throws Exception {
        Size maxInputSize = getMaxSize(inputFormat, StaticMetadata.StreamDirection.Input);
        Size maxReprocessOutputSize =
                getMaxSize(reprocessOutputFormat, StaticMetadata.StreamDirection.Output);

        switch (captureTestCase) {
            case SINGLE_SHOT:
                testReprocess(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
                        reprocessOutputFormat, previewSize, NUM_REPROCESS_CAPTURES);
                break;
            case ABORT_CAPTURE:
                testReprocessAbort(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
                        reprocessOutputFormat);
                break;
            case TIMESTAMPS:
                testReprocessTimestamps(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
                        reprocessOutputFormat);
                break;
            case JPEG_EXIF:
                testReprocessJpegExif(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize);
                break;
            case REQUEST_KEYS:
                testReprocessRequestKeys(cameraId, maxInputSize, inputFormat,
                        maxReprocessOutputSize, reprocessOutputFormat);
                break;
            default:
                throw new IllegalArgumentException("Invalid test case");
        }
    }

    /**
     * Test all input format, input size, output format, and output size combinations.
     */
    private void testReprocessingAllCombinations(String cameraId, Size previewSize,
            CaptureTestCase captureTestCase) throws Exception {

        Size QCIF = new Size(176, 144);
        Size VGA = new Size(640, 480);
        Size FULL_HD = new Size(1920, 1080);
        int[] supportedInputFormats =
                mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
        for (int inputFormat : supportedInputFormats) {
            Size[] supportedInputSizes =
                    mStaticInfo.getAvailableSizesForFormatChecked(inputFormat,
                    StaticMetadata.StreamDirection.Input);

            for (Size inputSize : supportedInputSizes) {
                int[] supportedReprocessOutputFormats =
                        mStaticInfo.getValidOutputFormatsForInput(inputFormat);

                for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
                    Size[] supportedReprocessOutputSizes =
                            mStaticInfo.getAvailableSizesForFormatChecked(reprocessOutputFormat,
                            StaticMetadata.StreamDirection.Output);

                    for (Size reprocessOutputSize : supportedReprocessOutputSizes) {
                        // Handle QCIF exceptions
                        if (reprocessOutputSize.equals(QCIF) &&
                                ((inputSize.getWidth() > FULL_HD.getWidth()) ||
                                 (inputSize.getHeight() > FULL_HD.getHeight()))) {
                            continue;
                        }
                        if (inputSize.equals(QCIF) &&
                                ((reprocessOutputSize.getWidth() > FULL_HD.getWidth()) ||
                                 (reprocessOutputSize.getHeight() > FULL_HD.getHeight()))) {
                            continue;
                        }
                        if ((previewSize != null) &&
                                ((previewSize.getWidth() > FULL_HD.getWidth()) || (
                                  previewSize.getHeight() > FULL_HD.getHeight())) &&
                                (inputSize.equals(QCIF) || reprocessOutputSize.equals(QCIF))) {
                            previewSize = VGA;
                        }

                        switch (captureTestCase) {
                            case SINGLE_SHOT:
                                testReprocess(cameraId, inputSize, inputFormat,
                                        reprocessOutputSize, reprocessOutputFormat, previewSize,
                                        NUM_REPROCESS_CAPTURES);
                                break;
                            case BURST:
                                testReprocessBurst(cameraId, inputSize, inputFormat,
                                        reprocessOutputSize, reprocessOutputFormat, previewSize,
                                        NUM_REPROCESS_BURST);
                                break;
                            case MIXED_BURST:
                                testReprocessMixedBurst(cameraId, inputSize, inputFormat,
                                        reprocessOutputSize, reprocessOutputFormat, previewSize,
                                        NUM_REPROCESS_BURST);
                                break;
                            default:
                                throw new IllegalArgumentException("Invalid test case");
                        }
                    }
                }
            }
        }
    }

    /**
     * Test burst that is mixed with regular and reprocess capture requests.
     */
    private void testReprocessMixedBurst(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat, Size previewSize,
            int numBurst) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessMixedBurst: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat +
                    " previewSize: " + previewSize + " numBurst: " + numBurst);
        }

        boolean enablePreview = (previewSize != null);
        ImageResultHolder[] imageResultHolders = new ImageResultHolder[0];

        try {
            // totalNumBurst = number of regular burst + number of reprocess burst.
            int totalNumBurst = numBurst * 2;

            if (enablePreview) {
                updatePreviewSurface(previewSize);
            } else {
                mPreviewSurface = null;
            }

            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                totalNumBurst);
            setupReprocessableSession(mPreviewSurface, /*numImageWriterImages*/numBurst);

            if (enablePreview) {
                startPreview(mPreviewSurface);
            }

            // Prepare an array of booleans indicating each capture's type (regular or reprocess)
            boolean[] isReprocessCaptures = new boolean[totalNumBurst];
            for (int i = 0; i < totalNumBurst; i++) {
                if ((i & 1) == 0) {
                    isReprocessCaptures[i] = true;
                } else {
                    isReprocessCaptures[i] = false;
                }
            }

            imageResultHolders = doMixedReprocessBurstCapture(isReprocessCaptures);
            for (ImageResultHolder holder : imageResultHolders) {
                Image reprocessedImage = holder.getImage();
                TotalCaptureResult result = holder.getTotalCaptureResult();

                mCollector.expectImageProperties("testReprocessMixedBurst", reprocessedImage,
                            reprocessOutputFormat, reprocessOutputSize,
                            result.get(CaptureResult.SENSOR_TIMESTAMP));

                if (DEBUG) {
                    Log.d(TAG, String.format("camera %s in %dx%d %d out %dx%d %d",
                            cameraId, inputSize.getWidth(), inputSize.getHeight(), inputFormat,
                            reprocessOutputSize.getWidth(), reprocessOutputSize.getHeight(),
                            reprocessOutputFormat));
                    dumpImage(reprocessedImage,
                            "/testReprocessMixedBurst_camera" + cameraId + "_" + mDumpFrameCount);
                    mDumpFrameCount++;
                }
            }
        } finally {
            for (ImageResultHolder holder : imageResultHolders) {
                holder.getImage().close();
            }
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Test burst of reprocess capture requests.
     */
    private void testReprocessBurst(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat, Size previewSize,
            int numBurst) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessBurst: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat +
                    " previewSize: " + previewSize + " numBurst: " + numBurst);
        }

        boolean enablePreview = (previewSize != null);
        ImageResultHolder[] imageResultHolders = new ImageResultHolder[0];

        try {
            if (enablePreview) {
                updatePreviewSurface(previewSize);
            } else {
                mPreviewSurface = null;
            }

            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                numBurst);
            setupReprocessableSession(mPreviewSurface, numBurst);

            if (enablePreview) {
                startPreview(mPreviewSurface);
            }

            imageResultHolders = doReprocessBurstCapture(numBurst);
            for (ImageResultHolder holder : imageResultHolders) {
                Image reprocessedImage = holder.getImage();
                TotalCaptureResult result = holder.getTotalCaptureResult();

                mCollector.expectImageProperties("testReprocessBurst", reprocessedImage,
                            reprocessOutputFormat, reprocessOutputSize,
                            result.get(CaptureResult.SENSOR_TIMESTAMP));

                if (DEBUG) {
                    Log.d(TAG, String.format("camera %s in %dx%d %d out %dx%d %d",
                            cameraId, inputSize.getWidth(), inputSize.getHeight(), inputFormat,
                            reprocessOutputSize.getWidth(), reprocessOutputSize.getHeight(),
                            reprocessOutputFormat));
                    dumpImage(reprocessedImage,
                            "/testReprocessBurst_camera" + cameraId + "_" + mDumpFrameCount);
                    mDumpFrameCount++;
                }
            }
        } finally {
            for (ImageResultHolder holder : imageResultHolders) {
                holder.getImage().close();
            }
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Test a sequences of reprocess capture requests.
     */
    private void testReprocess(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat, Size previewSize,
            int numReprocessCaptures) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocess: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat +
                    " previewSize: " + previewSize);
        }

        boolean enablePreview = (previewSize != null);

        try {
            if (enablePreview) {
                updatePreviewSurface(previewSize);
            } else {
                mPreviewSurface = null;
            }

            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                    /*maxImages*/1);
            setupReprocessableSession(mPreviewSurface, /*numImageWriterImages*/1);

            if (enablePreview) {
                startPreview(mPreviewSurface);
            }

            for (int i = 0; i < numReprocessCaptures; i++) {
                ImageResultHolder imageResultHolder = null;

                try {
                    imageResultHolder = doReprocessCapture();
                    Image reprocessedImage = imageResultHolder.getImage();
                    TotalCaptureResult result = imageResultHolder.getTotalCaptureResult();

                    mCollector.expectImageProperties("testReprocess", reprocessedImage,
                            reprocessOutputFormat, reprocessOutputSize,
                            result.get(CaptureResult.SENSOR_TIMESTAMP));

                    if (DEBUG) {
                        Log.d(TAG, String.format("camera %s in %dx%d %d out %dx%d %d",
                                cameraId, inputSize.getWidth(), inputSize.getHeight(), inputFormat,
                                reprocessOutputSize.getWidth(), reprocessOutputSize.getHeight(),
                                reprocessOutputFormat));

                        dumpImage(reprocessedImage,
                                "/testReprocess_camera" + cameraId + "_" + mDumpFrameCount);
                        mDumpFrameCount++;
                    }
                } finally {
                    if (imageResultHolder != null) {
                        imageResultHolder.getImage().close();
                    }
                }
            }
        } finally {
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Test aborting a burst reprocess capture and multiple single reprocess captures.
     */
    private void testReprocessAbort(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessAbort: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat);
        }

        try {
            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                    NUM_REPROCESS_CAPTURES);
            setupReprocessableSession(/*previewSurface*/null, NUM_REPROCESS_CAPTURES);

            // Test two cases: submitting reprocess requests one by one and in a burst.
            boolean submitInBursts[] = {false, true};
            for (boolean submitInBurst : submitInBursts) {
                // Prepare reprocess capture requests.
                ArrayList<CaptureRequest> reprocessRequests =
                        new ArrayList<>(NUM_REPROCESS_CAPTURES);

                for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
                    TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                            /*inputResult*/null);

                    mImageWriter.queueInputImage(
                            mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));
                    CaptureRequest.Builder builder = mCamera.createReprocessCaptureRequest(result);
                    builder.addTarget(getReprocessOutputImageReader().getSurface());
                    reprocessRequests.add(builder.build());
                }

                SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();

                // Submit reprocess capture requests.
                if (submitInBurst) {
                    mSession.captureBurst(reprocessRequests, captureCallback, mHandler);
                } else {
                    for (CaptureRequest request : reprocessRequests) {
                        mSession.capture(request, captureCallback, mHandler);
                    }
                }

                // Abort after getting the first result
                TotalCaptureResult reprocessResult =
                        captureCallback.getTotalCaptureResultForRequest(reprocessRequests.get(0),
                        CAPTURE_TIMEOUT_FRAMES);
                mSession.abortCaptures();

                // Wait until the session is ready again.
                mSessionListener.getStateWaiter().waitForState(
                        BlockingSessionCallback.SESSION_READY, SESSION_CLOSE_TIMEOUT_MS);

                // Gather all failed requests.
                ArrayList<CaptureFailure> failures =
                        captureCallback.getCaptureFailures(NUM_REPROCESS_CAPTURES - 1);
                ArrayList<CaptureRequest> failedRequests = new ArrayList<>();
                for (CaptureFailure failure : failures) {
                    failedRequests.add(failure.getRequest());
                }

                // For each request that didn't fail must have a valid result.
                for (int i = 1; i < reprocessRequests.size(); i++) {
                    CaptureRequest request = reprocessRequests.get(i);
                    if (!failedRequests.contains(request)) {
                        captureCallback.getTotalCaptureResultForRequest(request,
                                CAPTURE_TIMEOUT_FRAMES);
                    }
                }

                // Drain the image reader listeners.
                mFirstImageReaderListener.drain();
                if (!mShareOneImageReader) {
                    mSecondImageReaderListener.drain();
                }

                // Make sure all input surfaces are released.
                for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
                    mImageWriterListener.waitForImageReleased(CAPTURE_TIMEOUT_MS);
                }
            }
        } finally {
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Test timestamps for reprocess requests. Reprocess request's shutter timestamp, result's
     * sensor timestamp, and output image's timestamp should match the reprocess input's timestamp.
     */
    private void testReprocessTimestamps(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessTimestamps: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat);
        }

        try {
            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                    NUM_REPROCESS_CAPTURES);
            setupReprocessableSession(/*previewSurface*/null, NUM_REPROCESS_CAPTURES);

            // Prepare reprocess capture requests.
            ArrayList<CaptureRequest> reprocessRequests = new ArrayList<>(NUM_REPROCESS_CAPTURES);
            ArrayList<Long> expectedTimestamps = new ArrayList<>(NUM_REPROCESS_CAPTURES);

            for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
                TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                        /*inputResult*/null);

                mImageWriter.queueInputImage(
                        mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));
                CaptureRequest.Builder builder = mCamera.createReprocessCaptureRequest(result);
                builder.addTarget(getReprocessOutputImageReader().getSurface());
                reprocessRequests.add(builder.build());
                // Reprocess result's timestamp should match input image's timestamp.
                expectedTimestamps.add(result.get(CaptureResult.SENSOR_TIMESTAMP));
            }

            // Submit reprocess requests.
            SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();
            mSession.captureBurst(reprocessRequests, captureCallback, mHandler);

            // Verify we get the expected timestamps.
            for (int i = 0; i < reprocessRequests.size(); i++) {
                captureCallback.waitForCaptureStart(reprocessRequests.get(i),
                        expectedTimestamps.get(i), CAPTURE_TIMEOUT_FRAMES);
            }

            TotalCaptureResult[] reprocessResults =
                    captureCallback.getTotalCaptureResultsForRequests(reprocessRequests,
                    CAPTURE_TIMEOUT_FRAMES);

            for (int i = 0; i < expectedTimestamps.size(); i++) {
                // Verify the result timestamps match the input image's timestamps.
                long expected = expectedTimestamps.get(i);
                long timestamp = reprocessResults[i].get(CaptureResult.SENSOR_TIMESTAMP);
                assertEquals("Reprocess result timestamp (" + timestamp + ") doesn't match input " +
                        "image's timestamp (" + expected + ")", expected, timestamp);

                // Verify the reprocess output image timestamps match the input image's timestamps.
                Image image = getReprocessOutputImageReaderListener().getImage(CAPTURE_TIMEOUT_MS);
                timestamp = image.getTimestamp();
                image.close();

                assertEquals("Reprocess output timestamp (" + timestamp + ") doesn't match input " +
                        "image's timestamp (" + expected + ")", expected, timestamp);
            }

            // Make sure all input surfaces are released.
            for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
                mImageWriterListener.waitForImageReleased(CAPTURE_TIMEOUT_MS);
            }
        } finally {
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Test JPEG tags for reprocess requests. Reprocess result's JPEG tags and JPEG image's tags
     * match reprocess request's JPEG tags.
     */
    private void testReprocessJpegExif(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessJpegExif: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize);
        }

        Size[] thumbnailSizes = mStaticInfo.getAvailableThumbnailSizesChecked();
        Size[] testThumbnailSizes = new Size[EXIF_TEST_DATA.length];
        Arrays.fill(testThumbnailSizes, thumbnailSizes[thumbnailSizes.length - 1]);
        // Make sure thumbnail size (0, 0) is covered.
        testThumbnailSizes[0] = new Size(0, 0);

        try {
            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, ImageFormat.JPEG,
                    EXIF_TEST_DATA.length);
            setupReprocessableSession(/*previewSurface*/null, EXIF_TEST_DATA.length);

            // Prepare reprocess capture requests.
            ArrayList<CaptureRequest> reprocessRequests = new ArrayList<>(EXIF_TEST_DATA.length);

            for (int i = 0; i < EXIF_TEST_DATA.length; i++) {
                TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                        /*inputResult*/null);
                mImageWriter.queueInputImage(
                        mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));

                CaptureRequest.Builder builder = mCamera.createReprocessCaptureRequest(result);
                builder.addTarget(getReprocessOutputImageReader().getSurface());

                // set jpeg keys
                setJpegKeys(builder, EXIF_TEST_DATA[i], testThumbnailSizes[i], mCollector);
                reprocessRequests.add(builder.build());
            }

            // Submit reprocess requests.
            SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();
            mSession.captureBurst(reprocessRequests, captureCallback, mHandler);

            TotalCaptureResult[] reprocessResults =
                    captureCallback.getTotalCaptureResultsForRequests(reprocessRequests,
                    CAPTURE_TIMEOUT_FRAMES);

            for (int i = 0; i < EXIF_TEST_DATA.length; i++) {
                // Verify output image's and result's JPEG EXIF data.
                Image image = getReprocessOutputImageReaderListener().getImage(CAPTURE_TIMEOUT_MS);
                verifyJpegKeys(image, reprocessResults[i], reprocessOutputSize,
                        testThumbnailSizes[i], EXIF_TEST_DATA[i], mStaticInfo, mCollector);
                image.close();

            }
        } finally {
            closeReprossibleSession();
            closeImageReaders();
        }
    }



    /**
     * Test the following keys in reprocess results match the keys in reprocess requests:
     *   1. EDGE_MODE
     *   2. NOISE_REDUCTION_MODE
     *   3. REPROCESS_EFFECTIVE_EXPOSURE_FACTOR (only for YUV reprocess)
     */
    private void testReprocessRequestKeys(String cameraId, Size inputSize, int inputFormat,
            Size reprocessOutputSize, int reprocessOutputFormat) throws Exception {
        if (VERBOSE) {
            Log.v(TAG, "testReprocessRequestKeys: cameraId: " + cameraId + " inputSize: " +
                    inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
                    reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat);
        }

        final Integer[] EDGE_MODES = {CaptureRequest.EDGE_MODE_FAST,
                CaptureRequest.EDGE_MODE_HIGH_QUALITY, CaptureRequest.EDGE_MODE_OFF,
                CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG};
        final Integer[] NR_MODES = {CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY,
                CaptureRequest.NOISE_REDUCTION_MODE_OFF,
                CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG,
                CaptureRequest.NOISE_REDUCTION_MODE_FAST};
        final Float[] EFFECTIVE_EXP_FACTORS = {null, 1.0f, 2.5f, 4.0f};
        int numFrames = EDGE_MODES.length;

        try {
            setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                    numFrames);
            setupReprocessableSession(/*previewSurface*/null, numFrames);

            // Prepare reprocess capture requests.
            ArrayList<CaptureRequest> reprocessRequests = new ArrayList<>(numFrames);

            for (int i = 0; i < numFrames; i++) {
                TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                        /*inputResult*/null);
                mImageWriter.queueInputImage(
                        mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));

                CaptureRequest.Builder builder = mCamera.createReprocessCaptureRequest(result);
                builder.addTarget(getReprocessOutputImageReader().getSurface());

                // Set reprocess request keys
                builder.set(CaptureRequest.EDGE_MODE, EDGE_MODES[i]);
                builder.set(CaptureRequest.NOISE_REDUCTION_MODE, NR_MODES[i]);
                if (inputFormat == ImageFormat.YUV_420_888) {
                    builder.set(CaptureRequest.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR,
                            EFFECTIVE_EXP_FACTORS[i]);
                }
                reprocessRequests.add(builder.build());
            }

            // Submit reprocess requests.
            SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();
            mSession.captureBurst(reprocessRequests, captureCallback, mHandler);

            TotalCaptureResult[] reprocessResults =
                    captureCallback.getTotalCaptureResultsForRequests(reprocessRequests,
                    CAPTURE_TIMEOUT_FRAMES);

            for (int i = 0; i < numFrames; i++) {
                // Verify result's keys
                Integer resultEdgeMode = reprocessResults[i].get(CaptureResult.EDGE_MODE);
                Integer resultNoiseReductionMode =
                        reprocessResults[i].get(CaptureResult.NOISE_REDUCTION_MODE);

                assertEquals("Reprocess result edge mode (" + resultEdgeMode +
                        ") doesn't match requested edge mode (" + EDGE_MODES[i] + ")",
                        resultEdgeMode, EDGE_MODES[i]);
                assertEquals("Reprocess result noise reduction mode (" + resultNoiseReductionMode +
                        ") doesn't match requested noise reduction mode (" +
                        NR_MODES[i] + ")", resultNoiseReductionMode,
                        NR_MODES[i]);

                if (inputFormat == ImageFormat.YUV_420_888) {
                    Float resultEffectiveExposureFactor = reprocessResults[i].get(
                            CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
                    assertEquals("Reprocess effective exposure factor (" +
                            resultEffectiveExposureFactor + ") doesn't match requested " +
                            "effective exposure factor (" + EFFECTIVE_EXP_FACTORS[i] + ")",
                            resultEffectiveExposureFactor, EFFECTIVE_EXP_FACTORS[i]);
                }
            }
        } finally {
            closeReprossibleSession();
            closeImageReaders();
        }
    }

    /**
     * Set up two image readers: one for regular capture (used for reprocess input) and one for
     * reprocess capture.
     */
    private void setupImageReaders(Size inputSize, int inputFormat, Size reprocessOutputSize,
            int reprocessOutputFormat, int maxImages) {

        mShareOneImageReader = false;
        // If the regular output and reprocess output have the same size and format,
        // they can share one image reader.
        if (inputFormat == reprocessOutputFormat &&
                inputSize.equals(reprocessOutputSize)) {
            maxImages *= 2;
            mShareOneImageReader = true;
        }
        // create an ImageReader for the regular capture
        mFirstImageReaderListener = new SimpleImageReaderListener();
        mFirstImageReader = makeImageReader(inputSize, inputFormat, maxImages,
                mFirstImageReaderListener, mHandler);

        if (!mShareOneImageReader) {
            // create an ImageReader for the reprocess capture
            mSecondImageReaderListener = new SimpleImageReaderListener();
            mSecondImageReader = makeImageReader(reprocessOutputSize, reprocessOutputFormat,
                    maxImages, mSecondImageReaderListener, mHandler);
        }
    }

    /**
     * Close two image readers.
     */
    private void closeImageReaders() {
        CameraTestUtils.closeImageReader(mFirstImageReader);
        mFirstImageReader = null;
        CameraTestUtils.closeImageReader(mSecondImageReader);
        mSecondImageReader = null;
    }

    /**
     * Get the ImageReader for reprocess output.
     */
    private ImageReader getReprocessOutputImageReader() {
        if (mShareOneImageReader) {
            return mFirstImageReader;
        } else {
            return mSecondImageReader;
        }
    }

    private SimpleImageReaderListener getReprocessOutputImageReaderListener() {
        if (mShareOneImageReader) {
            return mFirstImageReaderListener;
        } else {
            return mSecondImageReaderListener;
        }
    }

    /**
     * Set up a reprocessable session and create an ImageWriter with the sessoin's input surface.
     */
    private void setupReprocessableSession(Surface previewSurface, int numImageWriterImages)
            throws Exception {
        // create a reprocessable capture session
        List<Surface> outSurfaces = new ArrayList<Surface>();
        outSurfaces.add(mFirstImageReader.getSurface());
        if (!mShareOneImageReader) {
            outSurfaces.add(mSecondImageReader.getSurface());
        }
        if (previewSurface != null) {
            outSurfaces.add(previewSurface);
        }

        InputConfiguration inputConfig = new InputConfiguration(mFirstImageReader.getWidth(),
                mFirstImageReader.getHeight(), mFirstImageReader.getImageFormat());
        String inputConfigString = inputConfig.toString();
        if (VERBOSE) {
            Log.v(TAG, "InputConfiguration: " + inputConfigString);
        }
        assertTrue(String.format("inputConfig is wrong: %dx%d format %d. Expect %dx%d format %d",
                inputConfig.getWidth(), inputConfig.getHeight(), inputConfig.getFormat(),
                mFirstImageReader.getWidth(), mFirstImageReader.getHeight(),
                mFirstImageReader.getImageFormat()),
                inputConfig.getWidth() == mFirstImageReader.getWidth() &&
                inputConfig.getHeight() == mFirstImageReader.getHeight() &&
                inputConfig.getFormat() == mFirstImageReader.getImageFormat());

        mSessionListener = new BlockingSessionCallback();
        mSession = configureReprocessableCameraSession(mCamera, inputConfig, outSurfaces,
                mSessionListener, mHandler);

        // create an ImageWriter
        mInputSurface = mSession.getInputSurface();
        mImageWriter = ImageWriter.newInstance(mInputSurface,
                numImageWriterImages);

        mImageWriterListener = new SimpleImageWriterListener(mImageWriter);
        mImageWriter.setOnImageReleasedListener(mImageWriterListener, mHandler);
    }

    /**
     * Close the reprocessable session and ImageWriter.
     */
    private void closeReprossibleSession() {
        mInputSurface = null;

        if (mSession != null) {
            mSession.close();
            mSession = null;
        }

        if (mImageWriter != null) {
            mImageWriter.close();
            mImageWriter = null;
        }
    }

    /**
     * Do one reprocess capture.
     */
    private ImageResultHolder doReprocessCapture() throws Exception {
        return doReprocessBurstCapture(/*numBurst*/1)[0];
    }

    /**
     * Do a burst of reprocess captures.
     */
    private ImageResultHolder[] doReprocessBurstCapture(int numBurst) throws Exception {
        boolean[] isReprocessCaptures = new boolean[numBurst];
        for (int i = 0; i < numBurst; i++) {
            isReprocessCaptures[i] = true;
        }

        return doMixedReprocessBurstCapture(isReprocessCaptures);
    }

    /**
     * Do a burst of captures that are mixed with regular and reprocess captures.
     *
     * @param isReprocessCaptures An array whose elements indicate whether it's a reprocess capture
     *                            request. If the element is true, it represents a reprocess capture
     *                            request. If the element is false, it represents a regular capture
     *                            request. The size of the array is the number of capture requests
     *                            in the burst.
     */
    private ImageResultHolder[] doMixedReprocessBurstCapture(boolean[] isReprocessCaptures)
            throws Exception {
        if (isReprocessCaptures == null || isReprocessCaptures.length <= 0) {
            throw new IllegalArgumentException("isReprocessCaptures must have at least 1 capture.");
        }

        boolean hasReprocessRequest = false;
        boolean hasRegularRequest = false;

        TotalCaptureResult[] results = new TotalCaptureResult[isReprocessCaptures.length];
        for (int i = 0; i < isReprocessCaptures.length; i++) {
            // submit a capture and get the result if this entry is a reprocess capture.
            if (isReprocessCaptures[i]) {
                results[i] = submitCaptureRequest(mFirstImageReader.getSurface(),
                        /*inputResult*/null);
                mImageWriter.queueInputImage(
                        mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));
                hasReprocessRequest = true;
            } else {
                hasRegularRequest = true;
            }
        }

        Surface[] outputSurfaces = new Surface[isReprocessCaptures.length];
        for (int i = 0; i < isReprocessCaptures.length; i++) {
            outputSurfaces[i] = getReprocessOutputImageReader().getSurface();
        }

        TotalCaptureResult[] finalResults = submitMixedCaptureBurstRequest(outputSurfaces, results);

        ImageResultHolder[] holders = new ImageResultHolder[isReprocessCaptures.length];
        for (int i = 0; i < isReprocessCaptures.length; i++) {
            Image image = getReprocessOutputImageReaderListener().getImage(CAPTURE_TIMEOUT_MS);
            if (hasReprocessRequest && hasRegularRequest) {
                // If there are mixed requests, images and results may not be in the same order.
                for (int j = 0; j < finalResults.length; j++) {
                    if (finalResults[j] != null &&
                            finalResults[j].get(CaptureResult.SENSOR_TIMESTAMP) ==
                            image.getTimestamp()) {
                        holders[i] = new ImageResultHolder(image, finalResults[j]);
                        finalResults[j] = null;
                        break;
                    }
                }

                assertNotNull("Cannot find a result matching output image's timestamp: " +
                        image.getTimestamp(), holders[i]);
            } else {
                // If no mixed requests, images and results should be in the same order.
                holders[i] = new ImageResultHolder(image, finalResults[i]);
            }
        }

        return holders;
    }

    /**
     * Start preview without a listener.
     */
    private void startPreview(Surface previewSurface) throws Exception {
        CaptureRequest.Builder builder = mCamera.createCaptureRequest(ZSL_TEMPLATE);
        builder.addTarget(previewSurface);
        mSession.setRepeatingRequest(builder.build(), null, mHandler);
    }

    /**
     * Issue a capture request and return the result. If inputResult is null, it's a regular
     * request. Otherwise, it's a reprocess request.
     */
    private TotalCaptureResult submitCaptureRequest(Surface output,
            TotalCaptureResult inputResult) throws Exception {
        Surface[] outputs = new Surface[1];
        outputs[0] = output;
        TotalCaptureResult[] inputResults = new TotalCaptureResult[1];
        inputResults[0] = inputResult;

        return submitMixedCaptureBurstRequest(outputs, inputResults)[0];
    }

    /**
     * Submit a burst request mixed with regular and reprocess requests.
     *
     * @param outputs An array of output surfaces. One output surface will be used in one request
     *                so the length of the array is the number of requests in a burst request.
     * @param inputResults An array of input results. If it's null, all requests are regular
     *                     requests. If an element is null, that element represents a regular
     *                     request. If an element if not null, that element represents a reprocess
     *                     request.
     *
     */
    private TotalCaptureResult[] submitMixedCaptureBurstRequest(Surface[] outputs,
            TotalCaptureResult[] inputResults) throws Exception {
        if (outputs == null || outputs.length <= 0) {
            throw new IllegalArgumentException("outputs must have at least 1 surface");
        } else if (inputResults != null && inputResults.length != outputs.length) {
            throw new IllegalArgumentException("The lengths of outputs and inputResults " +
                    "don't match");
        }

        int numReprocessCaptures = 0;
        SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();
        ArrayList<CaptureRequest> captureRequests = new ArrayList<>(outputs.length);

        // Prepare a list of capture requests. Whether it's a regular or reprocess capture request
        // is based on inputResults array.
        for (int i = 0; i < outputs.length; i++) {
            CaptureRequest.Builder builder;
            boolean isReprocess = (inputResults != null && inputResults[i] != null);
            if (isReprocess) {
                builder = mCamera.createReprocessCaptureRequest(inputResults[i]);
                numReprocessCaptures++;
            } else {
                builder = mCamera.createCaptureRequest(CAPTURE_TEMPLATE);
            }
            builder.addTarget(outputs[i]);
            CaptureRequest request = builder.build();
            assertTrue("Capture request reprocess type " + request.isReprocess() + " is wrong.",
                request.isReprocess() == isReprocess);

            captureRequests.add(request);
        }

        if (captureRequests.size() == 1) {
            mSession.capture(captureRequests.get(0), captureCallback, mHandler);
        } else {
            mSession.captureBurst(captureRequests, captureCallback, mHandler);
        }

        TotalCaptureResult[] results;
        if (numReprocessCaptures == 0 || numReprocessCaptures == outputs.length) {
            results = new TotalCaptureResult[outputs.length];
            // If the requests are not mixed, they should come in order.
            for (int i = 0; i < results.length; i++){
                results[i] = captureCallback.getTotalCaptureResultForRequest(
                        captureRequests.get(i), CAPTURE_TIMEOUT_FRAMES);
            }
        } else {
            // If the requests are mixed, they may not come in order.
            results = captureCallback.getTotalCaptureResultsForRequests(
                    captureRequests, CAPTURE_TIMEOUT_FRAMES * captureRequests.size());
        }

        // make sure all input surfaces are released.
        for (int i = 0; i < numReprocessCaptures; i++) {
            mImageWriterListener.waitForImageReleased(CAPTURE_TIMEOUT_MS);
        }

        return results;
    }

    private Size getMaxSize(int format, StaticMetadata.StreamDirection direction) {
        Size[] sizes = mStaticInfo.getAvailableSizesForFormatChecked(format, direction);
        return getAscendingOrderSizes(Arrays.asList(sizes), /*ascending*/false).get(0);
    }

    private boolean isYuvReprocessSupported(String cameraId) throws Exception {
        return isReprocessSupported(cameraId, ImageFormat.YUV_420_888);
    }

    private boolean isOpaqueReprocessSupported(String cameraId) throws Exception {
        return isReprocessSupported(cameraId, ImageFormat.PRIVATE);
    }

    private void dumpImage(Image image, String name) {
        String filename = DEBUG_FILE_NAME_BASE + name;
        switch(image.getFormat()) {
            case ImageFormat.JPEG:
                filename += ".jpg";
                break;
            case ImageFormat.NV16:
            case ImageFormat.NV21:
            case ImageFormat.YUV_420_888:
                filename += ".yuv";
                break;
            default:
                filename += "." + image.getFormat();
                break;
        }

        Log.d(TAG, "dumping an image to " + filename);
        dumpFile(filename , getDataFromImage(image));
    }

    /**
     * A class that holds an Image and a TotalCaptureResult.
     */
    private static class ImageResultHolder {
        private final Image mImage;
        private final TotalCaptureResult mResult;

        public ImageResultHolder(Image image, TotalCaptureResult result) {
            mImage = image;
            mResult = result;
        }

        public Image getImage() {
            return mImage;
        }

        public TotalCaptureResult getTotalCaptureResult() {
            return mResult;
        }
    }
}
