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

package android.hardware.camera2.cts;

import static android.hardware.camera2.cts.CameraTestUtils.*;
import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
import static org.mockito.Mockito.*;
import static android.hardware.camera2.CaptureRequest.*;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraMetadata;
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.Camera2AndroidTestCase;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
import android.view.Surface;

import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.blocking.BlockingStateCallback;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
import com.android.ex.camera2.utils.StateWaiter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import android.util.Size;

import org.mockito.ArgumentMatcher;

import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * <p>Basic test for CameraDevice APIs.</p>
 */
@AppModeFull
public class CameraDeviceTest extends Camera2AndroidTestCase {
    private static final String TAG = "CameraDeviceTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final int ERROR_LISTENER_WAIT_TIMEOUT_MS = 1000;
    private static final int REPEATING_CAPTURE_EXPECTED_RESULT_COUNT = 5;
    private static final int MAX_NUM_IMAGES = 5;
    private static final int MIN_FPS_REQUIRED_FOR_STREAMING = 20;
    private static final int DEFAULT_POST_RAW_SENSITIVITY_BOOST = 100;

    private CameraCaptureSession mSession;

    private BlockingStateCallback mCameraMockListener;
    private int mLatestDeviceState = STATE_UNINITIALIZED;
    private BlockingSessionCallback mSessionMockListener;
    private StateWaiter mSessionWaiter;
    private int mLatestSessionState = -1; // uninitialized

    private static int[] sTemplates = new int[] {
            CameraDevice.TEMPLATE_PREVIEW,
            CameraDevice.TEMPLATE_RECORD,
            CameraDevice.TEMPLATE_STILL_CAPTURE,
            CameraDevice.TEMPLATE_VIDEO_SNAPSHOT,
    };

    private static int[] sInvalidTemplates = new int[] {
            CameraDevice.TEMPLATE_PREVIEW - 1,
            CameraDevice.TEMPLATE_MANUAL + 1,
    };

