/*
 * 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.testcases.Camera2AndroidTestCase;
import android.hardware.camera2.params.MeteringRectangle;
import android.media.ImageReader;
import android.os.Handler;
import android.os.SystemClock;
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.utils.StateWaiter;

import org.mockito.ArgumentMatcher;

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 java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * <p>Basic test for CameraDevice APIs.</p>
 */
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 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
    };

    // 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;
        createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
                new ImageDropperListener());
    }

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

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

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

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

    /**
     * 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);
        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/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 {

        // Set up single dummy target
        createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
                /*listener*/ null);
        final ArrayList<Surface> outputs = new ArrayList<>();
        outputs.add(mReaderSurface);

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

            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();

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

            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;

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

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

            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++) {
            Throwable result;

            // 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;
                }
            }
        }
    }

    /**
     * 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);

                prepareTestByCamera();
            }
            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);

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

    /**
     * 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);

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

        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.isHardwareLevelLimitedOrBetter()) {
                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

        CaptureRequest.Builder 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.isHardwareLevelLimitedOrBetter()) {
                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());

        outputSurfaces = new ArrayList<>(
            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.isHardwareLevelLimitedOrBetter()) {
                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.isHardwareLevelLimitedOrBetter()) {
                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.isHardwareLevelLimitedOrBetter()) {
                fail("Preparing surface used in previous session must throw " +
                        "IllegalArgumentException");
            }
        } catch (IllegalArgumentException e) {
            // expected
        }

    }


    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
            extends ArgumentMatcher<TotalCaptureResult> {
        @Override
        public boolean matches(Object obj) {
            /**
             * Do the simple verification here. Only verify the timestamp for now.
             * TODO: verify more required capture result metadata fields.
             */
            TotalCaptureResult result = (TotalCaptureResult) obj;
            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.
     */
    private void runCaptureTest(boolean burst, boolean repeating, boolean abort) 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;
                        }
                        captureSingleShot(mCameraIds[i], sTemplates[j], repeating, abort);
                    }
                }
                else {
                    // Test: burst of one shot
                    captureBurstShot(mCameraIds[i], sTemplates, 1, repeating, abort);

                    int[] templates = new int[] {
                            CameraDevice.TEMPLATE_STILL_CAPTURE,
                            CameraDevice.TEMPLATE_STILL_CAPTURE,
                            CameraDevice.TEMPLATE_STILL_CAPTURE,
                            CameraDevice.TEMPLATE_STILL_CAPTURE,
                            CameraDevice.TEMPLATE_STILL_CAPTURE
                            };

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

                    // Test: burst of 5 shots of different template types
                    captureBurstShot(
                            mCameraIds[i], sTemplates, sTemplates.length, repeating, abort);
                }
                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) throws Exception {

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

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

        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();
            } else {
                mSession.stopRepeating();
            }
        }
        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
    }

    private void captureBurstShot(
            String id,
            int[] templates,
            int len,
            boolean repeating,
            boolean abort) 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>();
        for (int i = 0; i < len; i++) {
            // Skip video snapshots for LEGACY mode
            if (mStaticInfo.isHardwareLevelLegacy() &&
                    templates[i] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
                continue;
            }
            CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(templates[i]);
            assertNotNull("Failed to create capture request", requestBuilder);
            requestBuilder.addTarget(mReaderSurface);
            requests.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) {
            mSession.captureBurst(requests, mockCaptureCallback, mHandler);
        }
        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();
            } else {
                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();

        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.isHardwareLevelLimitedOrBetter()) {
                // 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;
        }

        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) {
        // 3A settings--control.mode.
        if (template != CameraDevice.TEMPLATE_MANUAL) {
            mCollector.expectKeyValueEquals(request, CONTROL_MODE,
                    CaptureRequest.CONTROL_MODE_AUTO);
        }

        // 3A settings--AE/AWB/AF.
        int maxRegionsAe = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
        int maxRegionsAwb = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
        int maxRegionsAf = props.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);

        checkAfMode(request, template, props);
        checkFpsRange(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_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);
            }
        }

        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(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.
        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);
            }
        }

        // Edge enhancement and noise reduction modes
        boolean supportReprocessing =
                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) ||
                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);

        if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
            // Not enforce high quality here, as some devices may not effectively have high quality
            // mode.
            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_MODE)) {
                mCollector.expectKeyValueNotEquals(
                        request, COLOR_CORRECTION_MODE,
                        CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
            }

            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()));
                if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
                            CaptureRequest.EDGE_MODE_HIGH_QUALITY);
                } else 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);
                }
            }

            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()));
                if (availableNoiseReductionModes
                        .contains(CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
                    mCollector.expectKeyValueEquals(
                            request, NOISE_REDUCTION_MODE,
                            CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
                } else 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);
                }
            }
        } 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 (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
                mCollector.expectKeyValueNotNull(request, EDGE_MODE);
            }

            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
                mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_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.expectKeyValueNotNull(request, STATISTICS_LENS_SHADING_MAP_MODE);
            }
        }

        mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT, template);

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

    /**
     * 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();
            }
        }
    }
}
