/*
 * 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.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>
 */
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 {

        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) {
                        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;
        }
    }
}