    // Request templates that are unsupported by LEGACY mode.
    private static Set<Integer> sLegacySkipTemplates = new HashSet<>();
    static {
        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_MANUAL);
    }

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

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

        /**
         * Create error listener in context scope, to catch asynchronous device error.
         * Use spy object here since we want to use the SimpleDeviceListener callback
         * implementation (spy doesn't stub the functions unless we ask it to do so).
         */
        mCameraMockListener = spy(new BlockingStateCallback());
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        /**
         * Due to the asynchronous nature of camera device error callback, we
         * have to make sure device doesn't run into error state before. If so,
         * fail the rest of the tests. This is especially needed when error
         * callback is fired too late.
         */
        verify(mCameraMockListener, never())
                .onError(
                    any(CameraDevice.class),
                    anyInt());
        verify(mCameraMockListener, never())
                .onDisconnected(
                    any(CameraDevice.class));

        mCameraListener = mCameraMockListener;
    }

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

    /**
     * <p>
     * Test camera capture request preview capture template.
     * </p>
     *
     * <p>
     * The request template returned by the camera device must include a
     * necessary set of metadata keys, and their values must be set correctly.
     * It mainly requires below settings:
     * </p>
     * <ul>
     * <li>All 3A settings are auto.</li>
     * <li>All sensor settings are not null.</li>
     * <li>All ISP processing settings should be non-manual, and the camera
     * device should make sure the stable frame rate is guaranteed for the given
     * settings.</li>
     * </ul>
     */
    public void testCameraDevicePreviewTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_PREVIEW);
        }

        // TODO: test the frame rate sustainability in preview use case test.
    }

    /**
     * <p>
     * Test camera capture request still capture template.
     * </p>
     *
     * <p>
     * The request template returned by the camera device must include a
     * necessary set of metadata keys, and their values must be set correctly.
     * It mainly requires below settings:
     * </p>
     * <ul>
     * <li>All 3A settings are auto.</li>
     * <li>All sensor settings are not null.</li>
     * <li>All ISP processing settings should be non-manual, and the camera
     * device should make sure the high quality takes priority to the stable
     * frame rate for the given settings.</li>
     * </ul>
     */
    public void testCameraDeviceStillTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_STILL_CAPTURE);
        }
    }

    /**
     * <p>
     * Test camera capture video recording template.
     * </p>
     *
     * <p>
     * The request template returned by the camera device must include a
     * necessary set of metadata keys, and their values must be set correctly.
     * It has the similar requirement as preview, with one difference:
     * </p>
     * <ul>
     * <li>Frame rate should be stable, for example, wide fps range like [7, 30]
     * is a bad setting.</li>
     */
    public void testCameraDeviceRecordingTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_RECORD);
        }

        // TODO: test the frame rate sustainability in recording use case test.
    }

    /**
     *<p>Test camera capture video snapshot template.</p>
     *
     * <p>The request template returned by the camera device must include a necessary set of
     * metadata keys, and their values must be set correctly. It has the similar requirement
     * as recording, with an additional requirement: the settings should maximize image quality
     * without compromising stable frame rate.</p>
     */
    public void testCameraDeviceVideoSnapShotTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
        }

        // TODO: test the frame rate sustainability in video snapshot use case test.
    }

    /**
     *<p>Test camera capture request zero shutter lag template.</p>
     *
     * <p>The request template returned by the camera device must include a necessary set of
     * metadata keys, and their values must be set correctly. It has the similar requirement
     * as preview, with an additional requirement: </p>
     */
    public void testCameraDeviceZSLTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
        }
    }

    /**
     * <p>
     * Test camera capture request manual template.
     * </p>
     *
     * <p>
     * The request template returned by the camera device must include a
     * necessary set of metadata keys, and their values must be set correctly. It
     * mainly requires below settings:
     * </p>
     * <ul>
     * <li>All 3A settings are manual.</li>
     * <li>ISP processing parameters are set to preview quality.</li>
     * <li>The manual capture parameters (exposure, sensitivity, and so on) are
     * set to reasonable defaults.</li>
     * </ul>
     */
    public void testCameraDeviceManualTemplate() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_MANUAL);
        }
    }

    public void testCameraDeviceCreateCaptureBuilder() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                /**
                 * Test: that each template type is supported, and that its required fields are
                 * present.
                 */
                for (int j = 0; j < sTemplates.length; j++) {
                    // Skip video snapshots for LEGACY mode
                    if (mStaticInfo.isHardwareLevelLegacy() &&
                            sTemplates[j] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
                        continue;
                    }
                    // Skip non-PREVIEW templates for non-color output
                    if (!mStaticInfo.isColorOutputSupported() &&
                            sTemplates[j] != CameraDevice.TEMPLATE_PREVIEW) {
                        continue;
                    }
                    CaptureRequest.Builder capReq = mCamera.createCaptureRequest(sTemplates[j]);
                    assertNotNull("Failed to create capture request", capReq);
                    if (mStaticInfo.areKeysAvailable(CaptureRequest.SENSOR_EXPOSURE_TIME)) {
                        assertNotNull("Missing field: SENSOR_EXPOSURE_TIME",
                                capReq.get(CaptureRequest.SENSOR_EXPOSURE_TIME));
                    }
                    if (mStaticInfo.areKeysAvailable(CaptureRequest.SENSOR_SENSITIVITY)) {
                        assertNotNull("Missing field: SENSOR_SENSITIVITY",
                                capReq.get(CaptureRequest.SENSOR_SENSITIVITY));
                    }
                }

                /**
                 * Test: creating capture requests with an invalid template ID should throw
                 * IllegalArgumentException.
                 */
                for (int j = 0; j < sInvalidTemplates.length; j++) {
                    try {
                        CaptureRequest.Builder capReq =
                                mCamera.createCaptureRequest(sInvalidTemplates[j]);
                        fail("Should get IllegalArgumentException due to an invalid template ID.");
                    } catch (IllegalArgumentException e) {
                        // Expected exception.
                    }
                }
            }
            finally {
                try {
                    closeSession();
                } finally {
                    closeDevice(mCameraIds[i], mCameraMockListener);
                }
            }
        }
    }

    public void testCameraDeviceSetErrorListener() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                /**
                 * Test: that the error listener can be set without problems.
                 * Also, wait some time to check if device doesn't run into error.
                 */
                SystemClock.sleep(ERROR_LISTENER_WAIT_TIMEOUT_MS);
                verify(mCameraMockListener, never())
                        .onError(
                                any(CameraDevice.class),
                                anyInt());
            }
            finally {
                try {
                    closeSession();
                } finally {
                    closeDevice(mCameraIds[i], mCameraMockListener);
                }
            }
        }
    }

    public void testCameraDeviceCapture() throws Exception {
        runCaptureTest(/*burst*/false, /*repeating*/false, /*abort*/false, /*useExecutor*/false);
        runCaptureTest(/*burst*/false, /*repeating*/false, /*abort*/false, /*useExecutor*/true);
    }

    public void testCameraDeviceCaptureBurst() throws Exception {
        runCaptureTest(/*burst*/true, /*repeating*/false, /*abort*/false, /*useExecutor*/false);
        runCaptureTest(/*burst*/true, /*repeating*/false, /*abort*/false, /*useExecutor*/true);
    }

    public void testCameraDeviceRepeatingRequest() throws Exception {
        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/false, /*useExecutor*/false);
        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/false, /*useExecutor*/true);
    }

    public void testCameraDeviceRepeatingBurst() throws Exception {
        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/false, /*useExecutor*/ false);
        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/false, /*useExecutor*/ true);
    }

    /**
     * Test {@link android.hardware.camera2.CameraCaptureSession#abortCaptures} API.
     *
     * <p>Abort is the fastest way to idle the camera device for reconfiguration with
     * {@link android.hardware.camera2.CameraCaptureSession#abortCaptures}, at the cost of
     * discarding in-progress work. Once the abort is complete, the idle callback will be called.
     * </p>
     */
    public void testCameraDeviceAbort() throws Exception {
        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/true, /*useExecutor*/false);
        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/true, /*useExecutor*/true);
        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/true, /*useExecutor*/false);
        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/true, /*useExecutor*/true);
        /**
         * TODO: this is only basic test of abort. we probably should also test below cases:
         *
         * 1. Performance. Make sure abort is faster than stopRepeating, we can test each one a
         * couple of times, then compare the average. Also, for abortCaptures() alone, we should
         * make sure it doesn't take too long time (e.g. <100ms for full devices, <500ms for limited
         * devices), after the abort, we should be able to get all results back very quickly.  This
         * can be done in performance test.
         *
         * 2. Make sure all in-flight request comes back after abort, e.g. submit a couple of
         * long exposure single captures, then abort, then check if we can get the pending
         * request back quickly.
         *
         * 3. Also need check onCaptureSequenceCompleted for repeating burst after abortCaptures().
         */
    }

    /**
     * Test invalid capture (e.g. null or empty capture request).
     */
    public void testInvalidCapture() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);

                prepareCapture();

                invalidRequestCaptureTestByCamera();

                closeSession();
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Test to ensure that we can call camera2 API methods inside callbacks.
     *
     * Tests:
     *  onOpened -> createCaptureSession, createCaptureRequest
     *  onConfigured -> getDevice, abortCaptures,
     *     createCaptureRequest, capture, setRepeatingRequest, stopRepeating
     *  onCaptureCompleted -> createCaptureRequest, getDevice, abortCaptures,
     *     capture, setRepeatingRequest, stopRepeating, session+device.close
     */
    public void testChainedOperation() throws Throwable {

        final ArrayList<Surface> outputs = new ArrayList<>();

        // A queue for the chained listeners to push results to
        // A success Throwable indicates no errors; other Throwables detail a test failure;
        // nulls indicate timeouts.
        final Throwable success = new Throwable("Success");
        final LinkedBlockingQueue<Throwable> results = new LinkedBlockingQueue<>();

        // Define listeners
        // A cascade of Device->Session->Capture listeners, each of which invokes at least one
        // method on the camera device or session.

        class ChainedCaptureCallback extends CameraCaptureSession.CaptureCallback {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                    TotalCaptureResult result) {
                try {
                    CaptureRequest.Builder request2 =
                            session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    request2.addTarget(mReaderSurface);

                    // Some calls to the camera for coverage
                    session.abortCaptures();
                    session.capture(request2.build(),
                            /*listener*/ null, /*handler*/ null);
                    session.setRepeatingRequest(request2.build(),
                            /*listener*/ null, /*handler*/ null);
                    session.stopRepeating();

                    CameraDevice camera = session.getDevice();
                    session.close();
                    camera.close();

                    results.offer(success);
                } catch (Throwable t) {
                    results.offer(t);
                }
            }

            @Override
            public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
                    CaptureFailure failure) {
                try {
                    CameraDevice camera = session.getDevice();
                    session.close();
                    camera.close();
                    fail("onCaptureFailed invoked with failure reason: " + failure.getReason());
                } catch (Throwable t) {
                    results.offer(t);
                }
            }
        }

        class ChainedSessionListener extends CameraCaptureSession.StateCallback {
            private final ChainedCaptureCallback mCaptureCallback = new ChainedCaptureCallback();

            @Override
            public void onConfigured(CameraCaptureSession session) {
                try {
                    CaptureRequest.Builder request =
                            session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    request.addTarget(mReaderSurface);
                    // Some calls to the camera for coverage
                    session.getDevice();
                    session.abortCaptures();
                    // The important call for the next level of chaining
                    session.capture(request.build(), mCaptureCallback, mHandler);
                    // Some more calls
                    session.setRepeatingRequest(request.build(),
                            /*listener*/ null, /*handler*/ null);
                    session.stopRepeating();
                    results.offer(success);
                } catch (Throwable t) {
                    results.offer(t);
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
                try {
                    CameraDevice camera = session.getDevice();
                    session.close();
                    camera.close();
                    fail("onConfigureFailed was invoked");
                } catch (Throwable t) {
                    results.offer(t);
                }
            }
        }

        class ChainedCameraListener extends CameraDevice.StateCallback {
            private final ChainedSessionListener mSessionListener = new ChainedSessionListener();

            public CameraDevice cameraDevice;

            @Override
            public void onOpened(CameraDevice camera) {

                cameraDevice = camera;
                try {
                    // Some calls for coverage
                    camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    // The important call for next level of chaining
                    camera.createCaptureSession(outputs, mSessionListener, mHandler);
                    results.offer(success);
                } catch (Throwable t) {
                    try {
                        camera.close();
                        results.offer(t);
                    } catch (Throwable t2) {
                        Log.e(TAG,
                                "Second failure reached; discarding first exception with trace " +
                                Log.getStackTraceString(t));
                        results.offer(t2);
                    }
                }
            }

            @Override
            public void onDisconnected(CameraDevice camera) {
                try {
                    camera.close();
                    fail("onDisconnected invoked");
                } catch (Throwable t) {
                    results.offer(t);
                }
            }

            @Override
            public void onError(CameraDevice camera, int error) {
                try {
                    camera.close();
                    fail("onError invoked with error code: " + error);
                } catch (Throwable t) {
                    results.offer(t);
                }
            }
        }

        // Actual test code

        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                Throwable result;

                if (!(new StaticMetadata(mCameraManager.getCameraCharacteristics(mCameraIds[i]))).
                        isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888,
                        MAX_NUM_IMAGES, new ImageDropperListener());
                outputs.add(mReaderSurface);

                // Start chained cascade
                ChainedCameraListener cameraListener = new ChainedCameraListener();
                mCameraManager.openCamera(mCameraIds[i], cameraListener, mHandler);

                // Check if open succeeded
                result = results.poll(CAMERA_OPEN_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                if (result != success) {
                    if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
                    if (result == null) {
                        fail("Timeout waiting for camera open");
                    } else {
                        throw result;
                    }
                }

                // Check if configure succeeded
                result = results.poll(SESSION_CONFIGURE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                if (result != success) {
                    if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
                    if (result == null) {
                        fail("Timeout waiting for session configure");
                    } else {
                        throw result;
                    }
                }

                // Check if capture succeeded
                result = results.poll(CAPTURE_RESULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                if (result != success) {
                    if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
                    if (result == null) {
                        fail("Timeout waiting for capture completion");
                    } else {
                        throw result;
                    }
                }

            } finally {
                closeDefaultImageReader();
                outputs.clear();
            }
        }
    }

    /**
     * Verify basic semantics and error conditions of the prepare call.
     *
     */
    public void testPrepare() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                prepareTestByCamera();
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Verify prepare call behaves properly when sharing surfaces.
     *
     */
    public void testPrepareForSharedSurfaces() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (mStaticInfo.isHardwareLevelLegacy()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] + " is legacy, skipping");
                    continue;
                }
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                prepareTestForSharedSurfacesByCamera();
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Verify creating sessions back to back.
     */
    public void testCreateSessions() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                testCreateSessionsByCamera(mCameraIds[i]);
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Verify creating a custom session
     */
    public void testCreateCustomSession() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                testCreateCustomSessionByCamera(mCameraIds[i]);
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Verify creating a custom mode session works
     */
    private void testCreateCustomSessionByCamera(String cameraId) throws Exception {
        final int SESSION_TIMEOUT_MS = 1000;
        final int CAPTURE_TIMEOUT_MS = 3000;

        if (VERBOSE) {
            Log.v(TAG, "Testing creating custom session for camera " + cameraId);
        }

        Size yuvSize = mOrderedPreviewSizes.get(0);

        // Create a list of image readers. JPEG for last one and YUV for the rest.
        ImageReader imageReader = ImageReader.newInstance(yuvSize.getWidth(), yuvSize.getHeight(),
                ImageFormat.YUV_420_888, /*maxImages*/1);

        try {
            // Create a normal-mode session via createCustomCaptureSession
            mSessionMockListener = spy(new BlockingSessionCallback());
            mSessionWaiter = mSessionMockListener.getStateWaiter();
            List<OutputConfiguration> outputs = new ArrayList<>();
            outputs.add(new OutputConfiguration(imageReader.getSurface()));
            mCamera.createCustomCaptureSession(/*inputConfig*/null, outputs,
                    CameraDevice.SESSION_OPERATION_MODE_NORMAL, mSessionMockListener, mHandler);
            mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

            // Verify we can capture a frame with the session.
            SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
            SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
            imageReader.setOnImageAvailableListener(imageListener, mHandler);

            CaptureRequest.Builder builder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            builder.addTarget(imageReader.getSurface());
            CaptureRequest request = builder.build();

            mSession.capture(request, captureListener, mHandler);
            captureListener.getCaptureResultForRequest(request, CAPTURE_TIMEOUT_MS);
            imageListener.getImage(CAPTURE_TIMEOUT_MS).close();

            // Create a few invalid custom sessions by using undefined non-vendor mode indices, and
            // check that they fail to configure
            mSessionMockListener = spy(new BlockingSessionCallback());
            mSessionWaiter = mSessionMockListener.getStateWaiter();
            mCamera.createCustomCaptureSession(/*inputConfig*/null, outputs,
                    CameraDevice.SESSION_OPERATION_MODE_VENDOR_START - 1, mSessionMockListener, mHandler);
            mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
            waitForSessionState(BlockingSessionCallback.SESSION_CONFIGURE_FAILED,
                    SESSION_CONFIGURE_TIMEOUT_MS);

            mSessionMockListener = spy(new BlockingSessionCallback());
            mCamera.createCustomCaptureSession(/*inputConfig*/null, outputs,
                    CameraDevice.SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED + 1, mSessionMockListener,
                    mHandler);
            mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
            mSessionWaiter = mSessionMockListener.getStateWaiter();
            waitForSessionState(BlockingSessionCallback.SESSION_CONFIGURE_FAILED,
                    SESSION_CONFIGURE_TIMEOUT_MS);

        } finally {
            imageReader.close();
            mSession.close();
        }
    }

    /**
     * Test session configuration.
     */
    public void testSessionConfiguration() throws Exception {
        ArrayList<OutputConfiguration> outConfigs = new ArrayList<OutputConfiguration> ();
        outConfigs.add(new OutputConfiguration(new Size(1, 1), SurfaceTexture.class));
        outConfigs.add(new OutputConfiguration(new Size(2, 2), SurfaceTexture.class));
        mSessionMockListener = spy(new BlockingSessionCallback());
        HandlerExecutor executor = new HandlerExecutor(mHandler);
        InputConfiguration inputConfig = new InputConfiguration(1, 1, ImageFormat.PRIVATE);

        SessionConfiguration regularSessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_REGULAR, outConfigs, executor, mSessionMockListener);

        SessionConfiguration highspeedSessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_HIGH_SPEED, outConfigs, executor, mSessionMockListener);

        assertEquals("Session configuration output doesn't match",
                regularSessionConfig.getOutputConfigurations(), outConfigs);

        assertEquals("Session configuration output doesn't match",
                regularSessionConfig.getOutputConfigurations(),
                highspeedSessionConfig.getOutputConfigurations());

        assertEquals("Session configuration callback doesn't match",
                regularSessionConfig.getStateCallback(), mSessionMockListener);

        assertEquals("Session configuration callback doesn't match",
                regularSessionConfig.getStateCallback(),
                highspeedSessionConfig.getStateCallback());

        assertEquals("Session configuration executor doesn't match",
                regularSessionConfig.getExecutor(), executor);

        assertEquals("Session configuration handler doesn't match",
                regularSessionConfig.getExecutor(), highspeedSessionConfig.getExecutor());

        regularSessionConfig.setInputConfiguration(inputConfig);
        assertEquals("Session configuration input doesn't match",
                regularSessionConfig.getInputConfiguration(), inputConfig);

        try {
            highspeedSessionConfig.setInputConfiguration(inputConfig);
            fail("No exception for valid input configuration in hight speed session configuration");
        } catch (UnsupportedOperationException e) {
            //expected
        }

        assertEquals("Session configuration input doesn't match",
                highspeedSessionConfig.getInputConfiguration(), null);

        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);

                CaptureRequest.Builder builder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                CaptureRequest request = builder.build();

                regularSessionConfig.setSessionParameters(request);
                highspeedSessionConfig.setSessionParameters(request);

                assertEquals("Session configuration parameters doesn't match",
                        regularSessionConfig.getSessionParameters(), request);

                assertEquals("Session configuration parameters doesn't match",
                        regularSessionConfig.getSessionParameters(),
                        highspeedSessionConfig.getSessionParameters());
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Check for any state leakage in case of internal re-configure
     */
    public void testSessionParametersStateLeak() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }
                testSessionParametersStateLeakByCamera(mCameraIds[i]);
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Check for any state leakage in case of internal re-configure
     */
    private void testSessionParametersStateLeakByCamera(String cameraId)
            throws Exception {
        int outputFormat = ImageFormat.YUV_420_888;
        Size outputSize = mOrderedPreviewSizes.get(0);

        CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap config = characteristics.get(
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        List <CaptureRequest.Key<?>> sessionKeys = characteristics.getAvailableSessionKeys();
        if (sessionKeys == null) {
            return;
        }

        if (config.isOutputSupportedFor(outputFormat)) {
            outputSize = config.getOutputSizes(outputFormat)[0];
        } else {
            return;
        }

        ImageReader imageReader = ImageReader.newInstance(outputSize.getWidth(),
                outputSize.getHeight(), outputFormat, /*maxImages*/3);

        class OnReadyCaptureStateCallback extends CameraCaptureSession.StateCallback {
            private ConditionVariable onReadyTriggeredCond = new ConditionVariable();
            private boolean onReadyTriggered = false;

            @Override
            public void onConfigured(CameraCaptureSession session) {
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
            }

            @Override
            public synchronized void onReady(CameraCaptureSession session) {
                onReadyTriggered = true;
                onReadyTriggeredCond.open();
            }

            public void waitForOnReady(long timeout) {
                synchronized (this) {
                    if (onReadyTriggered) {
                        onReadyTriggered = false;
                        onReadyTriggeredCond.close();
                        return;
                    }
                }

                if (onReadyTriggeredCond.block(timeout)) {
                    synchronized (this) {
                        onReadyTriggered = false;
                        onReadyTriggeredCond.close();
                    }
                } else {
                    throw new TimeoutRuntimeException("Unable to receive onReady after "
                        + timeout + "ms");
                }
            }
        }

        OnReadyCaptureStateCallback sessionListener = new OnReadyCaptureStateCallback();

        try {
            mSessionMockListener = spy(new BlockingSessionCallback(sessionListener));
            mSessionWaiter = mSessionMockListener.getStateWaiter();
            List<OutputConfiguration> outputs = new ArrayList<>();
            outputs.add(new OutputConfiguration(imageReader.getSurface()));
            SessionConfiguration sessionConfig = new SessionConfiguration(
                    SessionConfiguration.SESSION_REGULAR, outputs,
                    new HandlerExecutor(mHandler), mSessionMockListener);

            CaptureRequest.Builder builder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            builder.addTarget(imageReader.getSurface());
            CaptureRequest request = builder.build();

            sessionConfig.setSessionParameters(request);
            mCamera.createCaptureSession(sessionConfig);

            mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
            sessionListener.waitForOnReady(SESSION_CONFIGURE_TIMEOUT_MS);

            SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
            ImageDropperListener imageListener = new ImageDropperListener();
            imageReader.setOnImageAvailableListener(imageListener, mHandler);

            // To check the state leak condition, we need a capture request that has
            // at least one session pararameter value difference from the initial session
            // parameters configured above. Scan all available template types for the
            // required delta.
            CaptureRequest.Builder requestBuilder = null;
            ArrayList<CaptureRequest.Builder> builders = new ArrayList<CaptureRequest.Builder> ();
            if (mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL));
            }
            if (mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING)
                    || mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING)) {
                builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG));
            }
            builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT));
            builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW));
            builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD));
            for (CaptureRequest.Key<?> key : sessionKeys) {
                Object sessionValue = builder.get(key);
                for (CaptureRequest.Builder newBuilder : builders) {
                    Object currentValue = newBuilder.get(key);
                    if ((sessionValue == null) && (currentValue == null)) {
                        continue;
                    }

                    if (((sessionValue == null) && (currentValue != null)) ||
                            ((sessionValue != null) && (currentValue == null)) ||
                            (!sessionValue.equals(currentValue))) {
                        requestBuilder = newBuilder;
                        break;
                    }
                }

                if (requestBuilder != null) {
                    break;
                }
            }

            if (requestBuilder != null) {
                requestBuilder.addTarget(imageReader.getSurface());
                request = requestBuilder.build();
                mSession.setRepeatingRequest(request, captureListener, mHandler);
                try {
                    sessionListener.waitForOnReady(SESSION_CONFIGURE_TIMEOUT_MS);
                    fail("Camera shouldn't switch to ready state when session parameters are " +
                            "modified");
                } catch (TimeoutRuntimeException e) {
                    //expected
                }
            }
        } finally {
            imageReader.close();
            mSession.close();
        }
    }

    /**
     * Verify creating a session with additional parameters.
     */
    public void testCreateSessionWithParameters() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
                if (!mStaticInfo.isColorOutputSupported()) {
                    Log.i(TAG, "Camera " + mCameraIds[i] +
                            " does not support color outputs, skipping");
                    continue;
                }

                testCreateSessionWithParametersByCamera(mCameraIds[i], /*reprocessable*/false);
                testCreateSessionWithParametersByCamera(mCameraIds[i], /*reprocessable*/true);
            }
            finally {
                closeDevice(mCameraIds[i], mCameraMockListener);
            }
        }
    }

    /**
     * Verify creating a session with additional parameters works
     */
    private void testCreateSessionWithParametersByCamera(String cameraId, boolean reprocessable)
            throws Exception {
        final int SESSION_TIMEOUT_MS = 1000;
        final int CAPTURE_TIMEOUT_MS = 3000;
        int inputFormat = ImageFormat.YUV_420_888;
        int outputFormat = inputFormat;
        Size outputSize = mOrderedPreviewSizes.get(0);
        Size inputSize = outputSize;
        InputConfiguration inputConfig = null;

        if (VERBOSE) {
            Log.v(TAG, "Testing creating session with parameters for camera " + cameraId);
        }

        CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap config = characteristics.get(
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

        if (reprocessable) {
            //Pick a supported i/o format and size combination.
            //Ideally the input format should match the output.
            boolean found = false;
            int inputFormats [] = config.getInputFormats();
            if (inputFormats.length == 0) {
                return;
            }

            for (int inFormat : inputFormats) {
                int outputFormats [] = config.getValidOutputFormatsForInput(inFormat);
                for (int outFormat : outputFormats) {
                    if (inFormat == outFormat) {
                        inputFormat = inFormat;
                        outputFormat = outFormat;
                        found = true;
                        break;
                    }
                }
                if (found) {
                    break;
                }
            }

            //In case the above combination doesn't exist, pick the first first supported
            //pair.
            if (!found) {
                inputFormat = inputFormats[0];
                int outputFormats [] = config.getValidOutputFormatsForInput(inputFormat);
                assertTrue("No output formats supported for input format: " + inputFormat,
                        (outputFormats.length > 0));
                outputFormat = outputFormats[0];
            }

            Size inputSizes[] = config.getInputSizes(inputFormat);
            Size outputSizes[] = config.getOutputSizes(outputFormat);
            assertTrue("No valid sizes supported for input format: " + inputFormat,
                    (inputSizes.length > 0));
            assertTrue("No valid sizes supported for output format: " + outputFormat,
                    (outputSizes.length > 0));

            inputSize = inputSizes[0];
            outputSize = outputSizes[0];
            inputConfig = new InputConfiguration(inputSize.getWidth(),
                    inputSize.getHeight(), inputFormat);
        } else {
            if (config.isOutputSupportedFor(outputFormat)) {
                outputSize = config.getOutputSizes(outputFormat)[0];
            } else {
                return;
            }
        }

        ImageReader imageReader = ImageReader.newInstance(outputSize.getWidth(),
                outputSize.getHeight(), outputFormat, /*maxImages*/1);

        try {
            mSessionMockListener = spy(new BlockingSessionCallback());
            mSessionWaiter = mSessionMockListener.getStateWaiter();
            List<OutputConfiguration> outputs = new ArrayList<>();
            outputs.add(new OutputConfiguration(imageReader.getSurface()));
            SessionConfiguration sessionConfig = new SessionConfiguration(
                    SessionConfiguration.SESSION_REGULAR, outputs,
                    new HandlerExecutor(mHandler), mSessionMockListener);

            CaptureRequest.Builder builder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            builder.addTarget(imageReader.getSurface());
            CaptureRequest request = builder.build();

            sessionConfig.setInputConfiguration(inputConfig);
            sessionConfig.setSessionParameters(request);
            mCamera.createCaptureSession(sessionConfig);

            mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

            // Verify we can capture a frame with the session.
            SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
            SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
            imageReader.setOnImageAvailableListener(imageListener, mHandler);

            mSession.capture(request, captureListener, mHandler);
            captureListener.getCaptureResultForRequest(request, CAPTURE_TIMEOUT_MS);
            imageListener.getImage(CAPTURE_TIMEOUT_MS).close();
        } finally {
            imageReader.close();
            mSession.close();
        }
    }

    /**
     * Verify creating sessions back to back and only the last one is valid for
     * submitting requests.
     */
    private void testCreateSessionsByCamera(String cameraId) throws Exception {
        final int NUM_SESSIONS = 3;
        final int SESSION_TIMEOUT_MS = 1000;
        final int CAPTURE_TIMEOUT_MS = 3000;

        if (VERBOSE) {
            Log.v(TAG, "Testing creating sessions for camera " + cameraId);
        }

        Size yuvSize = getSortedSizesForFormat(cameraId, mCameraManager, ImageFormat.YUV_420_888,
                /*bound*/null).get(0);
        Size jpegSize = getSortedSizesForFormat(cameraId, mCameraManager, ImageFormat.JPEG,
                /*bound*/null).get(0);

        // Create a list of image readers. JPEG for last one and YUV for the rest.
        List<ImageReader> imageReaders = new ArrayList<>();
        List<CameraCaptureSession> allSessions = new ArrayList<>();

        try {
            for (int i = 0; i < NUM_SESSIONS - 1; i++) {
                imageReaders.add(ImageReader.newInstance(yuvSize.getWidth(), yuvSize.getHeight(),
                        ImageFormat.YUV_420_888, /*maxImages*/1));
            }
            imageReaders.add(ImageReader.newInstance(jpegSize.getWidth(), jpegSize.getHeight(),
                    ImageFormat.JPEG, /*maxImages*/1));

            // Create multiple sessions back to back.
            MultipleSessionCallback sessionListener =
                    new MultipleSessionCallback(/*failOnConfigureFailed*/true);
            for (int i = 0; i < NUM_SESSIONS; i++) {
                List<Surface> outputs = new ArrayList<>();
                outputs.add(imageReaders.get(i).getSurface());
                mCamera.createCaptureSession(outputs, sessionListener, mHandler);
            }

            // Verify we get onConfigured() for all sessions.
            allSessions = sessionListener.getAllSessions(NUM_SESSIONS,
                    SESSION_TIMEOUT_MS * NUM_SESSIONS);
            assertEquals(String.format("Got %d sessions but configured %d sessions",
                    allSessions.size(), NUM_SESSIONS), allSessions.size(), NUM_SESSIONS);

            // Verify all sessions except the last one are closed.
            for (int i = 0; i < NUM_SESSIONS - 1; i++) {
                sessionListener.waitForSessionClose(allSessions.get(i), SESSION_TIMEOUT_MS);
            }

            // Verify we can capture a frame with the last session.
            CameraCaptureSession session = allSessions.get(allSessions.size() - 1);
            SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
            ImageReader reader = imageReaders.get(imageReaders.size() - 1);
            SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
            reader.setOnImageAvailableListener(imageListener, mHandler);

            CaptureRequest.Builder builder =
                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            builder.addTarget(reader.getSurface());
            CaptureRequest request = builder.build();

            session.capture(request, captureListener, mHandler);
            captureListener.getCaptureResultForRequest(request, CAPTURE_TIMEOUT_MS);
            imageListener.getImage(CAPTURE_TIMEOUT_MS).close();
        } finally {
            for (ImageReader reader : imageReaders) {
                reader.close();
            }
            for (CameraCaptureSession session : allSessions) {
                session.close();
            }
        }
    }

    private void prepareTestByCamera() throws Exception {
        final int PREPARE_TIMEOUT_MS = 10000;

        mSessionMockListener = spy(new BlockingSessionCallback());

        SurfaceTexture output1 = new SurfaceTexture(1);
        Surface output1Surface = new Surface(output1);
        SurfaceTexture output2 = new SurfaceTexture(2);
        Surface output2Surface = new Surface(output2);

        ArrayList<OutputConfiguration> outConfigs = new ArrayList<OutputConfiguration> ();
        outConfigs.add(new OutputConfiguration(output1Surface));
        outConfigs.add(new OutputConfiguration(output2Surface));
        SessionConfiguration sessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_REGULAR, outConfigs,
                new HandlerExecutor(mHandler), mSessionMockListener);
        CaptureRequest.Builder r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        sessionConfig.setSessionParameters(r.build());
        mCamera.createCaptureSession(sessionConfig);

        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

        // Try basic prepare

        mSession.prepare(output1Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
                .onSurfacePrepared(eq(mSession), eq(output1Surface));

        // Should not complain if preparing already prepared stream

        mSession.prepare(output1Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(2))
                .onSurfacePrepared(eq(mSession), eq(output1Surface));

        // Check surface not included in session

        SurfaceTexture output3 = new SurfaceTexture(3);
        Surface output3Surface = new Surface(output3);
        try {
            mSession.prepare(output3Surface);
            // Legacy camera prepare always succeed
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                fail("Preparing surface not part of session must throw IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Ensure second prepare also works

        mSession.prepare(output2Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
                .onSurfacePrepared(eq(mSession), eq(output2Surface));

        // Use output1

        r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        r.addTarget(output1Surface);

        mSession.capture(r.build(), null, null);

        try {
            mSession.prepare(output1Surface);
            // Legacy camera prepare always succeed
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                fail("Preparing already-used surface must throw IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Create new session with outputs 1 and 3, ensure output1Surface still can't be prepared
        // again

        mSessionMockListener = spy(new BlockingSessionCallback());

        ArrayList<Surface> outputSurfaces = new ArrayList<Surface>(
            Arrays.asList(output1Surface, output3Surface));
        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);

        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

        try {
            mSession.prepare(output1Surface);
            // Legacy camera prepare always succeed
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                fail("Preparing surface used in previous session must throw " +
                        "IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Use output3, wait for result, then make sure prepare still doesn't work

        r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        r.addTarget(output3Surface);

        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        mSession.capture(r.build(), resultListener, mHandler);

        resultListener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);

        try {
            mSession.prepare(output3Surface);
            // Legacy camera prepare always succeed
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                fail("Preparing already-used surface must throw IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Create new session with outputs 1 and 2, ensure output2Surface can be prepared again

        mSessionMockListener = spy(new BlockingSessionCallback());

        outputSurfaces = new ArrayList<>(
            Arrays.asList(output1Surface, output2Surface));
        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);

        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

        mSession.prepare(output2Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
                .onSurfacePrepared(eq(mSession), eq(output2Surface));

        try {
            mSession.prepare(output1Surface);
            // Legacy camera prepare always succeed
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                fail("Preparing surface used in previous session must throw " +
                        "IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

        output1.release();
        output2.release();
        output3.release();
    }

    private void prepareTestForSharedSurfacesByCamera() throws Exception {
        final int PREPARE_TIMEOUT_MS = 10000;

        mSessionMockListener = spy(new BlockingSessionCallback());

        SurfaceTexture output1 = new SurfaceTexture(1);
        Surface output1Surface = new Surface(output1);
        SurfaceTexture output2 = new SurfaceTexture(2);
        Surface output2Surface = new Surface(output2);

        List<Surface> outputSurfaces = new ArrayList<>(
            Arrays.asList(output1Surface, output2Surface));
        OutputConfiguration surfaceSharedConfig = new OutputConfiguration(
            OutputConfiguration.SURFACE_GROUP_ID_NONE, output1Surface);
        surfaceSharedConfig.enableSurfaceSharing();
        surfaceSharedConfig.addSurface(output2Surface);

        List<OutputConfiguration> outputConfigurations = new ArrayList<>();
        outputConfigurations.add(surfaceSharedConfig);
        mCamera.createCaptureSessionByOutputConfigurations(
                outputConfigurations, mSessionMockListener, mHandler);

        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);

        // Try prepare on output1Surface
        mSession.prepare(output1Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
                .onSurfacePrepared(eq(mSession), eq(output1Surface));
        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
                .onSurfacePrepared(eq(mSession), eq(output2Surface));

        // Try prepare on output2Surface
        mSession.prepare(output2Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(2))
                .onSurfacePrepared(eq(mSession), eq(output1Surface));
        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(2))
                .onSurfacePrepared(eq(mSession), eq(output2Surface));

        // Try prepare on output1Surface again
        mSession.prepare(output1Surface);

        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(3))
                .onSurfacePrepared(eq(mSession), eq(output1Surface));
        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(3))
                .onSurfacePrepared(eq(mSession), eq(output2Surface));
    }

    private void invalidRequestCaptureTestByCamera() throws Exception {
        if (VERBOSE) Log.v(TAG, "invalidRequestCaptureTestByCamera");

        List<CaptureRequest> emptyRequests = new ArrayList<CaptureRequest>();
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        CaptureRequest unConfiguredRequest = requestBuilder.build();
        List<CaptureRequest> unConfiguredRequests = new ArrayList<CaptureRequest>();
        unConfiguredRequests.add(unConfiguredRequest);

        try {
            // Test: CameraCaptureSession capture should throw IAE for null request.
            mSession.capture(/*request*/null, /*listener*/null, mHandler);
            mCollector.addMessage(
                    "Session capture should throw IllegalArgumentException for null request");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession capture should throw IAE for request
            // without surface configured.
            mSession.capture(unConfiguredRequest, /*listener*/null, mHandler);
            mCollector.addMessage("Session capture should throw " +
                    "IllegalArgumentException for request without surface configured");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for null request.
            mSession.setRepeatingRequest(/*request*/null, /*listener*/null, mHandler);
            mCollector.addMessage("Session setRepeatingRequest should throw " +
                    "IllegalArgumentException for null request");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for for request
            // without surface configured.
            mSession.setRepeatingRequest(unConfiguredRequest, /*listener*/null, mHandler);
            mCollector.addMessage("Capture zero burst should throw IllegalArgumentException " +
                    "for request without surface configured");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession captureBurst should throw IAE for null request list.
            mSession.captureBurst(/*requests*/null, /*listener*/null, mHandler);
            mCollector.addMessage("Session captureBurst should throw " +
                    "IllegalArgumentException for null request list");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession captureBurst should throw IAE for empty request list.
            mSession.captureBurst(emptyRequests, /*listener*/null, mHandler);
            mCollector.addMessage("Session captureBurst should throw " +
                    " IllegalArgumentException for empty request list");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession captureBurst should throw IAE for request
            // without surface configured.
            mSession.captureBurst(unConfiguredRequests, /*listener*/null, mHandler);
            fail("Session captureBurst should throw IllegalArgumentException " +
                    "for null request list");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for null request list.
            mSession.setRepeatingBurst(/*requests*/null, /*listener*/null, mHandler);
            mCollector.addMessage("Session setRepeatingBurst should throw " +
                    "IllegalArgumentException for null request list");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for empty request list.
            mSession.setRepeatingBurst(emptyRequests, /*listener*/null, mHandler);
            mCollector.addMessage("Session setRepeatingBurst should throw " +
                    "IllegalArgumentException for empty request list");
        } catch (IllegalArgumentException e) {
            // Pass.
        }

        try {
            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for request
            // without surface configured.
            mSession.setRepeatingBurst(unConfiguredRequests, /*listener*/null, mHandler);
            mCollector.addMessage("Session setRepeatingBurst should throw " +
                    "IllegalArgumentException for request without surface configured");
        } catch (IllegalArgumentException e) {
            // Pass.
        }
    }

    private class IsCaptureResultNotEmpty
            implements ArgumentMatcher<TotalCaptureResult> {
        @Override
        public boolean matches(TotalCaptureResult result) {
            /**
             * Do the simple verification here. Only verify the timestamp for now.
             * TODO: verify more required capture result metadata fields.
             */
            Long timeStamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
            if (timeStamp != null && timeStamp.longValue() > 0L) {
                return true;
            }
            return false;
        }
    }

    /**
     * Run capture test with different test configurations.
     *
     * @param burst If the test uses {@link CameraCaptureSession#captureBurst} or
     * {@link CameraCaptureSession#setRepeatingBurst} to capture the burst.
     * @param repeating If the test uses {@link CameraCaptureSession#setRepeatingBurst} or
     * {@link CameraCaptureSession#setRepeatingRequest} for repeating capture.
     * @param abort If the test uses {@link CameraCaptureSession#abortCaptures} to stop the
     * repeating capture.  It has no effect if repeating is false.
     * @param useExecutor If the test uses {@link java.util.concurrent.Executor} instead of
     * {@link android.os.Handler} for callback invocation.
     */
    private void runCaptureTest(boolean burst, boolean repeating, boolean abort,
            boolean useExecutor) throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i], mCameraMockListener);
                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);

                prepareCapture();

                if (!burst) {
                    // Test: that a single capture of each template type succeeds.
                    for (int j = 0; j < sTemplates.length; j++) {
                        // Skip video snapshots for LEGACY mode
                        if (mStaticInfo.isHardwareLevelLegacy() &&
                                sTemplates[j] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
                            continue;
                        }
                        // Skip non-PREVIEW templates for non-color output
                        if (!mStaticInfo.isColorOutputSupported() &&
                                sTemplates[j] != CameraDevice.TEMPLATE_PREVIEW) {
                            continue;
                        }

                        captureSingleShot(mCameraIds[i], sTemplates[j], repeating, abort,
                                useExecutor);
                    }
                }
                else {
                    // Test: burst of one shot
                    captureBurstShot(mCameraIds[i], sTemplates, 1, repeating, abort, useExecutor);

                    int template = mStaticInfo.isColorOutputSupported() ?
                        CameraDevice.TEMPLATE_STILL_CAPTURE :
                        CameraDevice.TEMPLATE_PREVIEW;
                    int[] templates = new int[] {
                        template,
                        template,
                        template,
                        template,
                        template
                    };

                    // Test: burst of 5 shots of the same template type
                    captureBurstShot(mCameraIds[i], templates, templates.length, repeating, abort,
                            useExecutor);

                    if (mStaticInfo.isColorOutputSupported()) {
                        // Test: burst of 6 shots of different template types
                        captureBurstShot(mCameraIds[i], sTemplates, sTemplates.length, repeating,
                                abort, useExecutor);
                    }
                }
                verify(mCameraMockListener, never())
                        .onError(
                                any(CameraDevice.class),
                                anyInt());
            } catch (Exception e) {
                mCollector.addError(e);
            } finally {
                try {
                    closeSession();
                } catch (Exception e) {
                    mCollector.addError(e);
                }finally {
                    closeDevice(mCameraIds[i], mCameraMockListener);
                }
            }
        }
    }

    private void captureSingleShot(
            String id,
            int template,
            boolean repeating, boolean abort, boolean useExecutor) throws Exception {

        assertEquals("Bad initial state for preparing to capture",
                mLatestSessionState, SESSION_READY);

        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;
        CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(template);
        assertNotNull("Failed to create capture request", requestBuilder);
        requestBuilder.addTarget(mReaderSurface);
        CameraCaptureSession.CaptureCallback mockCaptureCallback =
                mock(CameraCaptureSession.CaptureCallback.class);

        if (VERBOSE) {
            Log.v(TAG, String.format("Capturing shot for device %s, template %d",
                    id, template));
        }

        if (executor != null) {
            startCapture(requestBuilder.build(), repeating, mockCaptureCallback, executor);
        } else {
            startCapture(requestBuilder.build(), repeating, mockCaptureCallback, mHandler);
        }
        waitForSessionState(SESSION_ACTIVE, SESSION_ACTIVE_TIMEOUT_MS);

        int expectedCaptureResultCount = repeating ? REPEATING_CAPTURE_EXPECTED_RESULT_COUNT : 1;
        verifyCaptureResults(mockCaptureCallback, expectedCaptureResultCount);

        if (repeating) {
            if (abort) {
                mSession.abortCaptures();
                // Have to make sure abort and new requests aren't interleave together.
                waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);

                // Capture a single capture, and verify the result.
                SimpleCaptureCallback resultCallback = new SimpleCaptureCallback();
                CaptureRequest singleRequest = requestBuilder.build();
                if (executor != null) {
                    mSession.captureSingleRequest(singleRequest, executor, resultCallback);
                } else {
                    mSession.capture(singleRequest, resultCallback, mHandler);
                }
                resultCallback.getCaptureResultForRequest(singleRequest, CAPTURE_RESULT_TIMEOUT_MS);

                // Resume the repeating, and verify that results are returned.
                if (executor != null) {
                    mSession.setSingleRepeatingRequest(singleRequest, executor, resultCallback);
                } else {
                    mSession.setRepeatingRequest(singleRequest, resultCallback, mHandler);
                }
                for (int i = 0; i < REPEATING_CAPTURE_EXPECTED_RESULT_COUNT; i++) {
                    resultCallback.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
                }
            }
            mSession.stopRepeating();
        }
        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
    }

    private void captureBurstShot(
            String id,
            int[] templates,
            int len,
            boolean repeating,
            boolean abort, boolean useExecutor) throws Exception {

        assertEquals("Bad initial state for preparing to capture",
                mLatestSessionState, SESSION_READY);

        assertTrue("Invalid args to capture function", len <= templates.length);
        List<CaptureRequest> requests = new ArrayList<CaptureRequest>();
        List<CaptureRequest> postAbortRequests = new ArrayList<CaptureRequest>();
        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;
        for (int i = 0; i < len; i++) {
            // Skip video snapshots for LEGACY mode
            if (mStaticInfo.isHardwareLevelLegacy() &&
                    templates[i] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
                continue;
            }
            // Skip non-PREVIEW templates for non-color outpu
            if (!mStaticInfo.isColorOutputSupported() &&
                    templates[i] != CameraDevice.TEMPLATE_PREVIEW) {
                continue;
            }

            CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(templates[i]);
            assertNotNull("Failed to create capture request", requestBuilder);
            requestBuilder.addTarget(mReaderSurface);
            requests.add(requestBuilder.build());
            if (abort) {
                postAbortRequests.add(requestBuilder.build());
            }
        }
        CameraCaptureSession.CaptureCallback mockCaptureCallback =
                mock(CameraCaptureSession.CaptureCallback.class);

        if (VERBOSE) {
            Log.v(TAG, String.format("Capturing burst shot for device %s", id));
        }

        if (!repeating) {
            if (executor != null) {
                mSession.captureBurstRequests(requests, executor, mockCaptureCallback);
            } else {
                mSession.captureBurst(requests, mockCaptureCallback, mHandler);
            }
        }
        else {
            if (executor != null) {
                mSession.setRepeatingBurstRequests(requests, executor, mockCaptureCallback);
            } else {
                mSession.setRepeatingBurst(requests, mockCaptureCallback, mHandler);
            }
        }
        waitForSessionState(SESSION_ACTIVE, SESSION_READY_TIMEOUT_MS);

        int expectedResultCount = requests.size();
        if (repeating) {
            expectedResultCount *= REPEATING_CAPTURE_EXPECTED_RESULT_COUNT;
        }

        verifyCaptureResults(mockCaptureCallback, expectedResultCount);

        if (repeating) {
            if (abort) {
                mSession.abortCaptures();
                // Have to make sure abort and new requests aren't interleave together.
                waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);

                // Capture a burst of captures, and verify the results.
                SimpleCaptureCallback resultCallback = new SimpleCaptureCallback();
                if (executor != null) {
                    mSession.captureBurstRequests(postAbortRequests, executor, resultCallback);
                } else {
                    mSession.captureBurst(postAbortRequests, resultCallback, mHandler);
                }
                // Verify that the results are returned.
                for (int i = 0; i < postAbortRequests.size(); i++) {
                    resultCallback.getCaptureResultForRequest(
                            postAbortRequests.get(i), CAPTURE_RESULT_TIMEOUT_MS);
                }

                // Resume the repeating, and verify that results are returned.
                if (executor != null) {
                    mSession.setRepeatingBurstRequests(requests, executor, resultCallback);
                } else {
                    mSession.setRepeatingBurst(requests, resultCallback, mHandler);
                }
                for (int i = 0; i < REPEATING_CAPTURE_EXPECTED_RESULT_COUNT; i++) {
                    resultCallback.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
                }
            }
            mSession.stopRepeating();
        }
        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
    }

    /**
     * Precondition: Device must be in known OPENED state (has been waited for).
     *
     * <p>Creates a new capture session and waits until it is in the {@code SESSION_READY} state.
     * </p>
     *
     * <p>Any existing capture session will be closed as a result of calling this.</p>
     * */
    private void prepareCapture() throws Exception {
        if (VERBOSE) Log.v(TAG, "prepareCapture");

        assertTrue("Bad initial state for preparing to capture",
                mLatestDeviceState == STATE_OPENED);

        if (mSession != null) {
            if (VERBOSE) Log.v(TAG, "prepareCapture - closing existing session");
            closeSession();
        }

        // Create a new session listener each time, it's not reusable across cameras
        mSessionMockListener = spy(new BlockingSessionCallback());
        mSessionWaiter = mSessionMockListener.getStateWaiter();

        if (!mStaticInfo.isColorOutputSupported()) {
            createDefaultImageReader(getMaxDepthSize(mCamera.getId(), mCameraManager),
                    ImageFormat.DEPTH16, MAX_NUM_IMAGES, new ImageDropperListener());
        } else {
            createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
                    new ImageDropperListener());
        }

        List<Surface> outputSurfaces = new ArrayList<>(Arrays.asList(mReaderSurface));
        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);

        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        waitForSessionState(SESSION_CONFIGURED, SESSION_CONFIGURE_TIMEOUT_MS);
        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
    }

    private void waitForDeviceState(int state, long timeoutMs) {
        mCameraMockListener.waitForState(state, timeoutMs);
        mLatestDeviceState = state;
    }

    private void waitForSessionState(int state, long timeoutMs) {
        mSessionWaiter.waitForState(state, timeoutMs);
        mLatestSessionState = state;
    }

    private void verifyCaptureResults(
            CameraCaptureSession.CaptureCallback mockListener,
            int expectResultCount) {
        final int TIMEOUT_PER_RESULT_MS = 2000;
        // Should receive expected number of capture results.
        verify(mockListener,
                timeout(TIMEOUT_PER_RESULT_MS * expectResultCount).atLeast(expectResultCount))
                        .onCaptureCompleted(
                                eq(mSession),
                                isA(CaptureRequest.class),
                                argThat(new IsCaptureResultNotEmpty()));
        // Should not receive any capture failed callbacks.
        verify(mockListener, never())
                        .onCaptureFailed(
                                eq(mSession),
                                isA(CaptureRequest.class),
                                isA(CaptureFailure.class));
        // Should receive expected number of capture shutter calls
        verify(mockListener,
                atLeast(expectResultCount))
                        .onCaptureStarted(
                               eq(mSession),
                               isA(CaptureRequest.class),
                               anyLong(),
                               anyLong());
    }

    private void checkFpsRange(CaptureRequest.Builder request, int template,
            CameraCharacteristics props) {
        CaptureRequest.Key<Range<Integer>> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
        Range<Integer> fpsRange;
        if ((fpsRange = mCollector.expectKeyValueNotNull(request, fpsRangeKey)) == null) {
            return;
        }

        int minFps = fpsRange.getLower();
        int maxFps = fpsRange.getUpper();
        Range<Integer>[] availableFpsRange = props
                .get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
        boolean foundRange = false;
        for (int i = 0; i < availableFpsRange.length; i += 1) {
            if (minFps == availableFpsRange[i].getLower()
                    && maxFps == availableFpsRange[i].getUpper()) {
                foundRange = true;
                break;
            }
        }
        if (!foundRange) {
            mCollector.addMessage(String.format("Unable to find the fps range (%d, %d)",
                    minFps, maxFps));
            return;
        }


        if (template != CameraDevice.TEMPLATE_MANUAL &&
                template != CameraDevice.TEMPLATE_STILL_CAPTURE) {
            if (maxFps < MIN_FPS_REQUIRED_FOR_STREAMING) {
                mCollector.addMessage("Max fps should be at least "
                        + MIN_FPS_REQUIRED_FOR_STREAMING);
                return;
            }

            // Relax framerate constraints on legacy mode
            if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
                // Need give fixed frame rate for video recording template.
                if (template == CameraDevice.TEMPLATE_RECORD) {
                    if (maxFps != minFps) {
                        mCollector.addMessage("Video recording frame rate should be fixed");
                    }
                }
            }
        }
    }

    private void checkAfMode(CaptureRequest.Builder request, int template,
            CameraCharacteristics props) {
        boolean hasFocuser = props.getKeys().contains(CameraCharacteristics.
                LENS_INFO_MINIMUM_FOCUS_DISTANCE) &&
                (props.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) > 0f);

        if (!hasFocuser) {
            return;
        }

        int targetAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
        int[] availableAfMode = props.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
        if (template == CameraDevice.TEMPLATE_PREVIEW ||
                template == CameraDevice.TEMPLATE_STILL_CAPTURE ||
                template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG) {
            // Default to CONTINUOUS_PICTURE if it is available, otherwise AUTO.
            for (int i = 0; i < availableAfMode.length; i++) {
                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) {
                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
                    break;
                }
            }
        } else if (template == CameraDevice.TEMPLATE_RECORD ||
                template == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
            // Default to CONTINUOUS_VIDEO if it is available, otherwise AUTO.
            for (int i = 0; i < availableAfMode.length; i++) {
                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
                    break;
                }
            }
        } else if (template == CameraDevice.TEMPLATE_MANUAL) {
            targetAfMode = CaptureRequest.CONTROL_AF_MODE_OFF;
        }

        mCollector.expectKeyValueEquals(request, CONTROL_AF_MODE, targetAfMode);
        if (mStaticInfo.areKeysAvailable(CaptureRequest.LENS_FOCUS_DISTANCE)) {
            mCollector.expectKeyValueNotNull(request, LENS_FOCUS_DISTANCE);
        }
    }

    private void checkAntiBandingMode(CaptureRequest.Builder request, int template) {
        if (template == CameraDevice.TEMPLATE_MANUAL) {
            return;
        }

        if (!mStaticInfo.isColorOutputSupported()) return;

        List<Integer> availableAntiBandingModes =
                Arrays.asList(toObject(mStaticInfo.getAeAvailableAntiBandingModesChecked()));

        if (availableAntiBandingModes.contains(CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO)) {
            mCollector.expectKeyValueEquals(request, CONTROL_AE_ANTIBANDING_MODE,
                    CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO);
        } else {
            mCollector.expectKeyValueIsIn(request, CONTROL_AE_ANTIBANDING_MODE,
                    CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_50HZ,
                    CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_60HZ);
        }
    }

    /**
     * <p>Check if 3A metering settings are "up to HAL" in request template</p>
     *
     * <p>This function doesn't fail the test immediately, it updates the
     * test pass/fail status and appends the failure message to the error collector each key.</p>
     *
     * @param regions The metering rectangles to be checked
     */
    private void checkMeteringRect(MeteringRectangle[] regions) {
        if (regions == null) {
            return;
        }
        mCollector.expectNotEquals("Number of metering region should not be 0", 0, regions.length);
        for (int i = 0; i < regions.length; i++) {
            mCollector.expectEquals("Default metering regions should have all zero weight",
                    0, regions[i].getMeteringWeight());
        }
    }

    /**
     * <p>Check if the request settings are suitable for a given request template.</p>
     *
     * <p>This function doesn't fail the test immediately, it updates the
     * test pass/fail status and appends the failure message to the error collector each key.</p>
     *
     * @param request The request to be checked.
     * @param template The capture template targeted by this request.
     * @param props The CameraCharacteristics this request is checked against with.
     */
    private void checkRequestForTemplate(CaptureRequest.Builder request, int template,
            CameraCharacteristics props) {
        Integer hwLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
        boolean isExternalCamera = (hwLevel ==
                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);

        // 3A settings--AE/AWB/AF.
        Integer maxRegionsAeVal = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
        int maxRegionsAe = maxRegionsAeVal != null ? maxRegionsAeVal : 0;
        Integer maxRegionsAwbVal = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
        int maxRegionsAwb = maxRegionsAwbVal != null ? maxRegionsAwbVal : 0;
        Integer maxRegionsAfVal = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
        int maxRegionsAf = maxRegionsAfVal != null ? maxRegionsAfVal : 0;

        checkFpsRange(request, template, props);

        checkAfMode(request, template, props);
        checkAntiBandingMode(request, template);

        if (template == CameraDevice.TEMPLATE_MANUAL) {
            mCollector.expectKeyValueEquals(request, CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
            mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_OFF);
            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
                    CaptureRequest.CONTROL_AWB_MODE_OFF);
        } else {
            mCollector.expectKeyValueEquals(request, CONTROL_MODE,
                    CaptureRequest.CONTROL_MODE_AUTO);
            if (mStaticInfo.isColorOutputSupported()) {
                mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
                        CaptureRequest.CONTROL_AE_MODE_ON);
                mCollector.expectKeyValueEquals(request, CONTROL_AE_EXPOSURE_COMPENSATION, 0);
                mCollector.expectKeyValueEquals(request, CONTROL_AE_PRECAPTURE_TRIGGER,
                        CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
                // if AE lock is not supported, expect the control key to be non-exist or false
                if (mStaticInfo.isAeLockSupported() || request.get(CONTROL_AE_LOCK) != null) {
                    mCollector.expectKeyValueEquals(request, CONTROL_AE_LOCK, false);
                }

                mCollector.expectKeyValueEquals(request, CONTROL_AF_TRIGGER,
                        CaptureRequest.CONTROL_AF_TRIGGER_IDLE);

                mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
                        CaptureRequest.CONTROL_AWB_MODE_AUTO);
                // if AWB lock is not supported, expect the control key to be non-exist or false
                if (mStaticInfo.isAwbLockSupported() || request.get(CONTROL_AWB_LOCK) != null) {
                    mCollector.expectKeyValueEquals(request, CONTROL_AWB_LOCK, false);
                }

                // Check 3A regions.
                if (VERBOSE) {
                    Log.v(TAG, String.format("maxRegions is: {AE: %s, AWB: %s, AF: %s}",
                                    maxRegionsAe, maxRegionsAwb, maxRegionsAf));
                }
                if (maxRegionsAe > 0) {
                    mCollector.expectKeyValueNotNull(request, CONTROL_AE_REGIONS);
                    MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
                    checkMeteringRect(aeRegions);
                }
                if (maxRegionsAwb > 0) {
                    mCollector.expectKeyValueNotNull(request, CONTROL_AWB_REGIONS);
                    MeteringRectangle[] awbRegions = request.get(CONTROL_AWB_REGIONS);
                    checkMeteringRect(awbRegions);
                }
                if (maxRegionsAf > 0) {
                    mCollector.expectKeyValueNotNull(request, CONTROL_AF_REGIONS);
                    MeteringRectangle[] afRegions = request.get(CONTROL_AF_REGIONS);
                    checkMeteringRect(afRegions);
                }
            }
        }

        // Sensor settings.

        mCollector.expectEquals("Lens aperture must be present in request if available apertures " +
                        "are present in metadata, and vice-versa.",
                mStaticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES),
                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_APERTURE));
        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)) {
            float[] availableApertures =
                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES);
            if (availableApertures.length > 1) {
                mCollector.expectKeyValueNotNull(request, LENS_APERTURE);
            }
        }

        mCollector.expectEquals("Lens filter density must be present in request if available " +
                        "filter densities are present in metadata, and vice-versa.",
                mStaticInfo.areKeysAvailable(CameraCharacteristics.
                        LENS_INFO_AVAILABLE_FILTER_DENSITIES),
                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_FILTER_DENSITY));
        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.
                LENS_INFO_AVAILABLE_FILTER_DENSITIES)) {
            float[] availableFilters =
                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES);
            if (availableFilters.length > 1) {
                mCollector.expectKeyValueNotNull(request, LENS_FILTER_DENSITY);
            }
        }


        if (!isExternalCamera) {
            float[] availableFocalLen =
                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
            if (availableFocalLen.length > 1) {
                mCollector.expectKeyValueNotNull(request, LENS_FOCAL_LENGTH);
            }
        }


        mCollector.expectEquals("Lens optical stabilization must be present in request if " +
                        "available optical stabilizations are present in metadata, and vice-versa.",
                mStaticInfo.areKeysAvailable(CameraCharacteristics.
                        LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION),
                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE));
        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.
                LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) {
            int[] availableOIS =
                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);
            if (availableOIS.length > 1) {
                mCollector.expectKeyValueNotNull(request, LENS_OPTICAL_STABILIZATION_MODE);
            }
        }

        if (mStaticInfo.areKeysAvailable(SENSOR_TEST_PATTERN_MODE)) {
            mCollector.expectKeyValueEquals(request, SENSOR_TEST_PATTERN_MODE,
                    CaptureRequest.SENSOR_TEST_PATTERN_MODE_OFF);
        }

        if (mStaticInfo.areKeysAvailable(BLACK_LEVEL_LOCK)) {
            mCollector.expectKeyValueEquals(request, BLACK_LEVEL_LOCK, false);
        }

        if (mStaticInfo.areKeysAvailable(SENSOR_FRAME_DURATION)) {
            mCollector.expectKeyValueNotNull(request, SENSOR_FRAME_DURATION);
        }

        if (mStaticInfo.areKeysAvailable(SENSOR_EXPOSURE_TIME)) {
            mCollector.expectKeyValueNotNull(request, SENSOR_EXPOSURE_TIME);
        }

        if (mStaticInfo.areKeysAvailable(SENSOR_SENSITIVITY)) {
            mCollector.expectKeyValueNotNull(request, SENSOR_SENSITIVITY);
        }

        // ISP-processing settings.
        if (mStaticInfo.isColorOutputSupported()) {
            mCollector.expectKeyValueEquals(
                    request, STATISTICS_FACE_DETECT_MODE,
                    CaptureRequest.STATISTICS_FACE_DETECT_MODE_OFF);
            mCollector.expectKeyValueEquals(request, FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
        }

        List<Integer> availableCaps = mStaticInfo.getAvailableCapabilitiesChecked();
        if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE)) {
            // If the device doesn't support RAW, all template should have OFF as default.
            if (!availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
                mCollector.expectKeyValueEquals(
                        request, STATISTICS_LENS_SHADING_MAP_MODE,
                        CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_OFF);
            }
        }

        boolean supportReprocessing =
                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) ||
                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);


        if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {

            // Ok with either FAST or HIGH_QUALITY
            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_MODE)) {
                mCollector.expectKeyValueNotEquals(
                        request, COLOR_CORRECTION_MODE,
                        CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
            }

            // Edge enhancement, noise reduction and aberration correction modes.
            mCollector.expectEquals("Edge mode must be present in request if " +
                            "available edge modes are present in metadata, and vice-versa.",
                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
                            EDGE_AVAILABLE_EDGE_MODES),
                    mStaticInfo.areKeysAvailable(CaptureRequest.EDGE_MODE));
            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
                List<Integer> availableEdgeModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
                // Don't need check fast as fast or high quality must be both present or both not.
                if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
                            CaptureRequest.EDGE_MODE_HIGH_QUALITY);
                } else {
                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
                            CaptureRequest.EDGE_MODE_OFF);
                }
            }
            if (mStaticInfo.areKeysAvailable(SHADING_MODE)) {
                List<Integer> availableShadingModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableShadingModesChecked()));
                mCollector.expectKeyValueEquals(request, SHADING_MODE,
                        CaptureRequest.SHADING_MODE_HIGH_QUALITY);
            }

            mCollector.expectEquals("Noise reduction mode must be present in request if " +
                            "available noise reductions are present in metadata, and vice-versa.",
                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
                            NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES),
                    mStaticInfo.areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE));
            if (mStaticInfo.areKeysAvailable(
                    CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)) {
                List<Integer> availableNoiseReductionModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableNoiseReductionModesChecked()));
                // Don't need check fast as fast or high quality must be both present or both not.
                if (availableNoiseReductionModes
                        .contains(CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(
                            request, NOISE_REDUCTION_MODE,
                            CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
                }
            }

            mCollector.expectEquals("Hot pixel mode must be present in request if " +
                            "available hot pixel modes are present in metadata, and vice-versa.",
                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
                            HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES),
                    mStaticInfo.areKeysAvailable(CaptureRequest.HOT_PIXEL_MODE));

            if (mStaticInfo.areKeysAvailable(HOT_PIXEL_MODE)) {
                List<Integer> availableHotPixelModes =
                        Arrays.asList(toObject(
                                mStaticInfo.getAvailableHotPixelModesChecked()));
                if (availableHotPixelModes
                        .contains(CaptureRequest.HOT_PIXEL_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(
                            request, HOT_PIXEL_MODE,
                            CaptureRequest.HOT_PIXEL_MODE_HIGH_QUALITY);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, HOT_PIXEL_MODE, CaptureRequest.HOT_PIXEL_MODE_OFF);
                }
            }

            boolean supportAvailableAberrationModes = mStaticInfo.areKeysAvailable(
                    CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES);
            boolean supportAberrationRequestKey = mStaticInfo.areKeysAvailable(
                    CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE);
            mCollector.expectEquals("Aberration correction mode must be present in request if " +
                    "available aberration correction reductions are present in metadata, and "
                    + "vice-versa.", supportAvailableAberrationModes, supportAberrationRequestKey);
            if (supportAberrationRequestKey) {
                List<Integer> availableAberrationModes = Arrays.asList(
                        toObject(mStaticInfo.getAvailableColorAberrationModesChecked()));
                // Don't need check fast as fast or high quality must be both present or both not.
                if (availableAberrationModes
                        .contains(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(
                            request, COLOR_CORRECTION_ABERRATION_MODE,
                            CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, COLOR_CORRECTION_ABERRATION_MODE,
                            CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
                }
            }
        } else if (template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG && supportReprocessing) {
            mCollector.expectKeyValueEquals(request, EDGE_MODE,
                    CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG);
            mCollector.expectKeyValueEquals(request, NOISE_REDUCTION_MODE,
                    CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
        } else if (template == CameraDevice.TEMPLATE_PREVIEW ||
                template == CameraDevice.TEMPLATE_RECORD) {

            // Ok with either FAST or HIGH_QUALITY
            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_MODE)) {
                mCollector.expectKeyValueNotEquals(
                        request, COLOR_CORRECTION_MODE,
                        CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
            }

            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
                List<Integer> availableEdgeModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
                if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
                            CaptureRequest.EDGE_MODE_FAST);
                } else {
                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
                            CaptureRequest.EDGE_MODE_OFF);
                }
            }

            if (mStaticInfo.areKeysAvailable(SHADING_MODE)) {
                List<Integer> availableShadingModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableShadingModesChecked()));
                mCollector.expectKeyValueEquals(request, SHADING_MODE,
                        CaptureRequest.SHADING_MODE_FAST);
            }

            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
                List<Integer> availableNoiseReductionModes =
                        Arrays.asList(toObject(
                                mStaticInfo.getAvailableNoiseReductionModesChecked()));
                if (availableNoiseReductionModes
                        .contains(CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
                    mCollector.expectKeyValueEquals(
                            request, NOISE_REDUCTION_MODE,
                            CaptureRequest.NOISE_REDUCTION_MODE_FAST);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
                }
            }

            if (mStaticInfo.areKeysAvailable(HOT_PIXEL_MODE)) {
                List<Integer> availableHotPixelModes =
                        Arrays.asList(toObject(
                                mStaticInfo.getAvailableHotPixelModesChecked()));
                if (availableHotPixelModes
                        .contains(CaptureRequest.HOT_PIXEL_MODE_FAST)) {
                    mCollector.expectKeyValueEquals(
                            request, HOT_PIXEL_MODE,
                            CaptureRequest.HOT_PIXEL_MODE_FAST);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, HOT_PIXEL_MODE, CaptureRequest.HOT_PIXEL_MODE_OFF);
                }
            }

            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_ABERRATION_MODE)) {
                List<Integer> availableAberrationModes = Arrays.asList(
                        toObject(mStaticInfo.getAvailableColorAberrationModesChecked()));
                if (availableAberrationModes
                        .contains(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_FAST)) {
                    mCollector.expectKeyValueEquals(
                            request, COLOR_CORRECTION_ABERRATION_MODE,
                            CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_FAST);
                } else {
                    mCollector.expectKeyValueEquals(
                            request, COLOR_CORRECTION_ABERRATION_MODE,
                            CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
                }
            }
        } else {
            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
                mCollector.expectKeyValueNotNull(request, EDGE_MODE);
            }

            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
                mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
            }

            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_ABERRATION_MODE)) {
                mCollector.expectKeyValueNotNull(request, COLOR_CORRECTION_ABERRATION_MODE);
            }
        }

        // Tone map and lens shading modes.
        if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
            mCollector.expectEquals("Tonemap mode must be present in request if " +
                            "available tonemap modes are present in metadata, and vice-versa.",
                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
                            TONEMAP_AVAILABLE_TONE_MAP_MODES),
                    mStaticInfo.areKeysAvailable(CaptureRequest.TONEMAP_MODE));
            if (mStaticInfo.areKeysAvailable(
                    CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES)) {
                List<Integer> availableToneMapModes =
                        Arrays.asList(toObject(mStaticInfo.getAvailableToneMapModesChecked()));
                if (availableToneMapModes.contains(CaptureRequest.TONEMAP_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
                            CaptureRequest.TONEMAP_MODE_HIGH_QUALITY);
                } else {
                    mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
                            CaptureRequest.TONEMAP_MODE_FAST);
                }
            }

            // Still capture template should have android.statistics.lensShadingMapMode ON when
            // RAW capability is supported.
            if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE) &&
                    availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
                    mCollector.expectKeyValueEquals(request, STATISTICS_LENS_SHADING_MAP_MODE,
                            STATISTICS_LENS_SHADING_MAP_MODE_ON);
            }
        } else {
            if (mStaticInfo.areKeysAvailable(TONEMAP_MODE)) {
                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
                        CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
                        CaptureRequest.TONEMAP_MODE_GAMMA_VALUE);
                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
                        CaptureRequest.TONEMAP_MODE_PRESET_CURVE);
            }
            if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE)) {
                mCollector.expectKeyValueEquals(request, STATISTICS_LENS_SHADING_MAP_MODE,
                        CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_OFF);
            }
            if (mStaticInfo.areKeysAvailable(STATISTICS_HOT_PIXEL_MAP_MODE)) {
                mCollector.expectKeyValueEquals(request, STATISTICS_HOT_PIXEL_MAP_MODE,
                        false);
            }
        }

        // Enable ZSL
        if (template != CameraDevice.TEMPLATE_STILL_CAPTURE) {
            if (mStaticInfo.areKeysAvailable(CONTROL_ENABLE_ZSL)) {
                    mCollector.expectKeyValueEquals(request, CONTROL_ENABLE_ZSL, false);
            }
        }

        int[] outputFormats = mStaticInfo.getAvailableFormats(
                StaticMetadata.StreamDirection.Output);
        boolean supportRaw = false;
        for (int format : outputFormats) {
            if (format == ImageFormat.RAW_SENSOR || format == ImageFormat.RAW10 ||
                    format == ImageFormat.RAW12 || format == ImageFormat.RAW_PRIVATE) {
                supportRaw = true;
                break;
            }
        }
        if (supportRaw) {
            mCollector.expectKeyValueEquals(request,
                    CONTROL_POST_RAW_SENSITIVITY_BOOST,
                    DEFAULT_POST_RAW_SENSITIVITY_BOOST);
        }

        switch(template) {
            case CameraDevice.TEMPLATE_PREVIEW:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_PREVIEW);
                break;
            case CameraDevice.TEMPLATE_STILL_CAPTURE:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
                break;
            case CameraDevice.TEMPLATE_RECORD:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
                break;
            case CameraDevice.TEMPLATE_VIDEO_SNAPSHOT:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
                break;
            case CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG);
                break;
            case CameraDevice.TEMPLATE_MANUAL:
                mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT,
                        CameraCharacteristics.CONTROL_CAPTURE_INTENT_MANUAL);
                break;
            default:
                // Skip unknown templates here
        }

        // Check distortion correction mode
        if (mStaticInfo.isDistortionCorrectionSupported()) {
            mCollector.expectKeyValueNotEquals(request, DISTORTION_CORRECTION_MODE,
                    CaptureRequest.DISTORTION_CORRECTION_MODE_OFF);
        }

        // TODO: use the list of keys from CameraCharacteristics to avoid expecting
        //       keys which are not available by this CameraDevice.
    }

    private void captureTemplateTestByCamera(String cameraId, int template) throws Exception {
        try {
            openDevice(cameraId, mCameraMockListener);

            assertTrue("Camera template " + template + " is out of range!",
                    template >= CameraDevice.TEMPLATE_PREVIEW
                            && template <= CameraDevice.TEMPLATE_MANUAL);

            mCollector.setCameraId(cameraId);

            try {
                CaptureRequest.Builder request = mCamera.createCaptureRequest(template);
                assertNotNull("Failed to create capture request for template " + template, request);

                CameraCharacteristics props = mStaticInfo.getCharacteristics();
                checkRequestForTemplate(request, template, props);
            } catch (IllegalArgumentException e) {
                if (template == CameraDevice.TEMPLATE_MANUAL &&
                        !mStaticInfo.isCapabilitySupported(CameraCharacteristics.
                                REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    // OK
                } else if (template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG &&
                        !mStaticInfo.isCapabilitySupported(CameraCharacteristics.
                                REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING)) {
                    // OK.
                } else if (sLegacySkipTemplates.contains(template) &&
                        mStaticInfo.isHardwareLevelLegacy()) {
                    // OK
                } else if (template != CameraDevice.TEMPLATE_PREVIEW &&
                        mStaticInfo.isDepthOutputSupported() &&
                        !mStaticInfo.isColorOutputSupported()) {
                    // OK, depth-only devices need only support PREVIEW template
                } else {
                    throw e; // rethrow
                }
            }
        }
        finally {
            try {
                closeSession();
            } finally {
                closeDevice(cameraId, mCameraMockListener);
            }
        }
    }

    /**
     * Start capture with given {@link #CaptureRequest}.
     *
     * @param request The {@link #CaptureRequest} to be captured.
     * @param repeating If the capture is single capture or repeating.
     * @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
     * @param handler The handler camera device used to post callbacks.
     */
    @Override
    protected void startCapture(CaptureRequest request, boolean repeating,
            CameraCaptureSession.CaptureCallback listener, Handler handler)
                    throws CameraAccessException {
        if (VERBOSE) Log.v(TAG, "Starting capture from session");

        if (repeating) {
            mSession.setRepeatingRequest(request, listener, handler);
        } else {
            mSession.capture(request, listener, handler);
        }
    }

    /**
     * Start capture with given {@link #CaptureRequest}.
     *
     * @param request The {@link #CaptureRequest} to be captured.
     * @param repeating If the capture is single capture or repeating.
     * @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
     * @param executor The executor used to invoke callbacks.
     */
    protected void startCapture(CaptureRequest request, boolean repeating,
            CameraCaptureSession.CaptureCallback listener, Executor executor)
                    throws CameraAccessException {
        if (VERBOSE) Log.v(TAG, "Starting capture from session");

        if (repeating) {
            mSession.setSingleRepeatingRequest(request, executor, listener);
        } else {
            mSession.captureSingleRequest(request, executor, listener);
        }
    }

    /**
     * Close a {@link #CameraCaptureSession capture session}; blocking until
     * the close finishes with a transition to {@link CameraCaptureSession.StateCallback#onClosed}.
     */
    protected void closeSession() {
        if (mSession == null) {
            return;
        }

        mSession.close();
        waitForSessionState(SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
        mSession = null;

        mSessionMockListener = null;
        mSessionWaiter = null;
    }

    /**
     * A camera capture session listener that keeps all the configured and closed sessions.
     */
    private class MultipleSessionCallback extends CameraCaptureSession.StateCallback {
        public static final int SESSION_CONFIGURED = 0;
        public static final int SESSION_CLOSED = 1;

        final List<CameraCaptureSession> mSessions = new ArrayList<>();
        final Map<CameraCaptureSession, Integer> mSessionStates = new HashMap<>();
        CameraCaptureSession mCurrentConfiguredSession = null;

        final ReentrantLock mLock = new ReentrantLock();
        final Condition mNewStateCond = mLock.newCondition();

        final boolean mFailOnConfigureFailed;

        /**
         * If failOnConfigureFailed is true, it calls fail() when onConfigureFailed() is invoked
         * for any session.
         */
        public MultipleSessionCallback(boolean failOnConfigureFailed) {
            mFailOnConfigureFailed = failOnConfigureFailed;
        }

        @Override
        public void onClosed(CameraCaptureSession session) {
            mLock.lock();
            mSessionStates.put(session, SESSION_CLOSED);
            mNewStateCond.signal();
            mLock.unlock();
        }

        @Override
        public void onConfigured(CameraCaptureSession session) {
            mLock.lock();
            mSessions.add(session);
            mSessionStates.put(session, SESSION_CONFIGURED);
            mNewStateCond.signal();
            mLock.unlock();
        }

        @Override
        public void onConfigureFailed(CameraCaptureSession session) {
            if (mFailOnConfigureFailed) {
                fail("Configuring a session failed");
            }
        }

        /**
         * Get a number of sessions that have been configured.
         */
        public List<CameraCaptureSession> getAllSessions(int numSessions, int timeoutMs)
                throws Exception {
            long remainingTime = timeoutMs;
            mLock.lock();
            try {
                while (mSessions.size() < numSessions) {
                    long startTime = SystemClock.elapsedRealtime();
                    boolean ret = mNewStateCond.await(remainingTime, TimeUnit.MILLISECONDS);
                    remainingTime -= (SystemClock.elapsedRealtime() - startTime);
                    ret &= remainingTime > 0;

                    assertTrue("Get " + numSessions + " sessions timed out after " + timeoutMs +
                            "ms", ret);
                }

                return mSessions;
            } finally {
                mLock.unlock();
            }
        }

        /**
         * Wait until a previously-configured sessoin is closed or it times out.
         */
        public void waitForSessionClose(CameraCaptureSession session, int timeoutMs) throws Exception {
            long remainingTime = timeoutMs;
            mLock.lock();
            try {
                while (mSessionStates.get(session).equals(SESSION_CLOSED) == false) {
                    long startTime = SystemClock.elapsedRealtime();
                    boolean ret = mNewStateCond.await(remainingTime, TimeUnit.MILLISECONDS);
                    remainingTime -= (SystemClock.elapsedRealtime() - startTime);
                    ret &= remainingTime > 0;

                    assertTrue("Wait for session close timed out after " + timeoutMs + "ms", ret);
                }
            } finally {
                mLock.unlock();
            }
        }
    }
}
