/*
 * Copyright 2014 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 android.hardware.camera2.CameraCharacteristics.*;

import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.ColorSpaceTransform;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.RggbChannelVector;
import android.hardware.camera2.params.TonemapCurve;

import android.util.Log;
import android.util.Range;
import android.util.Rational;
import android.util.Size;

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

/**
 * <p>
 * Basic test for camera CaptureRequest key controls.
 * </p>
 * <p>
 * Several test categories are covered: manual sensor control, 3A control,
 * manual ISP control and other per-frame control and synchronization.
 * </p>
 */
public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
    private static final String TAG = "CaptureRequestTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final int NUM_FRAMES_VERIFIED = 15;
    private static final int NUM_FACE_DETECTION_FRAMES_VERIFIED = 60;
    /** 30ms exposure time must be supported by full capability devices. */
    private static final long DEFAULT_EXP_TIME_NS = 30000000L;
    private static final int DEFAULT_SENSITIVITY = 100;
    private static final int RGGB_COLOR_CHANNEL_COUNT = 4;
    private static final int MAX_SHADING_MAP_SIZE = 64 * 64 * RGGB_COLOR_CHANNEL_COUNT;
    private static final int MIN_SHADING_MAP_SIZE = 1 * 1 * RGGB_COLOR_CHANNEL_COUNT;
    private static final long IGNORE_REQUESTED_EXPOSURE_TIME_CHECK = -1L;
    private static final long EXPOSURE_TIME_BOUNDARY_50HZ_NS = 10000000L; // 10ms
    private static final long EXPOSURE_TIME_BOUNDARY_60HZ_NS = 8333333L; // 8.3ms, Approximation.
    private static final long EXPOSURE_TIME_ERROR_MARGIN_NS = 100000L; // 100us, Approximation.
    private static final int SENSITIVITY_ERROR_MARGIN = 10; // 10
    private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
    private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 16;
    private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
    private static final int NUM_RESULTS_WAIT_TIMEOUT = 100;
    private static final int NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY = 8;
    private static final int NUM_TEST_FOCUS_DISTANCES = 10;
    // 5 percent error margin for calibrated device
    private static final float FOCUS_DISTANCE_ERROR_PERCENT_CALIBRATED = 0.05f;
    // 25 percent error margin for uncalibrated device
    private static final float FOCUS_DISTANCE_ERROR_PERCENT_UNCALIBRATED = 0.25f;
    // 10 percent error margin for approximate device
    private static final float FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE = 0.10f;
    private static final int ANTI_FLICKERING_50HZ = 1;
    private static final int ANTI_FLICKERING_60HZ = 2;

    // 5 percent error margin for resulting crop regions
    private static final float CROP_REGION_ERROR_PERCENT_DELTA = 0.05f;
    // 1 percent error margin for centering the crop region
    private static final float CROP_REGION_ERROR_PERCENT_CENTERED = 0.01f;

    // Linear tone mapping curve example.
    private static final float[] TONEMAP_CURVE_LINEAR = {0, 0, 1.0f, 1.0f};
    // Standard sRGB tone mapping, per IEC 61966-2-1:1999, with 16 control points.
    private static final float[] TONEMAP_CURVE_SRGB = {
            0.0000f, 0.0000f, 0.0667f, 0.2864f, 0.1333f, 0.4007f, 0.2000f, 0.4845f,
            0.2667f, 0.5532f, 0.3333f, 0.6125f, 0.4000f, 0.6652f, 0.4667f, 0.7130f,
            0.5333f, 0.7569f, 0.6000f, 0.7977f, 0.6667f, 0.8360f, 0.7333f, 0.8721f,
            0.8000f, 0.9063f, 0.8667f, 0.9389f, 0.9333f, 0.9701f, 1.0000f, 1.0000f
    };
    private final Rational ZERO_R = new Rational(0, 1);
    private final Rational ONE_R = new Rational(1, 1);

    private final int NUM_ALGORITHMS = 3; // AE, AWB and AF
    private final int INDEX_ALGORITHM_AE = 0;
    private final int INDEX_ALGORITHM_AWB = 1;
    private final int INDEX_ALGORITHM_AF = 2;

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

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

    /**
     * Test black level lock when exposure value change.
     * <p>
     * When {@link CaptureRequest#BLACK_LEVEL_LOCK} is true in a request, the
     * camera device should lock the black level. When the exposure values are changed,
     * the camera may require reset black level Since changes to certain capture
     * parameters (such as exposure time) may require resetting of black level
     * compensation. However, the black level must remain locked after exposure
     * value changes (when requests have lock ON).
     * </p>
     */
    public void testBlackLevelLock() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                if (!mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    continue;
                }

                SimpleCaptureCallback listener = new SimpleCaptureCallback();
                CaptureRequest.Builder requestBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

                // Start with default manual exposure time, with black level being locked.
                requestBuilder.set(CaptureRequest.BLACK_LEVEL_LOCK, true);
                changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS, DEFAULT_SENSITIVITY);

                Size previewSz =
                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);

                startPreview(requestBuilder, previewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                // No lock OFF state is allowed as the exposure is not changed.
                verifyBlackLevelLockResults(listener, NUM_FRAMES_VERIFIED, /*maxLockOffCnt*/0);

                // Double the exposure time and gain, with black level still being locked.
                changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS * 2, DEFAULT_SENSITIVITY * 2);
                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, previewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                // Allow at most one lock OFF state as the exposure is changed once.
                verifyBlackLevelLockResults(listener, NUM_FRAMES_VERIFIED, /*maxLockOffCnt*/1);

                stopPreview();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Basic lens shading map request test.
     * <p>
     * When {@link CaptureRequest#SHADING_MODE} is set to OFF, no lens shading correction will
     * be applied by the camera device, and an identity lens shading map data
     * will be provided if {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE} is ON.
     * </p>
     * <p>
     * When {@link CaptureRequest#SHADING_MODE} is set to other modes, lens shading correction
     * will be applied by the camera device. The lens shading map data can be
     * requested by setting {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE} to ON.
     * </p>
     */
    public void testLensShadingMap() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                if (!mStaticInfo.isManualLensShadingMapSupported()) {
                    continue;
                }

                SimpleCaptureCallback listener = new SimpleCaptureCallback();
                CaptureRequest.Builder requestBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

                // Shading map mode OFF, lensShadingMapMode ON, camera device
                // should output unity maps.
                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_OFF);
                requestBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
                        STATISTICS_LENS_SHADING_MAP_MODE_ON);

                Size previewSz =
                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);

                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, previewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_OFF);

                // Shading map mode FAST, lensShadingMapMode ON, camera device
                // should output valid maps.
                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_FAST);

                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, previewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                // Allow at most one lock OFF state as the exposure is changed once.
                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_FAST);

                // Shading map mode HIGH_QUALITY, lensShadingMapMode ON, camera device
                // should output valid maps.
                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_HIGH_QUALITY);

                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, previewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_HIGH_QUALITY);

                stopPreview();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE} control.
     * <p>
     * Test all available anti-banding modes, check if the exposure time adjustment is
     * correct.
     * </p>
     */
    public void testAntiBandingModes() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                // Without manual sensor control, exposure time cannot be verified
                if (!mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    return;
                }

                int[] modes = mStaticInfo.getAeAvailableAntiBandingModesChecked();

                Size previewSz =
                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);

                for (int mode : modes) {
                    antiBandingTestByMode(previewSz, mode);
                }
            } finally {
                closeDevice();
            }
        }

    }

    /**
     * Test AE mode and lock.
     *
     * <p>
     * For AE lock, when it is locked, exposure parameters shouldn't be changed.
     * For AE modes, each mode should satisfy the per frame controls defined in
     * API specifications.
     * </p>
     */
    public void testAeModeAndLock() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.

                // Update preview surface with given size for all sub-tests.
                updatePreviewSurface(maxPreviewSz);

                // Test aeMode and lock
                int[] aeModes = mStaticInfo.getAeAvailableModesChecked();
                for (int mode : aeModes) {
                    aeModeAndLockTestByMode(mode);
                }
            } finally {
                closeDevice();
            }
        }
    }

    /** Test {@link CaptureRequest#FLASH_MODE} control.
     * <p>
     * For each {@link CaptureRequest#FLASH_MODE} mode, test the flash control
     * and {@link CaptureResult#FLASH_STATE} result.
     * </p>
     */
    public void testFlashControl() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                SimpleCaptureCallback listener = new SimpleCaptureCallback();
                CaptureRequest.Builder requestBuilder =
                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

                Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.

                startPreview(requestBuilder, maxPreviewSz, listener);

                // Flash control can only be used when the AE mode is ON or OFF.
                flashTestByAeMode(listener, CaptureRequest.CONTROL_AE_MODE_ON);

                // LEGACY won't support AE mode OFF
                boolean aeOffModeSupported = false;
                for (int aeMode : mStaticInfo.getAeAvailableModesChecked()) {
                    if (aeMode == CaptureRequest.CONTROL_AE_MODE_OFF) {
                        aeOffModeSupported = true;
                    }
                }
                if (aeOffModeSupported) {
                    flashTestByAeMode(listener, CaptureRequest.CONTROL_AE_MODE_OFF);
                }

                stopPreview();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test face detection modes and results.
     */
    public void testFaceDetection() throws Exception {
        for (int i = 0; i < mCameraIds.length; i++) {
            try {
                openDevice(mCameraIds[i]);

                faceDetectionTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test tone map modes and controls.
     */
    public void testToneMapControl() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (!mStaticInfo.isManualToneMapSupported()) {
                    Log.i(TAG, "Camera " + id +
                            " doesn't support tone mapping controls, skipping test");
                    continue;
                }
                toneMapTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test color correction modes and controls.
     */
    public void testColorCorrectionControl() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (!mStaticInfo.isManualColorCorrectionSupported()) {
                    Log.i(TAG, "Camera " + id +
                            " doesn't support color correction controls, skipping test");
                    continue;
                }
                colorCorrectionTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    public void testEdgeModeControl() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (!mStaticInfo.isEdgeModeControlSupported()) {
                    Log.i(TAG, "Camera " + id +
                            " doesn't support EDGE_MODE controls, skipping test");
                    continue;
                }

                edgeModesTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test focus distance control.
     */
    public void testFocusDistanceControl() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (!mStaticInfo.hasFocuser()) {
                    Log.i(TAG, "Camera " + id + " has no focuser, skipping test");
                    continue;
                }

                if (!mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    Log.i(TAG, "Camera " + id +
                            " does not support MANUAL_SENSOR, skipping test");
                    continue;
                }

                focusDistanceTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    public void testNoiseReductionModeControl() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                if (!mStaticInfo.isNoiseReductionModeControlSupported()) {
                    Log.i(TAG, "Camera " + id +
                            " doesn't support noise reduction mode, skipping test");
                    continue;
                }

                noiseReductionModeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test AWB lock control.
     *
     * <p>The color correction gain and transform shouldn't be changed when AWB is locked.</p>
     */
    public void testAwbModeAndLock() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                awbModeAndLockTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test different AF modes.
     */
    public void testAfModes() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                afModeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test video and optical stabilizations.
     */
    public void testCameraStabilizations() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);
                List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();
                if (!(keys.contains(
                        CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES) ||
                        keys.contains(
                                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION))) {
                    Log.i(TAG, "Camera " + id + " doesn't support any stabilization modes");
                    continue;
                }

                stabilizationTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test digitalZoom (center wise and non-center wise), validate the returned crop regions.
     * The max preview size is used for each camera.
     */
    public void testDigitalZoom() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                Size maxPreviewSize = mOrderedPreviewSizes.get(0);
                digitalZoomTestByCamera(maxPreviewSize);
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test digital zoom and all preview size combinations.
     * TODO: this and above test should all be moved to preview test class.
     */
    public void testDigitalZoomPreviewCombinations() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                digitalZoomPreviewCombinationTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test scene mode controls.
     */
    public void testSceneModes() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                sceneModeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    /**
     * Test effect mode controls.
     */
    public void testEffectModes() throws Exception {
        for (String id : mCameraIds) {
            try {
                openDevice(id);

                effectModeTestByCamera();
            } finally {
                closeDevice();
            }
        }
    }

    // TODO: add 3A state machine test.

    private void noiseReductionModeTestByCamera() throws Exception {
        Size maxPrevSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        int[] availableModes = mStaticInfo.getAvailableNoiseReductionModesChecked();
        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        startPreview(requestBuilder, maxPrevSize, resultListener);

        for (int mode : availableModes) {
            requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, mode);
            resultListener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            verifyCaptureResultForKey(CaptureResult.NOISE_REDUCTION_MODE, mode,
                    resultListener, NUM_FRAMES_VERIFIED);

            // Test that OFF and FAST mode should not slow down the frame rate.
            if (mode == CaptureRequest.NOISE_REDUCTION_MODE_OFF ||
                    mode == CaptureRequest.NOISE_REDUCTION_MODE_FAST) {
                verifyFpsNotSlowDown(requestBuilder, NUM_FRAMES_VERIFIED);
            }
        }

        stopPreview();
    }

    private void focusDistanceTestByCamera() throws Exception {
        Size maxPrevSize = mOrderedPreviewSizes.get(0);
        float[] testDistances = getFocusDistanceTestValuesInOrder();
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        startPreview(requestBuilder, maxPrevSize, resultListener);

        CaptureRequest request;
        float[] resultDistances = new float[testDistances.length];
        for (int i = 0; i < testDistances.length; i++) {
            requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, testDistances[i]);
            request = requestBuilder.build();
            resultListener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(request, resultListener, mHandler);
            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
            resultDistances[i] = verifyFocusDistanceControl(testDistances[i], request,
                    resultListener);
            if (VERBOSE) {
                Log.v(TAG, "Capture request focus distance: " + testDistances[i] + " result: "
                        + resultDistances[i]);
            }
        }

        // Verify the monotonicity
        mCollector.checkArrayMonotonicityAndNotAllEqual(CameraTestUtils.toObject(resultDistances),
                /*ascendingOrder*/true);

        if (mStaticInfo.getCharacteristics().getKeys().
                contains(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE)) {

            // Test hyperfocal distance optionally
            float hyperFocalDistance = mStaticInfo.getHyperfocalDistanceChecked();
            if (hyperFocalDistance > 0) {
                requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, hyperFocalDistance);
                request = requestBuilder.build();
                resultListener = new SimpleCaptureCallback();
                mSession.setRepeatingRequest(request, resultListener, mHandler);
                waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

                // Then wait for the lens.state to be stationary.
                waitForResultValue(resultListener, CaptureResult.LENS_STATE,
                        CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
                // Need get reasonably accurate value.
                CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
                Float focusDistance = getValueNotNull(result, CaptureResult.LENS_FOCUS_DISTANCE);
                float errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_UNCALIBRATED;
                int calibrationStatus = mStaticInfo.getFocusDistanceCalibrationChecked();
                if (calibrationStatus ==
                        CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED) {
                    errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_CALIBRATED;
                } else if (calibrationStatus ==
                        CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE) {
                    errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE;
                }
                mCollector.expectInRange("Focus distance for hyper focal should be close enough to" +
                                "requested value", focusDistance,
                        hyperFocalDistance * (1.0f - errorMargin),
                        hyperFocalDistance * (1.0f + errorMargin)
                );
            }
        }
    }

    /**
     * Verify focus distance control.
     *
     * @param distance The focus distance requested
     * @param request The capture request to control the manual focus distance
     * @param resultListener The capture listener to recieve capture result callbacks
     * @return the result focus distance
     */
    private float verifyFocusDistanceControl(float distance, CaptureRequest request,
            SimpleCaptureCallback resultListener) {
        // Need make sure the result corresponding to the request is back, then check.
        CaptureResult result =
                resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
        // Then wait for the lens.state to be stationary.
        waitForResultValue(resultListener, CaptureResult.LENS_STATE,
                CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
        // Then check the focus distance.
        result = resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
        Float resultDistance = getValueNotNull(result, CaptureResult.LENS_FOCUS_DISTANCE);
        if (mStaticInfo.getFocusDistanceCalibrationChecked() ==
                CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED) {
            // TODO: what's more to test for CALIBRATED devices?
        }

        float minValue = 0;
        float maxValue = mStaticInfo.getMinimumFocusDistanceChecked();
        mCollector.expectInRange("Result focus distance is out of range",
                resultDistance, minValue, maxValue);

        return resultDistance;
    }

    /**
     * Verify edge mode control results.
     */
    private void edgeModesTestByCamera() throws Exception {
        Size maxPrevSize = mOrderedPreviewSizes.get(0);
        int[] edgeModes = mStaticInfo.getAvailableEdgeModesChecked();
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        startPreview(requestBuilder, maxPrevSize, resultListener);

        for (int mode : edgeModes) {
            requestBuilder.set(CaptureRequest.EDGE_MODE, mode);
            resultListener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            verifyCaptureResultForKey(CaptureResult.EDGE_MODE, mode, resultListener,
                    NUM_FRAMES_VERIFIED);

            // Test that OFF and FAST mode should not slow down the frame rate.
            if (mode == CaptureRequest.EDGE_MODE_OFF ||
                    mode == CaptureRequest.EDGE_MODE_FAST) {
                verifyFpsNotSlowDown(requestBuilder, NUM_FRAMES_VERIFIED);
            }
        }

        stopPreview();
    }

    /**
     * Test color correction controls.
     *
     * <p>Test different color correction modes. For TRANSFORM_MATRIX, only test
     * the unit gain and identity transform.</p>
     */
    private void colorCorrectionTestByCamera() throws Exception {
        CaptureRequest request;
        CaptureResult result;
        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
        updatePreviewSurface(maxPreviewSz);
        CaptureRequest.Builder manualRequestBuilder = createRequestForPreview();
        CaptureRequest.Builder previewRequestBuilder = createRequestForPreview();
        SimpleCaptureCallback listener = new SimpleCaptureCallback();

        startPreview(previewRequestBuilder, maxPreviewSz, listener);

        // Default preview result should give valid color correction metadata.
        result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        validateColorCorrectionResult(result,
                previewRequestBuilder.get(CaptureRequest.COLOR_CORRECTION_MODE));

        // TRANSFORM_MATRIX mode
        // Only test unit gain and identity transform
        RggbChannelVector UNIT_GAIN = new RggbChannelVector(1.0f, 1.0f, 1.0f, 1.0f);

        ColorSpaceTransform IDENTITY_TRANSFORM = new ColorSpaceTransform(
            new Rational[] {
                ONE_R, ZERO_R, ZERO_R,
                ZERO_R, ONE_R, ZERO_R,
                ZERO_R, ZERO_R, ONE_R
            });

        int colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX;
        manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS, UNIT_GAIN);
        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM, IDENTITY_TRANSFORM);
        request = manualRequestBuilder.build();
        mSession.capture(request, listener, mHandler);
        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
        RggbChannelVector gains = result.get(CaptureResult.COLOR_CORRECTION_GAINS);
        ColorSpaceTransform transform = result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM);
        validateColorCorrectionResult(result, colorCorrectionMode);
        mCollector.expectEquals("control mode result/request mismatch",
                CaptureResult.CONTROL_MODE_OFF, result.get(CaptureResult.CONTROL_MODE));
        mCollector.expectEquals("Color correction gain result/request mismatch",
                UNIT_GAIN, gains);
        mCollector.expectEquals("Color correction gain result/request mismatch",
                IDENTITY_TRANSFORM, transform);

        // FAST mode
        colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_FAST;
        manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
        request = manualRequestBuilder.build();
        mSession.capture(request, listener, mHandler);
        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
        validateColorCorrectionResult(result, colorCorrectionMode);
        mCollector.expectEquals("control mode result/request mismatch",
                CaptureResult.CONTROL_MODE_AUTO, result.get(CaptureResult.CONTROL_MODE));

        // HIGH_QUALITY mode
        colorCorrectionMode = CaptureRequest.COLOR_CORRECTION_MODE_HIGH_QUALITY;
        manualRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, colorCorrectionMode);
        request = manualRequestBuilder.build();
        mSession.capture(request, listener, mHandler);
        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
        validateColorCorrectionResult(result, colorCorrectionMode);
        mCollector.expectEquals("control mode result/request mismatch",
                CaptureResult.CONTROL_MODE_AUTO, result.get(CaptureResult.CONTROL_MODE));
    }

    private void validateColorCorrectionResult(CaptureResult result, int colorCorrectionMode) {
        final RggbChannelVector ZERO_GAINS = new RggbChannelVector(0, 0, 0, 0);
        final int TRANSFORM_SIZE = 9;
        Rational[] zeroTransform = new Rational[TRANSFORM_SIZE];
        Arrays.fill(zeroTransform, ZERO_R);
        final ColorSpaceTransform ZERO_TRANSFORM = new ColorSpaceTransform(zeroTransform);

        RggbChannelVector resultGain;
        if ((resultGain = mCollector.expectKeyValueNotNull(result,
                CaptureResult.COLOR_CORRECTION_GAINS)) != null) {
            mCollector.expectKeyValueNotEquals(result,
                    CaptureResult.COLOR_CORRECTION_GAINS, ZERO_GAINS);
        }

        ColorSpaceTransform resultTransform;
        if ((resultTransform = mCollector.expectKeyValueNotNull(result,
                CaptureResult.COLOR_CORRECTION_TRANSFORM)) != null) {
            mCollector.expectKeyValueNotEquals(result,
                    CaptureResult.COLOR_CORRECTION_TRANSFORM, ZERO_TRANSFORM);
        }

        mCollector.expectEquals("color correction mode result/request mismatch",
                colorCorrectionMode, result.get(CaptureResult.COLOR_CORRECTION_MODE));
    }

    /**
     * Test flash mode control by AE mode.
     * <p>
     * Only allow AE mode ON or OFF, because other AE mode could run into conflict with
     * flash manual control. This function expects the camera to already have an active
     * repeating request and be sending results to the listener.
     * </p>
     *
     * @param listener The Capture listener that is used to wait for capture result
     * @param aeMode The AE mode for flash to test with
     */
    private void flashTestByAeMode(SimpleCaptureCallback listener, int aeMode) throws Exception {
        CaptureResult result;
        final int NUM_FLASH_REQUESTS_TESTED = 10;
        CaptureRequest.Builder requestBuilder = createRequestForPreview();

        if (aeMode == CaptureRequest.CONTROL_AE_MODE_ON) {
            requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, aeMode);
        } else if (aeMode == CaptureRequest.CONTROL_AE_MODE_OFF) {
            changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS, DEFAULT_SENSITIVITY);
        } else {
            throw new IllegalArgumentException("This test only works when AE mode is ON or OFF");
        }

        mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
        waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

        // For camera that doesn't have flash unit, flash state should always be UNAVAILABLE.
        if (mStaticInfo.getFlashInfoChecked() == false) {
            for (int i = 0; i < NUM_FLASH_REQUESTS_TESTED; i++) {
                result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
                mCollector.expectEquals("No flash unit available, flash state must be UNAVAILABLE"
                        + "for AE mode " + aeMode, CaptureResult.FLASH_STATE_UNAVAILABLE,
                        result.get(CaptureResult.FLASH_STATE));
            }

            return;
        }

        // Test flash SINGLE mode control. Wait for flash state to be READY first.
        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
            waitForResultValue(listener, CaptureResult.FLASH_STATE, CaptureResult.FLASH_STATE_READY,
                    NUM_RESULTS_WAIT_TIMEOUT);
        } // else the settings were already waited on earlier

        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
        CaptureRequest flashSinglerequest = requestBuilder.build();

        int flashModeSingleRequests = captureRequestsSynchronized(
                flashSinglerequest, listener, mHandler);
        waitForNumResults(listener, flashModeSingleRequests - 1);
        result = listener.getCaptureResultForRequest(flashSinglerequest, NUM_RESULTS_WAIT_TIMEOUT);
        // Result mode must be SINGLE, state must be FIRED.
        mCollector.expectEquals("Flash mode result must be SINGLE",
                CaptureResult.FLASH_MODE_SINGLE, result.get(CaptureResult.FLASH_MODE));
        mCollector.expectEquals("Flash state result must be FIRED",
                CaptureResult.FLASH_STATE_FIRED, result.get(CaptureResult.FLASH_STATE));

        // Test flash TORCH mode control.
        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
        CaptureRequest torchRequest = requestBuilder.build();

        int flashModeTorchRequests = captureRequestsSynchronized(torchRequest,
                NUM_FLASH_REQUESTS_TESTED, listener, mHandler);
        waitForNumResults(listener, flashModeTorchRequests - NUM_FLASH_REQUESTS_TESTED);

        // Verify the results
        for (int i = 0; i < NUM_FLASH_REQUESTS_TESTED; i++) {
            result = listener.getCaptureResultForRequest(torchRequest,
                    NUM_RESULTS_WAIT_TIMEOUT);

            // Result mode must be TORCH, state must be FIRED
            mCollector.expectEquals("Flash mode result must be TORCH",
                    CaptureResult.FLASH_MODE_TORCH, result.get(CaptureResult.FLASH_MODE));
            mCollector.expectEquals("Flash state result must be FIRED",
                    CaptureResult.FLASH_STATE_FIRED, result.get(CaptureResult.FLASH_STATE));
        }

        // Test flash OFF mode control
        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
        CaptureRequest flashOffrequest = requestBuilder.build();

        int flashModeOffRequests = captureRequestsSynchronized(flashOffrequest, listener, mHandler);
        waitForNumResults(listener, flashModeOffRequests - 1);
        result = listener.getCaptureResultForRequest(flashOffrequest, NUM_RESULTS_WAIT_TIMEOUT);
        mCollector.expectEquals("Flash mode result must be OFF", CaptureResult.FLASH_MODE_OFF,
                result.get(CaptureResult.FLASH_MODE));
    }

    private void verifyAntiBandingMode(SimpleCaptureCallback listener, int numFramesVerified,
            int mode, boolean isAeManual, long requestExpTime) throws Exception {
        // Skip the first a couple of frames as antibanding may not be fully up yet.
        final int NUM_FRAMES_SKIPPED = 5;
        for (int i = 0; i < NUM_FRAMES_SKIPPED; i++) {
            listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        }

        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            Long resultExpTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
            assertNotNull("Exposure time shouldn't be null", resultExpTime);
            Integer flicker = result.get(CaptureResult.STATISTICS_SCENE_FLICKER);
            // Scene flicker result should be always available.
            assertNotNull("Scene flicker must not be null", flicker);
            assertTrue("Scene flicker is invalid", flicker >= STATISTICS_SCENE_FLICKER_NONE &&
                    flicker <= STATISTICS_SCENE_FLICKER_60HZ);

            if (isAeManual) {
                // First, round down not up, second, need close enough.
                validateExposureTime(requestExpTime, resultExpTime);
                return;
            }

            long expectedExpTime = resultExpTime; // Default, no exposure adjustment.
            if (mode == CONTROL_AE_ANTIBANDING_MODE_50HZ) {
                // result exposure time must be adjusted by 50Hz illuminant source.
                expectedExpTime =
                        getAntiFlickeringExposureTime(ANTI_FLICKERING_50HZ, resultExpTime);
            } else if (mode == CONTROL_AE_ANTIBANDING_MODE_60HZ) {
                // result exposure time must be adjusted by 60Hz illuminant source.
                expectedExpTime =
                        getAntiFlickeringExposureTime(ANTI_FLICKERING_60HZ, resultExpTime);
            } else if (mode == CONTROL_AE_ANTIBANDING_MODE_AUTO){
                /**
                 * Use STATISTICS_SCENE_FLICKER to tell the illuminant source
                 * and do the exposure adjustment.
                 */
                expectedExpTime = resultExpTime;
                if (flicker == STATISTICS_SCENE_FLICKER_60HZ) {
                    expectedExpTime =
                            getAntiFlickeringExposureTime(ANTI_FLICKERING_60HZ, resultExpTime);
                } else if (flicker == STATISTICS_SCENE_FLICKER_50HZ) {
                    expectedExpTime =
                            getAntiFlickeringExposureTime(ANTI_FLICKERING_50HZ, resultExpTime);
                }
            }

            if (Math.abs(resultExpTime - expectedExpTime) > EXPOSURE_TIME_ERROR_MARGIN_NS) {
                mCollector.addMessage(String.format("Result exposure time %dns diverges too much"
                        + " from expected exposure time %dns for mode %d when AE is auto",
                        resultExpTime, expectedExpTime, mode));
            }
        }
    }

    private void antiBandingTestByMode(Size size, int mode)
            throws Exception {
        if(VERBOSE) {
            Log.v(TAG, "Anti-banding test for mode " + mode + " for camera " + mCamera.getId());
        }
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, mode);

        // Test auto AE mode anti-banding behavior
        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
        startPreview(requestBuilder, size, resultListener);
        waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
        verifyAntiBandingMode(resultListener, NUM_FRAMES_VERIFIED, mode, /*isAeManual*/false,
                IGNORE_REQUESTED_EXPOSURE_TIME_CHECK);

        // Test manual AE mode anti-banding behavior
        // 65ms, must be supported by full capability devices.
        final long TEST_MANUAL_EXP_TIME_NS = 65000000L;
        long manualExpTime = mStaticInfo.getExposureClampToRange(TEST_MANUAL_EXP_TIME_NS);
        changeExposure(requestBuilder, manualExpTime);
        resultListener = new SimpleCaptureCallback();
        startPreview(requestBuilder, size, resultListener);
        waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
        verifyAntiBandingMode(resultListener, NUM_FRAMES_VERIFIED, mode, /*isAeManual*/true,
                manualExpTime);

        stopPreview();
    }

    /**
     * Test the all available AE modes and AE lock.
     * <p>
     * For manual AE mode, test iterates through different sensitivities and
     * exposure times, validate the result exposure time correctness. For
     * CONTROL_AE_MODE_ON_ALWAYS_FLASH mode, the AE lock and flash are tested.
     * For the rest of the AUTO mode, AE lock is tested.
     * </p>
     *
     * @param mode
     */
    private void aeModeAndLockTestByMode(int mode)
            throws Exception {
        switch (mode) {
            case CONTROL_AE_MODE_OFF:
                if (mStaticInfo.isCapabilitySupported(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    // Test manual exposure control.
                    aeManualControlTest();
                } else {
                    Log.w(TAG,
                            "aeModeAndLockTestByMode - can't test AE mode OFF without " +
                            "manual sensor control");
                }
                break;
            case CONTROL_AE_MODE_ON:
            case CONTROL_AE_MODE_ON_AUTO_FLASH:
            case CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE:
            case CONTROL_AE_MODE_ON_ALWAYS_FLASH:
                // Test AE lock for above AUTO modes.
                aeAutoModeTestLock(mode);
                break;
            default:
                throw new UnsupportedOperationException("Unhandled AE mode " + mode);
        }
    }

    /**
     * Test AE auto modes.
     * <p>
     * Use single request rather than repeating request to test AE lock per frame control.
     * </p>
     */
    private void aeAutoModeTestLock(int mode) throws Exception {
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, mode);
        configurePreviewOutput(requestBuilder);

        final int MAX_NUM_CAPTURES_DURING_LOCK = 5;
        for (int i = 1; i <= MAX_NUM_CAPTURES_DURING_LOCK; i++) {
            autoAeMultipleCapturesThenTestLock(requestBuilder, mode, i);
        }
    }

    /**
     * Issue multiple auto AE captures, then lock AE, validate the AE lock vs.
     * the first capture result after the AE lock. The right AE lock behavior is:
     * When it is locked, it locks to the current exposure value, and all subsequent
     * request with lock ON will have the same exposure value locked.
     */
    private void autoAeMultipleCapturesThenTestLock(
            CaptureRequest.Builder requestBuilder, int aeMode, int numCapturesDuringLock)
            throws Exception {
        if (numCapturesDuringLock < 1) {
            throw new IllegalArgumentException("numCapturesBeforeLock must be no less than 1");
        }
        if (VERBOSE) {
            Log.v(TAG, "Camera " + mCamera.getId() + ": Testing auto AE mode and lock for mode "
                    + aeMode + " with " + numCapturesDuringLock + " captures before lock");
        }

        final int NUM_CAPTURES_BEFORE_LOCK = 2;
        SimpleCaptureCallback listener =  new SimpleCaptureCallback();

        CaptureResult[] resultsDuringLock = new CaptureResult[numCapturesDuringLock];

        // Reset the AE lock to OFF, since we are reusing this builder many times
        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);

        // Just send several captures with auto AE, lock off.
        CaptureRequest request = requestBuilder.build();
        for (int i = 0; i < NUM_CAPTURES_BEFORE_LOCK; i++) {
            mSession.capture(request, listener, mHandler);
        }
        waitForNumResults(listener, NUM_CAPTURES_BEFORE_LOCK);

        // Then fire several capture to lock the AE.
        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);

        int requestCount = captureRequestsSynchronized(
                requestBuilder.build(), numCapturesDuringLock, listener, mHandler);

        int[] sensitivities = new int[numCapturesDuringLock];
        long[] expTimes = new long[numCapturesDuringLock];
        Arrays.fill(sensitivities, -1);
        Arrays.fill(expTimes, -1L);

        // Get the AE lock on result and validate the exposure values.
        waitForNumResults(listener, requestCount - numCapturesDuringLock);
        for (int i = 0; i < resultsDuringLock.length; i++) {
            resultsDuringLock[i] = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        }

        for (int i = 0; i < numCapturesDuringLock; i++) {
            mCollector.expectKeyValueEquals(
                    resultsDuringLock[i], CaptureResult.CONTROL_AE_LOCK, true);
        }

        // Can't read manual sensor/exposure settings without manual sensor
        if (mStaticInfo.isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
            int sensitivityLocked =
                    getValueNotNull(resultsDuringLock[0], CaptureResult.SENSOR_SENSITIVITY);
            long expTimeLocked =
                    getValueNotNull(resultsDuringLock[0], CaptureResult.SENSOR_EXPOSURE_TIME);
            for (int i = 1; i < resultsDuringLock.length; i++) {
                mCollector.expectKeyValueEquals(
                        resultsDuringLock[i], CaptureResult.SENSOR_EXPOSURE_TIME, expTimeLocked);
                mCollector.expectKeyValueEquals(
                        resultsDuringLock[i], CaptureResult.SENSOR_SENSITIVITY, sensitivityLocked);
            }
        }
    }

    /**
     * Iterate through exposure times and sensitivities for manual AE control.
     * <p>
     * Use single request rather than repeating request to test manual exposure
     * value change per frame control.
     * </p>
     */
    private void aeManualControlTest()
            throws Exception {
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
        configurePreviewOutput(requestBuilder);
        SimpleCaptureCallback listener =  new SimpleCaptureCallback();

        long[] expTimes = getExposureTimeTestValues();
        int[] sensitivities = getSensitivityTestValues();
        // Submit single request at a time, then verify the result.
        for (int i = 0; i < expTimes.length; i++) {
            for (int j = 0; j < sensitivities.length; j++) {
                if (VERBOSE) {
                    Log.v(TAG, "Camera " + mCamera.getId() + ": Testing sensitivity "
                            + sensitivities[j] + ", exposure time " + expTimes[i] + "ns");
                }

                changeExposure(requestBuilder, expTimes[i], sensitivities[j]);
                mSession.capture(requestBuilder.build(), listener, mHandler);

                CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
                long resultExpTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
                int resultSensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
                validateExposureTime(expTimes[i], resultExpTime);
                validateSensitivity(sensitivities[j], resultSensitivity);
                validateFrameDurationForCapture(result);
            }
        }
        // TODO: Add another case to test where we can submit all requests, then wait for
        // results, which will hide the pipeline latency. this is not only faster, but also
        // test high speed per frame control and synchronization.
    }


    /**
     * Verify black level lock control.
     */
    private void verifyBlackLevelLockResults(SimpleCaptureCallback listener, int numFramesVerified,
            int maxLockOffCnt) throws Exception {
        int noLockCnt = 0;
        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            Boolean blackLevelLock = result.get(CaptureResult.BLACK_LEVEL_LOCK);
            assertNotNull("Black level lock result shouldn't be null", blackLevelLock);

            // Count the lock == false result, which could possibly occur at most once.
            if (blackLevelLock == false) {
                noLockCnt++;
            }

            if(VERBOSE) {
                Log.v(TAG, "Black level lock result: " + blackLevelLock);
            }
        }
        assertTrue("Black level lock OFF occurs " + noLockCnt + " times,  expect at most "
                + maxLockOffCnt + " for camera " + mCamera.getId(), noLockCnt <= maxLockOffCnt);
    }

    /**
     * Verify shading map for different shading modes.
     */
    private void verifyShadingMap(SimpleCaptureCallback listener, int numFramesVerified,
            int shadingMode) throws Exception {

        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            mCollector.expectEquals("Shading mode result doesn't match request",
                    shadingMode, result.get(CaptureResult.SHADING_MODE));
            LensShadingMap mapObj = result.get(
                    CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
            assertNotNull("Map object must not be null", mapObj);
            int numElementsInMap = mapObj.getGainFactorCount();
            float[] map = new float[numElementsInMap];
            mapObj.copyGainFactors(map, /*offset*/0);
            assertNotNull("Map must not be null", map);
            assertFalse(String.format(
                    "Map size %d should be less than %d", numElementsInMap, MAX_SHADING_MAP_SIZE),
                    numElementsInMap >= MAX_SHADING_MAP_SIZE);
            assertFalse(String.format("Map size %d should be no less than %d", numElementsInMap,
                    MIN_SHADING_MAP_SIZE), numElementsInMap < MIN_SHADING_MAP_SIZE);

            if (shadingMode == CaptureRequest.SHADING_MODE_FAST ||
                    shadingMode == CaptureRequest.SHADING_MODE_HIGH_QUALITY) {
                // shading mode is FAST or HIGH_QUALITY, expect to receive a map with all
                // elements >= 1.0f

                int badValueCnt = 0;
                // Detect the bad values of the map data.
                for (int j = 0; j < numElementsInMap; j++) {
                    if (Float.isNaN(map[j]) || map[j] < 1.0f) {
                        badValueCnt++;
                    }
                }
                assertEquals("Number of value in the map is " + badValueCnt + " out of "
                        + numElementsInMap, /*expected*/0, /*actual*/badValueCnt);
            } else if (shadingMode == CaptureRequest.SHADING_MODE_OFF) {
                float[] unityMap = new float[numElementsInMap];
                Arrays.fill(unityMap, 1.0f);
                // shading mode is OFF, expect to receive a unity map.
                assertTrue("Result map " + Arrays.toString(map) + " must be an unity map",
                        Arrays.equals(unityMap, map));
            }
        }
    }

    /**
     * Test face detection for a camera.
     */
    private void faceDetectionTestByCamera() throws Exception {
        int[] faceDetectModes = mStaticInfo.getAvailableFaceDetectModesChecked();

        SimpleCaptureCallback listener;
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
        for (int mode : faceDetectModes) {
            requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, mode);
            if (VERBOSE) {
                Log.v(TAG, "Start testing face detection mode " + mode);
            }

            // Create a new listener for each run to avoid the results from one run spill
            // into another run.
            listener = new SimpleCaptureCallback();
            startPreview(requestBuilder, maxPreviewSz, listener);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
            verifyFaceDetectionResults(listener, NUM_FACE_DETECTION_FRAMES_VERIFIED, mode);
        }

        stopPreview();
    }

    /**
     * Verify face detection results for different face detection modes.
     *
     * @param listener The listener to get capture result
     * @param numFramesVerified Number of results to be verified
     * @param faceDetectionMode Face detection mode to be verified against
     */
    private void verifyFaceDetectionResults(SimpleCaptureCallback listener, int numFramesVerified,
            int faceDetectionMode) {
        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            mCollector.expectEquals("Result face detection mode should match the request",
                    faceDetectionMode, result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE));

            Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
            List<Integer> faceIds = new ArrayList<Integer>(faces.length);
            List<Integer> faceScores = new ArrayList<Integer>(faces.length);
            if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_OFF) {
                mCollector.expectEquals("Number of detection faces should always 0 for OFF mode",
                        0, faces.length);
            } else if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE) {
                for (Face face : faces) {
                    mCollector.expectNotNull("Face rectangle shouldn't be null", face.getBounds());
                    faceScores.add(face.getScore());
                    mCollector.expectTrue("Face id is expected to be -1 for SIMPLE mode",
                            face.getId() == Face.ID_UNSUPPORTED);
                }
            } else if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) {
                if (VERBOSE) {
                    Log.v(TAG, "Number of faces detected: " + faces.length);
                }

                for (Face face : faces) {
                    Rect faceBound;
                    boolean faceRectAvailable =  mCollector.expectTrue("Face rectangle "
                            + "shouldn't be null", face.getBounds() != null);
                    if (!faceRectAvailable) {
                        continue;
                    }
                    faceBound = face.getBounds();

                    faceScores.add(face.getScore());
                    faceIds.add(face.getId());

                    mCollector.expectTrue("Face id is shouldn't be -1 for FULL mode",
                            face.getId() != Face.ID_UNSUPPORTED);
                    boolean leftEyeAvailable =
                            mCollector.expectTrue("Left eye position shouldn't be null",
                                    face.getLeftEyePosition() != null);
                    boolean rightEyeAvailable =
                            mCollector.expectTrue("Right eye position shouldn't be null",
                                    face.getRightEyePosition() != null);
                    boolean mouthAvailable =
                            mCollector.expectTrue("Mouth position shouldn't be null",
                            face.getMouthPosition() != null);
                    // Eyes/mouth position should be inside of the face rect.
                    if (leftEyeAvailable) {
                        Point leftEye = face.getLeftEyePosition();
                        mCollector.expectTrue("Left eye " + leftEye + "should be"
                                + "inside of face rect " + faceBound,
                                faceBound.contains(leftEye.x, leftEye.y));
                    }
                    if (rightEyeAvailable) {
                        Point rightEye = face.getRightEyePosition();
                        mCollector.expectTrue("Right eye " + rightEye + "should be"
                                + "inside of face rect " + faceBound,
                                faceBound.contains(rightEye.x, rightEye.y));
                    }
                    if (mouthAvailable) {
                        Point mouth = face.getMouthPosition();
                        mCollector.expectTrue("Mouth " + mouth +  " should be inside of"
                                + " face rect " + faceBound,
                                faceBound.contains(mouth.x, mouth.y));
                    }
                }
            }
            mCollector.expectValuesInRange("Face scores are invalid", faceIds,
                    Face.SCORE_MIN, Face.SCORE_MAX);
            mCollector.expectValuesUnique("Face ids are invalid", faceIds);
        }
    }

    /**
     * Test tone map mode and result by camera
     */
    private void toneMapTestByCamera() throws Exception {
        if (!mStaticInfo.isManualToneMapSupported()) {
            return;
        }

        SimpleCaptureCallback listener;
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.

        int[] toneMapModes = mStaticInfo.getAvailableToneMapModesChecked();
        for (int mode : toneMapModes) {
            requestBuilder.set(CaptureRequest.TONEMAP_MODE, mode);
            if (VERBOSE) {
                Log.v(TAG, "Testing tonemap mode " + mode);
            }

            if (mode == CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE) {
                TonemapCurve tcLinear = new TonemapCurve(
                        TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR);
                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcLinear);
                // Create a new listener for each run to avoid the results from one run spill
                // into another run.
                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, maxPreviewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
                        TONEMAP_CURVE_LINEAR);

                TonemapCurve tcSrgb = new TonemapCurve(
                        TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB);
                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcSrgb);
                // Create a new listener for each run to avoid the results from one run spill
                // into another run.
                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, maxPreviewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
                        TONEMAP_CURVE_SRGB);
            } else {
                // Create a new listener for each run to avoid the results from one run spill
                // into another run.
                listener = new SimpleCaptureCallback();
                startPreview(requestBuilder, maxPreviewSz, listener);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
                        /*inputToneCurve*/null);
            }
        }

        stopPreview();
    }

    /**
     * Verify tonemap results.
     * <p>
     * Assumes R,G,B channels use the same tone curve
     * </p>
     *
     * @param listener The capture listener used to get the capture results
     * @param numFramesVerified Number of results to be verified
     * @param tonemapMode Tonemap mode to verify
     * @param inputToneCurve Tonemap curve used by all 3 channels, ignored when
     * map mode is not CONTRAST_CURVE.
     */
    private void verifyToneMapModeResults(SimpleCaptureCallback listener, int numFramesVerified,
            int tonemapMode, float[] inputToneCurve) {
        final int MIN_TONEMAP_CURVE_POINTS = 2;
        final Float ZERO = new Float(0);
        final Float ONE = new Float(1.0f);

        int maxCurvePoints = mStaticInfo.getMaxTonemapCurvePointChecked();
        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            mCollector.expectEquals("Capture result tonemap mode should match request", tonemapMode,
                    result.get(CaptureResult.TONEMAP_MODE));
            TonemapCurve tc = getValueNotNull(result, CaptureResult.TONEMAP_CURVE);
            int pointCount = tc.getPointCount(TonemapCurve.CHANNEL_RED);
            float[] mapRed = new float[pointCount * TonemapCurve.POINT_SIZE];
            pointCount = tc.getPointCount(TonemapCurve.CHANNEL_GREEN);
            float[] mapGreen = new float[pointCount * TonemapCurve.POINT_SIZE];
            pointCount = tc.getPointCount(TonemapCurve.CHANNEL_BLUE);
            float[] mapBlue = new float[pointCount * TonemapCurve.POINT_SIZE];
            tc.copyColorCurve(TonemapCurve.CHANNEL_RED, mapRed, 0);
            tc.copyColorCurve(TonemapCurve.CHANNEL_GREEN, mapGreen, 0);
            tc.copyColorCurve(TonemapCurve.CHANNEL_BLUE, mapBlue, 0);
            if (tonemapMode == CaptureResult.TONEMAP_MODE_CONTRAST_CURVE) {
                /**
                 * TODO: need figure out a good way to measure the difference
                 * between request and result, as they may have different array
                 * size.
                 */
            }

            // Tonemap curve result availability and basic sanity check for all modes.
            mCollector.expectValuesInRange("Tonemap curve red values are out of range",
                    CameraTestUtils.toObject(mapRed), /*min*/ZERO, /*max*/ONE);
            mCollector.expectInRange("Tonemap curve red length is out of range",
                    mapRed.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
            mCollector.expectValuesInRange("Tonemap curve green values are out of range",
                    CameraTestUtils.toObject(mapGreen), /*min*/ZERO, /*max*/ONE);
            mCollector.expectInRange("Tonemap curve green length is out of range",
                    mapGreen.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
            mCollector.expectValuesInRange("Tonemap curve blue values are out of range",
                    CameraTestUtils.toObject(mapBlue), /*min*/ZERO, /*max*/ONE);
            mCollector.expectInRange("Tonemap curve blue length is out of range",
                    mapBlue.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
        }
    }

    /**
     * Test awb mode control.
     * <p>
     * Test each supported AWB mode, verify the AWB mode in capture result
     * matches request. When AWB is locked, the color correction gains and
     * transform should remain unchanged.
     * </p>
     */
    private void awbModeAndLockTestByCamera() throws Exception {
        int[] awbModes = mStaticInfo.getAwbAvailableModesChecked();
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        startPreview(requestBuilder, maxPreviewSize, /*listener*/null);

        for (int mode : awbModes) {
            SimpleCaptureCallback listener;
            requestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, mode);
            listener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            // Verify AWB mode in capture result.
            verifyCaptureResultForKey(CaptureResult.CONTROL_AWB_MODE, mode, listener,
                    NUM_FRAMES_VERIFIED);

            if (mode == CameraMetadata.CONTROL_AWB_MODE_AUTO) {
                // Verify color correction transform and gains stay unchanged after a lock.
                requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
                listener = new SimpleCaptureCallback();
                mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

                if (mStaticInfo.areKeysAvailable(CaptureResult.CONTROL_AWB_STATE)) {
                    waitForResultValue(listener, CaptureResult.CONTROL_AWB_STATE,
                            CaptureResult.CONTROL_AWB_STATE_LOCKED, NUM_RESULTS_WAIT_TIMEOUT);
                }

            }
            verifyAwbCaptureResultUnchanged(listener, NUM_FRAMES_VERIFIED);
        }
    }

    private void verifyAwbCaptureResultUnchanged(SimpleCaptureCallback listener,
            int numFramesVerified) {
        // Skip check if cc gains/transform/mode are not available
        if (!mStaticInfo.areKeysAvailable(
                CaptureResult.COLOR_CORRECTION_GAINS,
                CaptureResult.COLOR_CORRECTION_TRANSFORM,
                CaptureResult.COLOR_CORRECTION_MODE)) {
            return;
        }

        CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
        RggbChannelVector lockedGains =
                getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
        ColorSpaceTransform lockedTransform =
                getValueNotNull(result, CaptureResult.COLOR_CORRECTION_TRANSFORM);

        for (int i = 0; i < numFramesVerified; i++) {
            result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            // Color correction mode check is skipped here, as it is checked in colorCorrectionTest.
            validateColorCorrectionResult(result, result.get(CaptureResult.COLOR_CORRECTION_MODE));

            RggbChannelVector gains = getValueNotNull(result, CaptureResult.COLOR_CORRECTION_GAINS);
            ColorSpaceTransform transform =
                    getValueNotNull(result, CaptureResult.COLOR_CORRECTION_TRANSFORM);
            mCollector.expectEquals("Color correction gains should remain unchanged after awb lock",
                    lockedGains, gains);
            mCollector.expectEquals("Color correction transform should remain unchanged after"
                    + " awb lock", lockedTransform, transform);
        }
    }

    /**
     * Test AF mode control.
     * <p>
     * Test all supported AF modes, verify the AF mode in capture result matches
     * request. When AF mode is one of the CONTROL_AF_MODE_CONTINUOUS_* mode,
     * verify if the AF can converge to PASSIVE_FOCUSED or PASSIVE_UNFOCUSED
     * state within certain amount of frames.
     * </p>
     */
    private void afModeTestByCamera() throws Exception {
        int[] afModes = mStaticInfo.getAfAvailableModesChecked();
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        startPreview(requestBuilder, maxPreviewSize, /*listener*/null);

        for (int mode : afModes) {
            SimpleCaptureCallback listener;
            requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mode);
            listener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            // Verify AF mode in capture result.
            verifyCaptureResultForKey(CaptureResult.CONTROL_AF_MODE, mode, listener,
                    NUM_FRAMES_VERIFIED);

            // Verify AF can finish a scan for CONTROL_AF_MODE_CONTINUOUS_* modes.
            // In LEGACY mode, a transition to one of the continuous AF modes does not necessarily
            // result in a passive AF call if the camera has already been focused, and the scene has
            // not changed enough to trigger an AF pass.  Skip this constraint for LEGACY.
            if (mStaticInfo.isHardwareLevelLimitedOrBetter() &&
                    (mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE ||
                    mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
                List<Integer> afStateList = new ArrayList<Integer>();
                afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED);
                afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED);
                waitForAnyResultValue(listener, CaptureResult.CONTROL_AF_STATE, afStateList,
                        NUM_RESULTS_WAIT_TIMEOUT);
            }
        }
    }

    /**
     * Test video and optical stabilizations if they are supported by a given camera.
     */
    private void stabilizationTestByCamera() throws Exception {
        // video stabilization test.
        List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();

        int[] videoStabModes = (keys.contains(CameraCharacteristics.
                CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)) ?
                mStaticInfo.getAvailableVideoStabilizationModesChecked() : new int[0];
        int[] opticalStabModes = (keys.contains(
                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) ?
                mStaticInfo.getAvailableOpticalStabilizationChecked() : new int[0];

        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        SimpleCaptureCallback listener = new SimpleCaptureCallback();
        startPreview(requestBuilder, maxPreviewSize, listener);

        for (int mode : videoStabModes) {
            listener = new SimpleCaptureCallback();
            requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
            verifyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE, mode,
                    listener, NUM_FRAMES_VERIFIED);
        }

        for (int mode : opticalStabModes) {
            listener = new SimpleCaptureCallback();
            requestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, mode);
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
            verifyCaptureResultForKey(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE, mode,
                    listener, NUM_FRAMES_VERIFIED);
        }

        stopPreview();
    }

    private void digitalZoomTestByCamera(Size previewSize) throws Exception {
        final int ZOOM_STEPS = 15;
        final PointF[] TEST_ZOOM_CENTERS;

        final int croppingType = mStaticInfo.getScalerCroppingTypeChecked();
        if (croppingType ==
                CameraCharacteristics.SCALER_CROPPING_TYPE_FREEFORM) {
            TEST_ZOOM_CENTERS = new PointF[] {
                new PointF(0.5f, 0.5f),   // Center point
                new PointF(0.25f, 0.25f), // top left corner zoom, minimal zoom: 2x
                new PointF(0.75f, 0.25f), // top right corner zoom, minimal zoom: 2x
                new PointF(0.25f, 0.75f), // bottom left corner zoom, minimal zoom: 2x
                new PointF(0.75f, 0.75f), // bottom right corner zoom, minimal zoom: 2x
            };

            if (VERBOSE) {
                Log.v(TAG, "Testing zoom with CROPPING_TYPE = FREEFORM");
            }
        } else {
            // CENTER_ONLY
            TEST_ZOOM_CENTERS = new PointF[] {
                    new PointF(0.5f, 0.5f),   // Center point
            };

            if (VERBOSE) {
                Log.v(TAG, "Testing zoom with CROPPING_TYPE = CENTER_ONLY");
            }
        }

        final float maxZoom = mStaticInfo.getAvailableMaxDigitalZoomChecked();
        final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
        Rect[] cropRegions = new Rect[ZOOM_STEPS];
        MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        SimpleCaptureCallback listener = new SimpleCaptureCallback();

        updatePreviewSurface(previewSize);
        configurePreviewOutput(requestBuilder);

        CaptureRequest[] requests = new CaptureRequest[ZOOM_STEPS];

        // Set algorithm regions to full active region
        // TODO: test more different 3A regions
        final MeteringRectangle[] defaultMeteringRect = new MeteringRectangle[] {
                new MeteringRectangle (
                        /*x*/0, /*y*/0, activeArraySize.width(), activeArraySize.height(),
                        /*meteringWeight*/1)
        };

        for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
            update3aRegion(requestBuilder, algo,  defaultMeteringRect);
        }

        final int CAPTURE_SUBMIT_REPEAT;
        {
            int maxLatency = mStaticInfo.getSyncMaxLatency();
            if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
                CAPTURE_SUBMIT_REPEAT = NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY + 1;
            } else {
                CAPTURE_SUBMIT_REPEAT = maxLatency + 1;
            }
        }

        if (VERBOSE) {
            Log.v(TAG, "Testing zoom with CAPTURE_SUBMIT_REPEAT = " + CAPTURE_SUBMIT_REPEAT);
        }

        for (PointF center : TEST_ZOOM_CENTERS) {
            Rect previousCrop = null;

            for (int i = 0; i < ZOOM_STEPS; i++) {
                /*
                 * Submit capture request
                 */
                float zoomFactor = (float) (1.0f + (maxZoom - 1.0) * i / ZOOM_STEPS);
                cropRegions[i] = getCropRegionForZoom(zoomFactor, center, maxZoom, activeArraySize);
                if (VERBOSE) {
                    Log.v(TAG, "Testing Zoom for factor " + zoomFactor + " and center " +
                            center + " The cropRegion is " + cropRegions[i] +
                            " Preview size is " + previewSize);
                }
                requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegions[i]);
                requests[i] = requestBuilder.build();
                for (int j = 0; j < CAPTURE_SUBMIT_REPEAT; ++j) {
                    if (VERBOSE) {
                        Log.v(TAG, "submit crop region " + cropRegions[i]);
                    }
                    mSession.capture(requests[i], listener, mHandler);
                }

                /*
                 * Validate capture result
                 */
                waitForNumResults(listener, CAPTURE_SUBMIT_REPEAT - 1); // Drop first few frames
                CaptureResult result = listener.getCaptureResultForRequest(
                        requests[i], NUM_RESULTS_WAIT_TIMEOUT);
                Rect cropRegion = getValueNotNull(result, CaptureResult.SCALER_CROP_REGION);

                /*
                 * Validate resulting crop regions
                 */
                if (previousCrop != null) {
                    Rect currentCrop = cropRegion;
                    mCollector.expectTrue(String.format(
                            "Crop region should shrink or stay the same " +
                                    "(previous = %s, current = %s)",
                                    previousCrop, currentCrop),
                            previousCrop.equals(currentCrop) ||
                                (previousCrop.width() > currentCrop.width() &&
                                 previousCrop.height() > currentCrop.height()));
                }

                if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
                    mCollector.expectRectsAreSimilar(
                            "Request and result crop region should be similar",
                            cropRegions[i], cropRegion, CROP_REGION_ERROR_PERCENT_DELTA);
                }

                if (croppingType == SCALER_CROPPING_TYPE_CENTER_ONLY) {
                    mCollector.expectRectCentered(
                            "Result crop region should be centered inside the active array",
                            new Size(activeArraySize.width(), activeArraySize.height()),
                            cropRegion, CROP_REGION_ERROR_PERCENT_CENTERED);
                }

                /*
                 * Validate resulting metering regions
                 */

                // Use the actual reported crop region to calculate the resulting metering region
                expectRegions[i] = getExpectedOutputRegion(
                        /*requestRegion*/defaultMeteringRect,
                        /*cropRect*/     cropRegion);

                // Verify Output 3A region is intersection of input 3A region and crop region
                for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
                    validate3aRegion(result, algo, expectRegions[i]);
                }

                previousCrop = cropRegion;
            }

            if (maxZoom > 1.0f) {
                mCollector.expectTrue(
                        String.format("Most zoomed-in crop region should be smaller" +
                                        "than active array w/h" +
                                        "(last crop = %s, active array = %s)",
                                        previousCrop, activeArraySize),
                            (previousCrop.width() < activeArraySize.width() &&
                             previousCrop.height() < activeArraySize.height()));
            }
        }
    }

    private void digitalZoomPreviewCombinationTestByCamera() throws Exception {
        final double ASPECT_RATIO_THRESHOLD = 0.001;
        List<Double> aspectRatiosTested = new ArrayList<Double>();
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        aspectRatiosTested.add((double)(maxPreviewSize.getWidth()) / maxPreviewSize.getHeight());

        for (Size size : mOrderedPreviewSizes) {
            // Max preview size was already tested in testDigitalZoom test. skip it.
            if (size.equals(maxPreviewSize)) {
                continue;
            }

            // Only test the largest size for each aspect ratio.
            double aspectRatio = (double)(size.getWidth()) / size.getHeight();
            if (isAspectRatioContained(aspectRatiosTested, aspectRatio, ASPECT_RATIO_THRESHOLD)) {
                continue;
            }

            if (VERBOSE) {
                Log.v(TAG, "Test preview size " + size.toString() + " digital zoom");
            }

            aspectRatiosTested.add(aspectRatio);
            digitalZoomTestByCamera(size);
        }
    }

    private static boolean isAspectRatioContained(List<Double> aspectRatioList,
            double aspectRatio, double delta) {
        for (Double ratio : aspectRatioList) {
            if (Math.abs(ratio - aspectRatio) < delta) {
                return true;
            }
        }

        return false;
    }

    private void sceneModeTestByCamera() throws Exception {
        int[] sceneModes = mStaticInfo.getAvailableSceneModesChecked();
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        SimpleCaptureCallback listener = new SimpleCaptureCallback();
        requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
        startPreview(requestBuilder, maxPreviewSize, listener);

        for(int mode : sceneModes) {
            requestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, mode);
            listener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            verifyCaptureResultForKey(CaptureResult.CONTROL_SCENE_MODE,
                    mode, listener, NUM_FRAMES_VERIFIED);
            // This also serves as purpose of showing preview for NUM_FRAMES_VERIFIED
            verifyCaptureResultForKey(CaptureResult.CONTROL_MODE,
                    CaptureRequest.CONTROL_MODE_USE_SCENE_MODE, listener, NUM_FRAMES_VERIFIED);
        }
    }

    private void effectModeTestByCamera() throws Exception {
        int[] effectModes = mStaticInfo.getAvailableEffectModesChecked();
        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
        CaptureRequest.Builder requestBuilder =
                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
        SimpleCaptureCallback listener = new SimpleCaptureCallback();
        startPreview(requestBuilder, maxPreviewSize, listener);

        for(int mode : effectModes) {
            requestBuilder.set(CaptureRequest.CONTROL_EFFECT_MODE, mode);
            listener = new SimpleCaptureCallback();
            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);

            verifyCaptureResultForKey(CaptureResult.CONTROL_EFFECT_MODE,
                    mode, listener, NUM_FRAMES_VERIFIED);
            // This also serves as purpose of showing preview for NUM_FRAMES_VERIFIED
            verifyCaptureResultForKey(CaptureResult.CONTROL_MODE,
                    CaptureRequest.CONTROL_MODE_AUTO, listener, NUM_FRAMES_VERIFIED);
        }
    }

    //----------------------------------------------------------------
    //---------Below are common functions for all tests.--------------
    //----------------------------------------------------------------

    /**
     * Enable exposure manual control and change exposure and sensitivity and
     * clamp the value into the supported range.
     */
    private void changeExposure(CaptureRequest.Builder requestBuilder,
            long expTime, int sensitivity) {
        // Check if the max analog sensitivity is available and no larger than max sensitivity.
        // The max analog sensitivity is not actually used here. This is only an extra sanity check.
        mStaticInfo.getMaxAnalogSensitivityChecked();

        expTime = mStaticInfo.getExposureClampToRange(expTime);
        sensitivity = mStaticInfo.getSensitivityClampToRange(sensitivity);

        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
        requestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, expTime);
        requestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, sensitivity);
    }
    /**
     * Enable exposure manual control and change exposure time and
     * clamp the value into the supported range.
     *
     * <p>The sensitivity is set to default value.</p>
     */
    private void changeExposure(CaptureRequest.Builder requestBuilder, long expTime) {
        changeExposure(requestBuilder, expTime, DEFAULT_SENSITIVITY);
    }

    /**
     * Get the exposure time array that contains multiple exposure time steps in
     * the exposure time range.
     */
    private long[] getExposureTimeTestValues() {
        long[] testValues = new long[DEFAULT_NUM_EXPOSURE_TIME_STEPS + 1];
        long maxExpTime = mStaticInfo.getExposureMaximumOrDefault(DEFAULT_EXP_TIME_NS);
        long minxExpTime = mStaticInfo.getExposureMinimumOrDefault(DEFAULT_EXP_TIME_NS);

        long range = maxExpTime - minxExpTime;
        double stepSize = range / (double)DEFAULT_NUM_EXPOSURE_TIME_STEPS;
        for (int i = 0; i < testValues.length; i++) {
            testValues[i] = minxExpTime + (long)(stepSize * i);
            testValues[i] = mStaticInfo.getExposureClampToRange(testValues[i]);
        }

        return testValues;
    }

    /**
     * Generate test focus distances in range of [0, minFocusDistance] in increasing order.
     */
    private float[] getFocusDistanceTestValuesInOrder() {
        float[] testValues = new float[NUM_TEST_FOCUS_DISTANCES + 1];
        float minValue = 0;
        float maxValue = mStaticInfo.getMinimumFocusDistanceChecked();

        float range = maxValue - minValue;
        float stepSize = range / NUM_TEST_FOCUS_DISTANCES;
        for (int i = 0; i < testValues.length; i++) {
            testValues[i] = minValue + stepSize * i;
        }

        return testValues;
    }

    /**
     * Get the sensitivity array that contains multiple sensitivity steps in the
     * sensitivity range.
     * <p>
     * Sensitivity number of test values is determined by
     * {@value #DEFAULT_SENSITIVITY_STEP_SIZE} and sensitivity range, and
     * bounded by {@value #DEFAULT_NUM_SENSITIVITY_STEPS}.
     * </p>
     */
    private int[] getSensitivityTestValues() {
        int maxSensitivity = mStaticInfo.getSensitivityMaximumOrDefault(
                DEFAULT_SENSITIVITY);
        int minSensitivity = mStaticInfo.getSensitivityMinimumOrDefault(
                DEFAULT_SENSITIVITY);

        int range = maxSensitivity - minSensitivity;
        int stepSize = DEFAULT_SENSITIVITY_STEP_SIZE;
        int numSteps = range / stepSize;
        // Bound the test steps to avoid supper long test.
        if (numSteps > DEFAULT_NUM_SENSITIVITY_STEPS) {
            numSteps = DEFAULT_NUM_SENSITIVITY_STEPS;
            stepSize = range / numSteps;
        }
        int[] testValues = new int[numSteps + 1];
        for (int i = 0; i < testValues.length; i++) {
            testValues[i] = minSensitivity + stepSize * i;
            testValues[i] = mStaticInfo.getSensitivityClampToRange(testValues[i]);
        }

        return testValues;
    }

    /**
     * Validate the AE manual control exposure time.
     *
     * <p>Exposure should be close enough, and only round down if they are not equal.</p>
     *
     * @param request Request exposure time
     * @param result Result exposure time
     */
    private void validateExposureTime(long request, long result) {
        long expTimeDelta = request - result;
        // First, round down not up, second, need close enough.
        mCollector.expectTrue("Exposture time is invalid for AE manaul control test, request: "
                + request + " result: " + result,
                expTimeDelta < EXPOSURE_TIME_ERROR_MARGIN_NS && expTimeDelta >= 0);
    }

    /**
     * Validate AE manual control sensitivity.
     *
     * @param request Request sensitivity
     * @param result Result sensitivity
     */
    private void validateSensitivity(int request, int result) {
        int sensitivityDelta = request - result;
        // First, round down not up, second, need close enough.
        mCollector.expectTrue("Sensitivity is invalid for AE manaul control test, request: "
                + request + " result: " + result,
                sensitivityDelta < SENSITIVITY_ERROR_MARGIN && sensitivityDelta >= 0);
    }

    /**
     * Validate frame duration for a given capture.
     *
     * <p>Frame duration should be longer than exposure time.</p>
     *
     * @param result The capture result for a given capture
     */
    private void validateFrameDurationForCapture(CaptureResult result) {
        long expTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
        long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
        if (VERBOSE) {
            Log.v(TAG, "frame duration: " + frameDuration + " Exposure time: " + expTime);
        }

        mCollector.expectTrue(String.format("Frame duration (%d) should be longer than exposure"
                + " time (%d) for a given capture", frameDuration, expTime),
                frameDuration >= expTime);

        validatePipelineDepth(result);
    }

    private <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
        T value = result.get(key);
        assertNotNull("Value of Key " + key.getName() + " shouldn't be null", value);
        return value;
    }

    /**
     * Basic verification for the control mode capture result.
     *
     * @param key The capture result key to be verified against
     * @param requestMode The request mode for this result
     * @param listener The capture listener to get capture results
     * @param numFramesVerified The number of capture results to be verified
     */
    private <T> void verifyCaptureResultForKey(CaptureResult.Key<T> key, T requestMode,
            SimpleCaptureCallback listener, int numFramesVerified) {
        for (int i = 0; i < numFramesVerified; i++) {
            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
            validatePipelineDepth(result);
            T resultMode = getValueNotNull(result, key);
            if (VERBOSE) {
                Log.v(TAG, "Expect value: " + requestMode.toString() + " result value: "
                        + resultMode.toString());
            }
            mCollector.expectEquals("Key " + key.getName() + " result should match request",
                    requestMode, resultMode);
        }
    }

    /**
     * Verify if the fps is slow down for given input request with certain
     * controls inside.
     * <p>
     * This method selects a max preview size for each fps range, and then
     * configure the preview stream. Preview is started with the max preview
     * size, and then verify if the result frame duration is in the frame
     * duration range.
     * </p>
     *
     * @param requestBuilder The request builder that contains post-processing
     *            controls that could impact the output frame rate, such as
     *            {@link CaptureRequest.NOISE_REDUCTION_MODE}. The value of
     *            these controls must be set to some values such that the frame
     *            rate is not slow down.
     * @param numFramesVerified The number of frames to be verified
     */
    private void verifyFpsNotSlowDown(CaptureRequest.Builder requestBuilder,
            int numFramesVerified)  throws Exception {
        boolean frameDurationAvailable = true;
        // Allow a few frames for AE to settle on target FPS range
        final int NUM_FRAME_TO_SKIP = 6;
        float frameDurationErrorMargin = FRAME_DURATION_ERROR_MARGIN;
        if (!mStaticInfo.areKeysAvailable(CaptureResult.SENSOR_FRAME_DURATION)) {
            frameDurationAvailable = false;
            // Allow a larger error margin (1.5%) for timestamps
            frameDurationErrorMargin = 0.015f;
        }

        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
        boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
        Range<Integer> fpsRange;
        SimpleCaptureCallback resultListener;

        for (int i = 0; i < fpsRanges.length; i += 1) {
            fpsRange = fpsRanges[i];
            Size previewSz = getMaxPreviewSizeForFpsRange(fpsRange);
            // If unable to find a preview size, then log the failure, and skip this run.
            if (previewSz == null) {
                if (mStaticInfo.isCapabilitySupported(
                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
                    mCollector.addMessage(String.format(
                            "Unable to find a preview size supporting given fps range %s",
                            fpsRange));
                }
                continue;
            }

            if (VERBOSE) {
                Log.v(TAG, String.format("Test fps range %s for preview size %s",
                        fpsRange, previewSz.toString()));
            }
            requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
            // Turn off auto antibanding to avoid exposure time and frame duration interference
            // from antibanding algorithm.
            if (antiBandingOffIsSupported) {
                requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
                        CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
            } else {
                // The device doesn't implement the OFF mode, test continues. It need make sure
                // that the antibanding algorithm doesn't slow down the fps.
                Log.i(TAG, "OFF antibanding mode is not supported, the camera device output must" +
                        " not slow down the frame rate regardless of its current antibanding" +
                        " mode");
            }

            resultListener = new SimpleCaptureCallback();
            startPreview(requestBuilder, previewSz, resultListener);
            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
            // Wait several more frames for AE to settle on target FPS range
            waitForNumResults(resultListener, NUM_FRAME_TO_SKIP);

            long[] frameDurationRange = new long[]{
                    (long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
            long captureTime = 0, prevCaptureTime = 0;
            for (int j = 0; j < numFramesVerified; j++) {
                long frameDuration = frameDurationRange[0];
                CaptureResult result =
                        resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
                validatePipelineDepth(result);
                if (frameDurationAvailable) {
                    frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
                } else {
                    // if frame duration is not available, check timestamp instead
                    captureTime = getValueNotNull(result, CaptureResult.SENSOR_TIMESTAMP);
                    if (j > 0) {
                        frameDuration = captureTime - prevCaptureTime;
                    }
                    prevCaptureTime = captureTime;
                }
                mCollector.expectInRange(
                        "Frame duration must be in the range of " +
                                Arrays.toString(frameDurationRange),
                        frameDuration,
                        (long) (frameDurationRange[0] * (1 - frameDurationErrorMargin)),
                        (long) (frameDurationRange[1] * (1 + frameDurationErrorMargin)));
            }
        }

        mSession.stopRepeating();
    }

    /**
     * Validate the pipeline depth result.
     *
     * @param result The capture result to get pipeline depth data
     */
    private void validatePipelineDepth(CaptureResult result) {
        final byte MIN_PIPELINE_DEPTH = 1;
        byte maxPipelineDepth = mStaticInfo.getPipelineMaxDepthChecked();
        Byte pipelineDepth = getValueNotNull(result, CaptureResult.REQUEST_PIPELINE_DEPTH);
        mCollector.expectInRange(String.format("Pipeline depth must be in the range of [%d, %d]",
                MIN_PIPELINE_DEPTH, maxPipelineDepth), pipelineDepth, MIN_PIPELINE_DEPTH,
                maxPipelineDepth);
    }

    /**
     * Calculate the anti-flickering corrected exposure time.
     * <p>
     * If the input exposure time is very short (shorter than flickering
     * boundary), which indicate the scene is bright and very likely at outdoor
     * environment, skip the correction, as it doesn't make much sense by doing so.
     * </p>
     * <p>
     * For long exposure time (larger than the flickering boundary), find the
     * exposure time that is closest to the flickering boundary.
     * </p>
     *
     * @param flickeringMode The flickering mode
     * @param exposureTime The input exposureTime to be corrected
     * @return anti-flickering corrected exposure time
     */
    private long getAntiFlickeringExposureTime(int flickeringMode, long exposureTime) {
        if (flickeringMode != ANTI_FLICKERING_50HZ && flickeringMode != ANTI_FLICKERING_60HZ) {
            throw new IllegalArgumentException("Input anti-flickering mode must be 50 or 60Hz");
        }
        long flickeringBoundary = EXPOSURE_TIME_BOUNDARY_50HZ_NS;
        if (flickeringMode == ANTI_FLICKERING_60HZ) {
            flickeringBoundary = EXPOSURE_TIME_BOUNDARY_60HZ_NS;
        }

        if (exposureTime <= flickeringBoundary) {
            return exposureTime;
        }

        // Find the closest anti-flickering corrected exposure time
        long correctedExpTime = exposureTime + (flickeringBoundary / 2);
        correctedExpTime = correctedExpTime - (correctedExpTime % flickeringBoundary);
        return correctedExpTime;
    }

    /**
     * Update one 3A region in capture request builder if that region is supported. Do nothing
     * if the specified 3A region is not supported by camera device.
     * @param requestBuilder The request to be updated
     * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
     * @param regions The 3A regions to be set
     */
    private void update3aRegion(
            CaptureRequest.Builder requestBuilder, int algoIdx, MeteringRectangle[] regions)
    {
        int maxRegions;
        CaptureRequest.Key<MeteringRectangle[]> key;

        if (regions == null || regions.length == 0) {
            throw new IllegalArgumentException("Invalid input 3A region!");
        }

        switch (algoIdx) {
            case INDEX_ALGORITHM_AE:
                maxRegions = mStaticInfo.getAeMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AE_REGIONS;
                break;
            case INDEX_ALGORITHM_AWB:
                maxRegions = mStaticInfo.getAwbMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AWB_REGIONS;
                break;
            case INDEX_ALGORITHM_AF:
                maxRegions = mStaticInfo.getAfMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AF_REGIONS;
                break;
            default:
                throw new IllegalArgumentException("Unknown 3A Algorithm!");
        }

        if (maxRegions >= regions.length) {
            requestBuilder.set(key, regions);
        }
    }

    /**
     * Validate one 3A region in capture result equals to expected region if that region is
     * supported. Do nothing if the specified 3A region is not supported by camera device.
     * @param result The capture result to be validated
     * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
     * @param expectRegions The 3A regions expected in capture result
     */
    private void validate3aRegion(
            CaptureResult result, int algoIdx, MeteringRectangle[] expectRegions)
    {
        int maxRegions;
        CaptureResult.Key<MeteringRectangle[]> key;
        MeteringRectangle[] actualRegion;

        switch (algoIdx) {
            case INDEX_ALGORITHM_AE:
                maxRegions = mStaticInfo.getAeMaxRegionsChecked();
                key = CaptureResult.CONTROL_AE_REGIONS;
                break;
            case INDEX_ALGORITHM_AWB:
                maxRegions = mStaticInfo.getAwbMaxRegionsChecked();
                key = CaptureResult.CONTROL_AWB_REGIONS;
                break;
            case INDEX_ALGORITHM_AF:
                maxRegions = mStaticInfo.getAfMaxRegionsChecked();
                key = CaptureResult.CONTROL_AF_REGIONS;
                break;
            default:
                throw new IllegalArgumentException("Unknown 3A Algorithm!");
        }

        if (maxRegions > 0)
        {
            actualRegion = getValueNotNull(result, key);
            mCollector.expectEquals(
                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                    " does not match actual one: " + Arrays.toString(actualRegion),
                    expectRegions, actualRegion);
        }
    }
}
