/*
 * Copyright (C) 2008 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.cts;

import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.Area;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Face;
import android.hardware.Camera.FaceDetectionListener;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.ExifInterface;
import android.media.MediaRecorder;
import android.os.ConditionVariable;
import android.os.Environment;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
import android.test.MoreAsserts;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.SurfaceHolder;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * This test case must run with hardware. It can't be tested in emulator
 */
@LargeTest
public class CameraTest extends ActivityInstrumentationTestCase2<CameraStubActivity> {
    private static String TAG = "CameraTest";
    private static final String PACKAGE = "com.android.cts.stub";
    private static final boolean LOGV = false;
    private final String JPEG_PATH = Environment.getExternalStorageDirectory().getPath() +
            "/test.jpg";
    private byte[] mJpegData;

    private static final int PREVIEW_CALLBACK_NOT_RECEIVED = 0;
    private static final int PREVIEW_CALLBACK_RECEIVED = 1;
    private static final int PREVIEW_CALLBACK_DATA_NULL = 2;
    private static final int PREVIEW_CALLBACK_INVALID_FRAME_SIZE = 3;
    private int mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;

    private boolean mShutterCallbackResult = false;
    private boolean mRawPictureCallbackResult = false;
    private boolean mJpegPictureCallbackResult = false;
    private static final int NO_ERROR = -1;
    private int mCameraErrorCode = NO_ERROR;
    private boolean mAutoFocusSucceeded = false;

    private static final int WAIT_FOR_COMMAND_TO_COMPLETE = 5000;  // Milliseconds.
    private static final int WAIT_FOR_FOCUS_TO_COMPLETE = 5000;
    private static final int WAIT_FOR_SNAPSHOT_TO_COMPLETE = 5000;

    private static final int FOCUS_AREA = 0;
    private static final int METERING_AREA = 1;

    private static final int AUTOEXPOSURE_LOCK = 0;
    private static final int AUTOWHITEBALANCE_LOCK = 1;

    private PreviewCallback mPreviewCallback = new PreviewCallback();
    private TestShutterCallback mShutterCallback = new TestShutterCallback();
    private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
    private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback();
    private TestErrorCallback mErrorCallback = new TestErrorCallback();
    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
    private AutoFocusMoveCallback mAutoFocusMoveCallback = new AutoFocusMoveCallback();

    private Looper mLooper = null;
    private final ConditionVariable mPreviewDone = new ConditionVariable();
    private final ConditionVariable mFocusDone = new ConditionVariable();
    private final ConditionVariable mSnapshotDone = new ConditionVariable();

    Camera mCamera;

    public CameraTest() {
        super(PACKAGE, CameraStubActivity.class);
        if (LOGV) Log.v(TAG, "Camera Constructor");
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        // to start CameraStubActivity.
        getActivity();
    }

    @Override
    protected void tearDown() throws Exception {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
        super.tearDown();
    }

    /*
     * Initializes the message looper so that the Camera object can
     * receive the callback messages.
     */
    private void initializeMessageLooper(final int cameraId) throws IOException {
        final ConditionVariable startDone = new ConditionVariable();
        new Thread() {
            @Override
            public void run() {
                Log.v(TAG, "start loopRun");
                // Set up a looper to be used by camera.
                Looper.prepare();
                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();
                try {
                    mCamera = Camera.open(cameraId);
                    mCamera.setErrorCallback(mErrorCallback);
                } catch (RuntimeException e) {
                    Log.e(TAG, "Fail to open camera." + e);
                }
                Log.v(TAG, "camera is opened");
                startDone.open();
                Looper.loop(); // Blocks forever until Looper.quit() is called.
                if (LOGV) Log.v(TAG, "initializeMessageLooper: quit.");
            }
        }.start();

        Log.v(TAG, "start waiting for looper");
        if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
            Log.v(TAG, "initializeMessageLooper: start timeout");
            fail("initializeMessageLooper: start timeout");
        }
        assertNotNull("Fail to open camera.", mCamera);
        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
    }

    /*
     * Terminates the message looper thread.
     */
    private void terminateMessageLooper() throws Exception {
        mLooper.quit();
        // Looper.quit() is asynchronous. The looper may still has some
        // preview callbacks in the queue after quit is called. The preview
        // callback still uses the camera object (setHasPreviewCallback).
        // After camera is released, RuntimeException will be thrown from
        // the method. So we need to join the looper thread here.
        mLooper.getThread().join();
        mCamera.release();
        mCamera = null;
        assertEquals("Got camera error callback.", NO_ERROR, mCameraErrorCode);
    }

    // Align 'x' to 'to', which should be a power of 2
    private static int align(int x, int to) {
        return (x + (to-1)) & ~(to - 1);
    }
    private static int calculateBufferSize(int width, int height,
                                           int format, int bpp) {

        if (LOGV) {
            Log.v(TAG, "calculateBufferSize: w=" + width + ",h=" + height
            + ",f=" + format + ",bpp=" + bpp);
        }

        if (format == ImageFormat.YV12) {
            /*
            http://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
            */

            int stride = align(width, 16);

            int y_size = stride * height;
            int c_stride = align(stride/2, 16);
            int c_size = c_stride * height/2;
            int size = y_size + c_size * 2;

            if (LOGV) {
                Log.v(TAG, "calculateBufferSize: YV12 size= " + size);
            }

            return size;

        }
        else {
            return width * height * bpp / 8;
        }
    }

    //Implement the previewCallback
    private final class PreviewCallback
            implements android.hardware.Camera.PreviewCallback {
        public void onPreviewFrame(byte [] data, Camera camera) {
            if (data == null) {
                mPreviewCallbackResult = PREVIEW_CALLBACK_DATA_NULL;
                mPreviewDone.open();
                return;
            }
            Size size = camera.getParameters().getPreviewSize();
            int format = camera.getParameters().getPreviewFormat();
            int bitsPerPixel = ImageFormat.getBitsPerPixel(format);
            if (calculateBufferSize(size.width, size.height,
                    format, bitsPerPixel) != data.length) {
                Log.e(TAG, "Invalid frame size " + data.length + ". width=" + size.width
                        + ". height=" + size.height + ". bitsPerPixel=" + bitsPerPixel);
                mPreviewCallbackResult = PREVIEW_CALLBACK_INVALID_FRAME_SIZE;
                mPreviewDone.open();
                return;
            }
            mPreviewCallbackResult = PREVIEW_CALLBACK_RECEIVED;
            mCamera.stopPreview();
            if (LOGV) Log.v(TAG, "notify the preview callback");
            mPreviewDone.open();
            if (LOGV) Log.v(TAG, "Preview callback stop");
        }
    }

    //Implement the shutterCallback
    private final class TestShutterCallback implements ShutterCallback {
        public void onShutter() {
            mShutterCallbackResult = true;
            if (LOGV) Log.v(TAG, "onShutter called");
        }
    }

    //Implement the RawPictureCallback
    private final class RawPictureCallback implements PictureCallback {
        public void onPictureTaken(byte [] rawData, Camera camera) {
            mRawPictureCallbackResult = true;
            if (LOGV) Log.v(TAG, "RawPictureCallback callback");
        }
    }

    // Implement the JpegPictureCallback
    private final class JpegPictureCallback implements PictureCallback {
        public void onPictureTaken(byte[] rawData, Camera camera) {
            try {
                mJpegData = rawData;
                if (rawData != null) {
                    // try to store the picture on the SD card
                    File rawoutput = new File(JPEG_PATH);
                    FileOutputStream outStream = new FileOutputStream(rawoutput);
                    outStream.write(rawData);
                    outStream.close();
                    mJpegPictureCallbackResult = true;

                    if (LOGV) {
                        Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawData.length);
                    }
                } else {
                    mJpegPictureCallbackResult = false;
                }
                mSnapshotDone.open();
                if (LOGV) Log.v(TAG, "Jpeg Picture callback");
            } catch (IOException e) {
                // no need to fail here; callback worked fine
                Log.w(TAG, "Error writing picture to sd card.");
            }
        }
    }

    // Implement the ErrorCallback
    private final class TestErrorCallback implements ErrorCallback {
        public void onError(int error, Camera camera) {
            Log.e(TAG, "Got camera error=" + error);
            mCameraErrorCode = error;
        }
    }

    private final class AutoFocusCallback
            implements android.hardware.Camera.AutoFocusCallback {
        public void onAutoFocus(boolean success, Camera camera) {
            mAutoFocusSucceeded = success;
            Log.v(TAG, "AutoFocusCallback success=" + success);
            mFocusDone.open();
        }
    }

    private final class AutoFocusMoveCallback
            implements android.hardware.Camera.AutoFocusMoveCallback {
        @Override
        public void onAutoFocusMoving(boolean start, Camera camera) {
        }
    }

    private void waitForPreviewDone() {
        if (LOGV) Log.v(TAG, "Wait for preview callback");
        if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
            // timeout could be expected or unexpected. The caller will decide.
            Log.v(TAG, "waitForPreviewDone: timeout");
        }
        mPreviewDone.close();
    }

    private boolean waitForFocusDone() {
        boolean result = mFocusDone.block(WAIT_FOR_FOCUS_TO_COMPLETE);
        if (!result) {
            // timeout could be expected or unexpected. The caller will decide.
            Log.v(TAG, "waitForFocusDone: timeout");
        }
        mFocusDone.close();
        return result;
    }

    private void waitForSnapshotDone() {
        if (!mSnapshotDone.block(WAIT_FOR_SNAPSHOT_TO_COMPLETE)) {
            // timeout could be expected or unexpected. The caller will decide.
            Log.v(TAG, "waitForSnapshotDone: timeout");
        }
        mSnapshotDone.close();
    }

    private void checkPreviewCallback() throws Exception {
        if (LOGV) Log.v(TAG, "check preview callback");
        mCamera.startPreview();
        waitForPreviewDone();
        mCamera.setPreviewCallback(null);
    }

    /*
     * Test case 1: Take a picture and verify all the callback
     * functions are called properly.
     */
    @UiThreadTest
    public void testTakePicture() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            mCamera.startPreview();
            subtestTakePictureByCamera(false, 0, 0);
            terminateMessageLooper();
        }
    }

    private void subtestTakePictureByCamera(boolean isVideoSnapshot,
            int videoWidth, int videoHeight) throws Exception {
        int videoSnapshotMinArea =
                videoWidth * videoHeight; // Temporary until new API definitions

        Size pictureSize = mCamera.getParameters().getPictureSize();
        mCamera.autoFocus(mAutoFocusCallback);
        assertTrue(waitForFocusDone());
        mJpegData = null;
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        assertTrue("Shutter callback not received", mShutterCallbackResult);
        assertTrue("Raw picture callback not received", mRawPictureCallbackResult);
        assertTrue("Jpeg picture callback not recieved", mJpegPictureCallbackResult);
        assertNotNull(mJpegData);
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions);
        if (!isVideoSnapshot) {
            assertEquals(pictureSize.width, bmpOptions.outWidth);
            assertEquals(pictureSize.height, bmpOptions.outHeight);
        } else {
            int realArea = bmpOptions.outWidth * bmpOptions.outHeight;
            if (LOGV) Log.v(TAG, "Video snapshot is " +
                    bmpOptions.outWidth + " x " + bmpOptions.outHeight +
                    ", video size is " + videoWidth + " x " + videoHeight);
            assertTrue ("Video snapshot too small! Expected at least " +
                    videoWidth + " x " + videoHeight + " (" +
                    videoSnapshotMinArea/1000000. + " MP)",
                    realArea >= videoSnapshotMinArea);
        }
    }

    @UiThreadTest
    public void testPreviewCallback() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewCallbackByCamera(id);
        }
    }

    private void testPreviewCallbackByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        mCamera.setPreviewCallback(mPreviewCallback);
        checkPreviewCallback();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);

        mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
        initializeMessageLooper(cameraId);
        checkPreviewCallback();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_NOT_RECEIVED, mPreviewCallbackResult);

        // Test all preview sizes.
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();
        for (Size size: parameters.getSupportedPreviewSizes()) {
            mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
            mCamera.setPreviewCallback(mPreviewCallback);
            parameters.setPreviewSize(size.width, size.height);
            mCamera.setParameters(parameters);
            assertEquals(size, mCamera.getParameters().getPreviewSize());
            checkPreviewCallback();
            assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);
            try {
                // Wait for a while to throw away the remaining preview frames.
                Thread.sleep(1000);
            } catch(Exception e) {
                // ignore
            }
            mPreviewDone.close();
        }
        terminateMessageLooper();
    }

    @UiThreadTest
    public void testSetOneShotPreviewCallback() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testSetOneShotPreviewCallbackByCamera(id);
        }
    }

    private void testSetOneShotPreviewCallbackByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
        checkPreviewCallback();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);

        mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
        initializeMessageLooper(cameraId);
        checkPreviewCallback();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_NOT_RECEIVED, mPreviewCallbackResult);
    }

    @UiThreadTest
    public void testSetPreviewDisplay() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testSetPreviewDisplayByCamera(id);
        }
    }

    private void testSetPreviewDisplayByCamera(int cameraId) throws Exception {
        SurfaceHolder holder = getActivity().getSurfaceView().getHolder();
        initializeMessageLooper(cameraId);

        // Check the order: startPreview->setPreviewDisplay.
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
        mCamera.startPreview();
        mCamera.setPreviewDisplay(holder);
        waitForPreviewDone();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);

        // Check the order: setPreviewDisplay->startPreview.
        initializeMessageLooper(cameraId);
        mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
        waitForPreviewDone();
        mCamera.stopPreview();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);

        // Check the order: setting preview display to null->startPreview->
        // setPreviewDisplay.
        mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
        mCamera.setPreviewDisplay(null);
        mCamera.startPreview();
        mCamera.setPreviewDisplay(holder);
        waitForPreviewDone();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);
    }

    @UiThreadTest
    public void testDisplayOrientation() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testDisplayOrientationByCamera(id);
        }
    }

    private void testDisplayOrientationByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);

        // Check valid arguments.
        mCamera.setDisplayOrientation(0);
        mCamera.setDisplayOrientation(90);
        mCamera.setDisplayOrientation(180);
        mCamera.setDisplayOrientation(270);

        // Check invalid arguments.
        try {
            mCamera.setDisplayOrientation(45);
            fail("Should throw exception for invalid arguments");
        } catch (RuntimeException ex) {
            // expected
        }

        // Start preview.
        mCamera.startPreview();

        // Check setting orientation during preview is allowed.
        mCamera.setDisplayOrientation(90);
        mCamera.setDisplayOrientation(180);
        mCamera.setDisplayOrientation(270);
        mCamera.setDisplayOrientation(00);

        terminateMessageLooper();
    }

    @UiThreadTest
    public void testParameters() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testParametersByCamera(id);
        }
    }

    private void testParametersByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        // we can get parameters just by getxxx method due to the private constructor
        Parameters pSet = mCamera.getParameters();
        assertParameters(pSet);
        terminateMessageLooper();
    }

    // Also test Camera.Parameters
    private void assertParameters(Parameters parameters) {
        // Parameters constants
        final int PICTURE_FORMAT = ImageFormat.JPEG;
        final int PREVIEW_FORMAT = ImageFormat.NV21;

        // Before setting Parameters
        final int origPictureFormat = parameters.getPictureFormat();
        final int origPictureWidth = parameters.getPictureSize().width;
        final int origPictureHeight = parameters.getPictureSize().height;
        final int origPreviewFormat = parameters.getPreviewFormat();
        final int origPreviewWidth = parameters.getPreviewSize().width;
        final int origPreviewHeight = parameters.getPreviewSize().height;
        final int origPreviewFrameRate = parameters.getPreviewFrameRate();

        assertTrue(origPictureWidth > 0);
        assertTrue(origPictureHeight > 0);
        assertTrue(origPreviewWidth > 0);
        assertTrue(origPreviewHeight > 0);
        assertTrue(origPreviewFrameRate > 0);

        // The default preview format must be yuv420 (NV21).
        assertEquals(ImageFormat.NV21, origPreviewFormat);

        // The default picture format must be Jpeg.
        assertEquals(ImageFormat.JPEG, origPictureFormat);

        // If camera supports flash, the default flash mode must be off.
        String flashMode = parameters.getFlashMode();
        assertTrue(flashMode == null || flashMode.equals(parameters.FLASH_MODE_OFF));
        String wb = parameters.getWhiteBalance();
        assertTrue(wb == null || wb.equals(parameters.WHITE_BALANCE_AUTO));
        String effect = parameters.getColorEffect();
        assertTrue(effect == null || effect.equals(parameters.EFFECT_NONE));

        // Some parameters must be supported.
        List<Size> previewSizes = parameters.getSupportedPreviewSizes();
        List<Size> pictureSizes = parameters.getSupportedPictureSizes();
        List<Integer> previewFormats = parameters.getSupportedPreviewFormats();
        List<Integer> pictureFormats = parameters.getSupportedPictureFormats();
        List<Integer> frameRates = parameters.getSupportedPreviewFrameRates();
        List<String> focusModes = parameters.getSupportedFocusModes();
        String focusMode = parameters.getFocusMode();
        float focalLength = parameters.getFocalLength();
        float horizontalViewAngle = parameters.getHorizontalViewAngle();
        float verticalViewAngle = parameters.getVerticalViewAngle();
        int jpegQuality = parameters.getJpegQuality();
        int jpegThumnailQuality = parameters.getJpegThumbnailQuality();
        assertTrue(previewSizes != null && previewSizes.size() != 0);
        assertTrue(pictureSizes != null && pictureSizes.size() != 0);
        assertTrue(previewFormats != null && previewFormats.size() >= 2);
        assertTrue(previewFormats.contains(ImageFormat.NV21));
        assertTrue(previewFormats.contains(ImageFormat.YV12));
        assertTrue(pictureFormats != null && pictureFormats.size() != 0);
        assertTrue(frameRates != null && frameRates.size() != 0);
        assertTrue(focusModes != null && focusModes.size() != 0);
        assertNotNull(focusMode);
        // The default focus mode must be auto if it exists.
        if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) {
            assertEquals(Parameters.FOCUS_MODE_AUTO, focusMode);
        }
        assertTrue(focalLength > 0);
        assertTrue(horizontalViewAngle > 0 && horizontalViewAngle <= 360);
        assertTrue(verticalViewAngle > 0 && verticalViewAngle <= 360);
        Size previewSize = previewSizes.get(0);
        Size pictureSize = pictureSizes.get(0);
        assertTrue(jpegQuality >= 1 && jpegQuality <= 100);
        assertTrue(jpegThumnailQuality >= 1 && jpegThumnailQuality <= 100);

        // If a parameter is supported, both getXXX and getSupportedXXX have to
        // be non null.
        if (parameters.getWhiteBalance() != null) {
            assertNotNull(parameters.getSupportedWhiteBalance());
        }
        if (parameters.getSupportedWhiteBalance() != null) {
            assertNotNull(parameters.getWhiteBalance());
        }
        if (parameters.getColorEffect() != null) {
            assertNotNull(parameters.getSupportedColorEffects());
        }
        if (parameters.getSupportedColorEffects() != null) {
            assertNotNull(parameters.getColorEffect());
        }
        if (parameters.getAntibanding() != null) {
            assertNotNull(parameters.getSupportedAntibanding());
        }
        if (parameters.getSupportedAntibanding() != null) {
            assertNotNull(parameters.getAntibanding());
        }
        if (parameters.getSceneMode() != null) {
            assertNotNull(parameters.getSupportedSceneModes());
        }
        if (parameters.getSupportedSceneModes() != null) {
            assertNotNull(parameters.getSceneMode());
        }
        if (parameters.getFlashMode() != null) {
            assertNotNull(parameters.getSupportedFlashModes());
        }
        if (parameters.getSupportedFlashModes() != null) {
            assertNotNull(parameters.getFlashMode());
        }

        // Check if the sizes value contain invalid characters.
        assertNoLetters(parameters.get("preview-size-values"), "preview-size-values");
        assertNoLetters(parameters.get("picture-size-values"), "picture-size-values");
        assertNoLetters(parameters.get("jpeg-thumbnail-size-values"),
                "jpeg-thumbnail-size-values");

        // Set the parameters.
        parameters.setPictureFormat(PICTURE_FORMAT);
        assertEquals(PICTURE_FORMAT, parameters.getPictureFormat());
        parameters.setPictureSize(pictureSize.width, pictureSize.height);
        assertEquals(pictureSize.width, parameters.getPictureSize().width);
        assertEquals(pictureSize.height, parameters.getPictureSize().height);
        parameters.setPreviewFormat(PREVIEW_FORMAT);
        assertEquals(PREVIEW_FORMAT, parameters.getPreviewFormat());
        parameters.setPreviewFrameRate(frameRates.get(0));
        assertEquals(frameRates.get(0).intValue(), parameters.getPreviewFrameRate());
        parameters.setPreviewSize(previewSize.width, previewSize.height);
        assertEquals(previewSize.width, parameters.getPreviewSize().width);
        assertEquals(previewSize.height, parameters.getPreviewSize().height);

        mCamera.setParameters(parameters);
        Parameters paramActual = mCamera.getParameters();

        assertTrue(isValidPixelFormat(paramActual.getPictureFormat()));
        assertEquals(pictureSize.width, paramActual.getPictureSize().width);
        assertEquals(pictureSize.height, paramActual.getPictureSize().height);
        assertTrue(isValidPixelFormat(paramActual.getPreviewFormat()));
        assertEquals(previewSize.width, paramActual.getPreviewSize().width);
        assertEquals(previewSize.height, paramActual.getPreviewSize().height);
        assertTrue(paramActual.getPreviewFrameRate() > 0);

        checkExposureCompensation(parameters);
        checkPreferredPreviewSizeForVideo(parameters);
    }

    private void checkPreferredPreviewSizeForVideo(Parameters parameters) {
        List<Size> videoSizes = parameters.getSupportedVideoSizes();
        Size preferredPreviewSize = parameters.getPreferredPreviewSizeForVideo();

        // If getSupportedVideoSizes() returns null,
        // getPreferredPreviewSizeForVideo() will return null;
        // otherwise, if getSupportedVideoSizes() does not return null,
        // getPreferredPreviewSizeForVideo() will not return null.
        if (videoSizes == null) {
            assertNull(preferredPreviewSize);
        } else {
            assertNotNull(preferredPreviewSize);
        }

        // If getPreferredPreviewSizeForVideo() returns null,
        // getSupportedVideoSizes() will return null;
        // otherwise, if getPreferredPreviewSizeForVideo() does not return null,
        // getSupportedVideoSizes() will not return null.
        if (preferredPreviewSize == null) {
            assertNull(videoSizes);
        } else {
            assertNotNull(videoSizes);
        }

        if (videoSizes != null) {  // implies: preferredPreviewSize != null
            // If getSupportedVideoSizes() does not return null,
            // the returned list will contain at least one size.
            assertTrue(videoSizes.size() > 0);

            // In addition, getPreferredPreviewSizeForVideo() returns a size
            // that is among the supported preview sizes.
            List<Size> previewSizes = parameters.getSupportedPreviewSizes();
            assertNotNull(previewSizes);
            assertTrue(previewSizes.size() > 0);
            assertTrue(previewSizes.contains(preferredPreviewSize));
        }
    }

    private void checkExposureCompensation(Parameters parameters) {
        assertEquals(0, parameters.getExposureCompensation());
        int max = parameters.getMaxExposureCompensation();
        int min = parameters.getMinExposureCompensation();
        float step = parameters.getExposureCompensationStep();
        if (max == 0 && min == 0) {
            assertEquals(0f, step, 0.000001f);
            return;
        }
        assertTrue(step > 0);
        assertTrue(max >= 0);
        assertTrue(min <= 0);
    }

    private boolean isValidPixelFormat(int format) {
        return (format == ImageFormat.RGB_565) || (format == ImageFormat.NV21)
                || (format == ImageFormat.JPEG) || (format == ImageFormat.YUY2);
    }

    @UiThreadTest
    public void testJpegThumbnailSize() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            testJpegThumbnailSizeByCamera(false, 0, 0);
            terminateMessageLooper();
        }
    }

    private void testJpegThumbnailSizeByCamera(boolean recording,
            int recordingWidth, int recordingHeight) throws Exception {
        // Thumbnail size parameters should have valid values.
        Parameters p = mCamera.getParameters();
        Size size = p.getJpegThumbnailSize();
        assertTrue(size.width > 0 && size.height > 0);
        List<Size> sizes = p.getSupportedJpegThumbnailSizes();
        assertTrue(sizes.size() >= 2);
        assertTrue(sizes.contains(size));
        assertTrue(sizes.contains(mCamera.new Size(0, 0)));

        // Test if the thumbnail size matches the setting.
        if (!recording) mCamera.startPreview();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        assertTrue(mJpegPictureCallbackResult);
        ExifInterface exif = new ExifInterface(JPEG_PATH);
        assertTrue(exif.hasThumbnail());
        byte[] thumb = exif.getThumbnail();
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(thumb, 0, thumb.length, bmpOptions);
        if (!recording) {
            assertEquals(size.width, bmpOptions.outWidth);
            assertEquals(size.height, bmpOptions.outHeight);
        } else {
            assertTrue(bmpOptions.outWidth >= recordingWidth ||
                    bmpOptions.outWidth == size.width);
            assertTrue(bmpOptions.outHeight >= recordingHeight ||
                    bmpOptions.outHeight == size.height);
        }

        // Test no thumbnail case.
        p.setJpegThumbnailSize(0, 0);
        mCamera.setParameters(p);
        Size actual = mCamera.getParameters().getJpegThumbnailSize();
        assertEquals(0, actual.width);
        assertEquals(0, actual.height);
        if (!recording) mCamera.startPreview();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        assertTrue(mJpegPictureCallbackResult);
        exif = new ExifInterface(JPEG_PATH);
        assertFalse(exif.hasThumbnail());
    }

    @UiThreadTest
    public void testJpegExif() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            testJpegExifByCamera(false);
            terminateMessageLooper();
        }
    }

    private void testJpegExifByCamera(boolean recording) throws Exception {
        Camera.Parameters parameters = mCamera.getParameters();
        if (!recording) mCamera.startPreview();
        double focalLength = parameters.getFocalLength();
        Date date = new Date(System.currentTimeMillis());
        String localDatetime = new SimpleDateFormat("yyyy:MM:dd HH:").format(date);

        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();

        // Test various exif tags.
        ExifInterface exif = new ExifInterface(JPEG_PATH);
        assertNotNull(exif.getAttribute(ExifInterface.TAG_MAKE));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_MODEL));
        String datetime = exif.getAttribute(ExifInterface.TAG_DATETIME);
        assertNotNull(datetime);
        // Datetime should be local time.
        assertTrue(datetime.startsWith(localDatetime));
        assertTrue(datetime.length() == 19); // EXIF spec is "YYYY:MM:DD HH:MM:SS".
        checkGpsDataNull(exif);
        double exifFocalLength = exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, -1);
        assertEquals(focalLength, exifFocalLength, 0.001);
        // Test image width and height exif tags. They should match the jpeg.
        assertBitmapAndJpegSizeEqual(mJpegData, exif);

        // Test gps exif tags.
        testGpsExifValues(parameters, 37.736071, -122.441983, 21, 1199145600,
            "GPS NETWORK HYBRID ARE ALL FINE.");
        testGpsExifValues(parameters, 0.736071, 0.441983, 1, 1199145601, "GPS");
        testGpsExifValues(parameters, -89.736071, -179.441983, 100000, 1199145602, "NETWORK");

        // Test gps tags do not exist after calling removeGpsData. Also check if
        // image width and height exif match the jpeg when jpeg rotation is set.
        if (!recording) mCamera.startPreview();
        parameters.removeGpsData();
        parameters.setRotation(90); // For testing image width and height exif.
        mCamera.setParameters(parameters);
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        exif = new ExifInterface(JPEG_PATH);
        checkGpsDataNull(exif);
        assertBitmapAndJpegSizeEqual(mJpegData, exif);
        // Reset the rotation to prevent from affecting other tests.
        parameters.setRotation(0);
        mCamera.setParameters(parameters);
    }

    private void assertBitmapAndJpegSizeEqual(byte[] jpegData, ExifInterface exif) {
        int exifWidth = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0);
        int exifHeight = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0);
        assertTrue(exifWidth != 0 && exifHeight != 0);
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, bmpOptions);
        assertEquals(bmpOptions.outWidth, exifWidth);
        assertEquals(bmpOptions.outHeight, exifHeight);
    }

    private void testGpsExifValues(Parameters parameters, double latitude,
            double longitude, double altitude, long timestamp, String method)
            throws IOException {
        mCamera.startPreview();
        parameters.setGpsLatitude(latitude);
        parameters.setGpsLongitude(longitude);
        parameters.setGpsAltitude(altitude);
        parameters.setGpsTimestamp(timestamp);
        parameters.setGpsProcessingMethod(method);
        mCamera.setParameters(parameters);
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        ExifInterface exif = new ExifInterface(JPEG_PATH);
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
        assertEquals(method, exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD));
        float[] latLong = new float[2];
        assertTrue(exif.getLatLong(latLong));
        assertEquals((float)latitude, latLong[0], 0.0001f);
        assertEquals((float)longitude, latLong[1], 0.0001f);
        assertEquals(altitude, exif.getAltitude(-1), 1);
        assertEquals(timestamp, exif.getGpsDateTime() / 1000);
    }

    private void checkGpsDataNull(ExifInterface exif) {
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD));
    }

    @UiThreadTest
    public void testLockUnlock() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testLockUnlockByCamera(id);
        }
    }

    private void testLockUnlockByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Camera.Parameters parameters = mCamera.getParameters();
        SurfaceHolder surfaceHolder;
        surfaceHolder = getActivity().getSurfaceView().getHolder();
        CamcorderProfile profile = CamcorderProfile.get(cameraId,
                CamcorderProfile.QUALITY_LOW);

        // Set the preview size.
        setPreviewSizeByProfile(parameters, profile);

        mCamera.setParameters(parameters);
        mCamera.setPreviewDisplay(surfaceHolder);
        mCamera.startPreview();
        mCamera.lock();  // Locking again from the same process has no effect.
        try {
            recordVideo(profile, surfaceHolder);
            fail("Recording should not succeed because camera is locked.");
        } catch (Exception e) {
            // expected
        }

        mCamera.unlock();  // Unlock the camera so media recorder can use it.
        try {
            mCamera.setParameters(parameters);
            fail("setParameters should not succeed because camera is unlocked.");
        } catch (RuntimeException e) {
            // expected
        }

        recordVideo(profile, surfaceHolder);  // should not throw exception
        // Media recorder already releases the camera so the test application
        // can lock and use the camera now.
        mCamera.lock();  // should not fail
        mCamera.setParameters(parameters);  // should not fail
        terminateMessageLooper();
    }

    private void setPreviewSizeByProfile(Parameters parameters, CamcorderProfile profile) {
        if (parameters.getSupportedVideoSizes() == null) {
            parameters.setPreviewSize(profile.videoFrameWidth,
                    profile.videoFrameHeight);
        } else {  // Driver supports separates outputs for preview and video.
            List<Size> sizes = parameters.getSupportedPreviewSizes();
            Size preferred = parameters.getPreferredPreviewSizeForVideo();
            int product = preferred.width * preferred.height;
            for (Size size: sizes) {
                if (size.width * size.height <= product) {
                    parameters.setPreviewSize(size.width, size.height);
                    break;
                }
            }
        }
    }

    private void recordVideo(CamcorderProfile profile,
            SurfaceHolder holder) throws Exception {
        MediaRecorder recorder = new MediaRecorder();
        try {
            // Pass the camera from the test application to media recorder.
            recorder.setCamera(mCamera);
            recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            recorder.setProfile(profile);
            recorder.setOutputFile("/dev/null");
            recorder.setPreviewDisplay(holder.getSurface());
            recorder.prepare();
            recorder.start();

            // Apps can use the camera after start since API level 13.
            Parameters parameters = mCamera.getParameters();
            if (parameters.isZoomSupported()) {
               if (parameters.getMaxZoom() > 0) {
                   parameters.setZoom(1);
                   mCamera.setParameters(parameters);
                   parameters.setZoom(0);
                   mCamera.setParameters(parameters);
               }
            }
            if (parameters.isSmoothZoomSupported()) {
                if (parameters.getMaxZoom() > 0) {
                    ZoomListener zoomListener = new ZoomListener();
                    mCamera.setZoomChangeListener(zoomListener);
                    mCamera.startSmoothZoom(1);
                    assertTrue(zoomListener.mZoomDone.block(1000));
                }
            }

            try {
                mCamera.unlock();
                fail("unlock should not succeed during recording.");
            } catch(RuntimeException e) {
                // expected
            }

            Thread.sleep(2000);
            recorder.stop();
        } finally {
            recorder.release();
        }
    }

    @UiThreadTest
    public void testPreviewCallbackWithBuffer() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewCallbackWithBufferByCamera(id);
        }
    }

    private void testPreviewCallbackWithBufferByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        SurfaceHolder surfaceHolder;
        surfaceHolder = getActivity().getSurfaceView().getHolder();
        mCamera.setPreviewDisplay(surfaceHolder);
        Parameters parameters = mCamera.getParameters();
        PreviewCallbackWithBuffer callback = new PreviewCallbackWithBuffer();
        // Test all preview sizes.
        for (Size size: parameters.getSupportedPreviewSizes()) {
            parameters.setPreviewSize(size.width, size.height);
            mCamera.setParameters(parameters);
            assertEquals(size, mCamera.getParameters().getPreviewSize());
            callback.mNumCbWithBuffer1 = 0;
            callback.mNumCbWithBuffer2 = 0;
            callback.mNumCbWithBuffer3 = 0;
            int format = mCamera.getParameters().getPreviewFormat();
            int bitsPerPixel = ImageFormat.getBitsPerPixel(format);
            callback.mBuffer1 = new byte[size.width * size.height * bitsPerPixel / 8];
            callback.mBuffer2 = new byte[size.width * size.height * bitsPerPixel / 8];
            callback.mBuffer3 = new byte[size.width * size.height * bitsPerPixel / 8];

            // Test if we can get the preview callbacks with specified buffers.
            mCamera.addCallbackBuffer(callback.mBuffer1);
            mCamera.addCallbackBuffer(callback.mBuffer2);
            mCamera.setPreviewCallbackWithBuffer(callback);
            mCamera.startPreview();
            waitForPreviewDone();
            assertFalse(callback.mPreviewDataNull);
            assertFalse(callback.mInvalidData);
            assertEquals(1, callback.mNumCbWithBuffer1);
            assertEquals(1, callback.mNumCbWithBuffer2);
            assertEquals(0, callback.mNumCbWithBuffer3);

            // Test if preview callback with buffer still works during preview.
            mCamera.addCallbackBuffer(callback.mBuffer3);
            waitForPreviewDone();
            assertFalse(callback.mPreviewDataNull);
            assertFalse(callback.mInvalidData);
            assertEquals(1, callback.mNumCbWithBuffer1);
            assertEquals(1, callback.mNumCbWithBuffer2);
            assertEquals(1, callback.mNumCbWithBuffer3);
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.stopPreview();
        }
        terminateMessageLooper();
    }

    private final class PreviewCallbackWithBuffer
            implements android.hardware.Camera.PreviewCallback {
        public int mNumCbWithBuffer1, mNumCbWithBuffer2, mNumCbWithBuffer3;
        public byte[] mBuffer1, mBuffer2, mBuffer3;
        public boolean mPreviewDataNull, mInvalidData;
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (data == null) {
                Log.e(TAG, "Preview data is null!");
                mPreviewDataNull = true;
                mPreviewDone.open();
                return;
            }
            if (data == mBuffer1) {
                mNumCbWithBuffer1++;
            } else if (data == mBuffer2) {
                mNumCbWithBuffer2++;
            } else if (data == mBuffer3) {
                mNumCbWithBuffer3++;
            } else {
                Log.e(TAG, "Invalid byte array.");
                mInvalidData = true;
                mPreviewDone.open();
                return;
            }

            if ((mNumCbWithBuffer1 == 1 && mNumCbWithBuffer2 == 1)
                    || mNumCbWithBuffer3 == 1) {
                mPreviewDone.open();
            }
        }
    }

    @UiThreadTest
    public void testImmediateZoom() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testImmediateZoomByCamera(id);
        }
    }

    private void testImmediateZoomByCamera(int id) throws Exception {
        initializeMessageLooper(id);

        Parameters parameters = mCamera.getParameters();
        if (!parameters.isZoomSupported()) {
            terminateMessageLooper();
            return;
        }

        // Test the zoom parameters.
        assertEquals(0, parameters.getZoom());  // default zoom should be 0.
        for (Size size: parameters.getSupportedPreviewSizes()) {
            parameters = mCamera.getParameters();
            parameters.setPreviewSize(size.width, size.height);
            mCamera.setParameters(parameters);
            parameters = mCamera.getParameters();
            int maxZoom = parameters.getMaxZoom();
            assertTrue(maxZoom >= 0);

            // Zoom ratios should be sorted from small to large.
            List<Integer> ratios = parameters.getZoomRatios();
            assertEquals(maxZoom + 1, ratios.size());
            assertEquals(100, ratios.get(0).intValue());
            for (int i = 0; i < ratios.size() - 1; i++) {
                assertTrue(ratios.get(i) < ratios.get(i + 1));
            }
            mCamera.startPreview();
            waitForPreviewDone();

            // Test each zoom step.
            for (int i = 0; i <= maxZoom; i++) {
                parameters.setZoom(i);
                mCamera.setParameters(parameters);
                assertEquals(i, mCamera.getParameters().getZoom());
            }

            // It should throw exception if an invalid value is passed.
            try {
                parameters.setZoom(maxZoom + 1);
                mCamera.setParameters(parameters);
                fail("setZoom should throw exception.");
            } catch (RuntimeException e) {
                // expected
            }
            assertEquals(maxZoom, mCamera.getParameters().getZoom());

            mCamera.takePicture(mShutterCallback, mRawPictureCallback,
                                mJpegPictureCallback);
            waitForSnapshotDone();
        }

        terminateMessageLooper();
    }

    @UiThreadTest
    public void testSmoothZoom() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testSmoothZoomByCamera(id);
        }
    }

    private void testSmoothZoomByCamera(int id) throws Exception {
        initializeMessageLooper(id);

        Parameters parameters = mCamera.getParameters();
        if (!parameters.isSmoothZoomSupported()) {
            terminateMessageLooper();
            return;
        }
        assertTrue(parameters.isZoomSupported());

        ZoomListener zoomListener = new ZoomListener();
        mCamera.setZoomChangeListener(zoomListener);
        mCamera.startPreview();
        waitForPreviewDone();

        // Immediate zoom should not generate callbacks.
        int maxZoom = parameters.getMaxZoom();
        parameters.setZoom(maxZoom);
        mCamera.setParameters(parameters);
        assertEquals(maxZoom, mCamera.getParameters().getZoom());
        parameters.setZoom(0);
        mCamera.setParameters(parameters);
        assertEquals(0, mCamera.getParameters().getZoom());
        assertFalse(zoomListener.mZoomDone.block(500));

        // Nothing will happen if zoom is not moving.
        mCamera.stopSmoothZoom();

        // It should not generate callbacks if zoom value is not changed.
        mCamera.startSmoothZoom(0);
        assertFalse(zoomListener.mZoomDone.block(500));
        assertEquals(0, mCamera.getParameters().getZoom());

        // Test startSmoothZoom.
        mCamera.startSmoothZoom(maxZoom);
        assertEquals(true, zoomListener.mZoomDone.block(5000));
        assertEquals(maxZoom, mCamera.getParameters().getZoom());
        assertEquals(maxZoom, zoomListener.mValues.size());
        for(int i = 0; i < maxZoom; i++) {
            int value = zoomListener.mValues.get(i);
            boolean stopped = zoomListener.mStopped.get(i);
            // Make sure we get all the zoom values in order.
            assertEquals(i + 1, value);
            // All "stopped" except the last should be false.
            assertEquals(i == maxZoom - 1, stopped);
        }

        // Test startSmoothZoom. Make sure we get all the callbacks.
        if (maxZoom > 1) {
            zoomListener.mValues.clear();
            zoomListener.mStopped.clear();
            Log.e(TAG, "zoomListener.mStopped = " + zoomListener.mStopped);
            zoomListener.mZoomDone.close();
            mCamera.startSmoothZoom(maxZoom / 2);
            assertTrue(zoomListener.mZoomDone.block(5000));
            assertEquals(maxZoom / 2, mCamera.getParameters().getZoom());
            assertEquals(maxZoom - (maxZoom / 2), zoomListener.mValues.size());
            for(int i = 0; i < zoomListener.mValues.size(); i++) {
                int value = zoomListener.mValues.get(i);
                boolean stopped = zoomListener.mStopped.get(i);
                // Make sure we get all the zoom values in order.
                assertEquals(maxZoom - 1 - i, value);
                // All "stopped" except the last should be false.
                assertEquals(i == zoomListener.mValues.size() - 1, stopped);
            }
        }

        // It should throw exception if an invalid value is passed.
        try {
            mCamera.startSmoothZoom(maxZoom + 1);
            fail("startSmoothZoom should throw exception.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        // Test stopSmoothZoom.
        zoomListener.mValues.clear();
        zoomListener.mStopped.clear();
        zoomListener.mZoomDone.close();
        parameters.setZoom(0);
        mCamera.setParameters(parameters);
        assertEquals(0, mCamera.getParameters().getZoom());
        mCamera.startSmoothZoom(maxZoom);
        mCamera.stopSmoothZoom();
        assertTrue(zoomListener.mZoomDone.block(5000));
        assertEquals(zoomListener.mValues.size(), mCamera.getParameters().getZoom());
        for(int i = 0; i < zoomListener.mValues.size() - 1; i++) {
            int value = zoomListener.mValues.get(i);
            boolean stopped = zoomListener.mStopped.get(i);
            // Make sure we get all the callbacks in order (except the last).
            assertEquals(i + 1, value);
            // All "stopped" except the last should be false. stopSmoothZoom has been called. So the
            // last "stopped" can be true or false.
            if (i != zoomListener.mValues.size() - 1) {
                assertFalse(stopped);
            }
        }

        terminateMessageLooper();
    }

    private final class ZoomListener
            implements android.hardware.Camera.OnZoomChangeListener {
        public ArrayList<Integer> mValues = new ArrayList<Integer>();
        public ArrayList<Boolean> mStopped = new ArrayList<Boolean>();
        public final ConditionVariable mZoomDone = new ConditionVariable();

        public void onZoomChange(int value, boolean stopped, Camera camera) {
            mValues.add(value);
            mStopped.add(stopped);
            if (stopped) {
                mZoomDone.open();
            }
        }
    }

    @UiThreadTest
    public void testFocusDistances() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testFocusDistancesByCamera(id);
        }
    }

    private void testFocusDistancesByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        mCamera.startPreview();
        waitForPreviewDone();
        Parameters parameters = mCamera.getParameters();

        // Test every supported focus mode.
        for (String focusMode: parameters.getSupportedFocusModes()) {
            parameters.setFocusMode(focusMode);
            mCamera.setParameters(parameters);
            parameters = mCamera.getParameters();
            assertEquals(focusMode, parameters.getFocusMode());
            checkFocusDistances(parameters);
            if (Parameters.FOCUS_MODE_AUTO.equals(focusMode)
                    || Parameters.FOCUS_MODE_MACRO.equals(focusMode)
                    || Parameters.FOCUS_MODE_CONTINUOUS_VIDEO.equals(focusMode)
                    || Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focusMode)) {
                Log.v(TAG, "Focus mode=" + focusMode);
                mCamera.autoFocus(mAutoFocusCallback);
                assertTrue(waitForFocusDone());
                parameters = mCamera.getParameters();
                checkFocusDistances(parameters);
                float[] initialFocusDistances = new float[3];
                parameters.getFocusDistances(initialFocusDistances);

                // Focus position should not change after autoFocus call.
                // Continuous autofocus should have stopped. Sleep some time and
                // check. Make sure continuous autofocus is not working. If the
                // focus mode is auto or macro, it is no harm to do the extra
                // test.
                Thread.sleep(500);
                parameters = mCamera.getParameters();
                float[] currentFocusDistances = new float[3];
                parameters.getFocusDistances(currentFocusDistances);
                assertEquals(initialFocusDistances, currentFocusDistances);

                // Focus position should not change after stopping preview.
                mCamera.stopPreview();
                parameters = mCamera.getParameters();
                parameters.getFocusDistances(currentFocusDistances);
                assertEquals(initialFocusDistances, currentFocusDistances);

                // Focus position should not change after taking a picture.
                mCamera.startPreview();
                mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
                waitForSnapshotDone();
                parameters = mCamera.getParameters();
                parameters.getFocusDistances(currentFocusDistances);
                assertEquals(initialFocusDistances, currentFocusDistances);
                mCamera.startPreview();
            }
        }

        // Test if the method throws exception if the argument is invalid.
        try {
            parameters.getFocusDistances(null);
            fail("getFocusDistances should not accept null.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        try {
            parameters.getFocusDistances(new float[2]);
            fail("getFocusDistances should not accept a float array with two elements.");
        } catch (IllegalArgumentException e) {
            // expected
        }

        try {
            parameters.getFocusDistances(new float[4]);
            fail("getFocusDistances should not accept a float array with four elements.");
        } catch (IllegalArgumentException e) {
            // expected
        }
        terminateMessageLooper();
    }

    private void checkFocusDistances(Parameters parameters) {
        float[] distances = new float[3];
        parameters.getFocusDistances(distances);

        // Focus distances should be greater than 0.
        assertTrue(distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX] > 0);
        assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] > 0);
        assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] > 0);

        // Make sure far focus distance >= optimal focus distance >= near focus distance.
        assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] >=
                   distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);
        assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] >=
                   distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX]);

        // Far focus distance should be infinity in infinity focus mode.
        if (Parameters.FOCUS_MODE_INFINITY.equals(parameters.getFocusMode())) {
            assertEquals(Float.POSITIVE_INFINITY,
                         distances[Parameters.FOCUS_DISTANCE_FAR_INDEX]);
        }
    }

    @UiThreadTest
    public void testCancelAutofocus() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testCancelAutofocusByCamera(id);
        }
    }

    private void testCancelAutofocusByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();
        List<String> focusModes = parameters.getSupportedFocusModes();

        if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) {
            parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
        } else if (focusModes.contains(Parameters.FOCUS_MODE_MACRO)) {
            parameters.setFocusMode(Parameters.FOCUS_MODE_MACRO);
        } else {
            terminateMessageLooper();
            return;
        }

        mCamera.setParameters(parameters);

        // Valid to call outside of preview; should just reset lens or
        // be a no-op.
        mCamera.cancelAutoFocus();

        mCamera.startPreview();

        // No op if autofocus is not in progress.
        mCamera.cancelAutoFocus();

        // Try to cancel autofocus immediately.
        mCamera.autoFocus(mAutoFocusCallback);
        mCamera.cancelAutoFocus();
        checkFocusDistanceNotChanging();

        // Try to cancel autofocus after it starts for some time.
        mCamera.autoFocus(mAutoFocusCallback);
        Thread.sleep(500);
        mCamera.cancelAutoFocus();
        checkFocusDistanceNotChanging();

        // Try to cancel autofocus after it completes. It should be no op.
        mCamera.autoFocus(mAutoFocusCallback);
        assertTrue(waitForFocusDone());
        mCamera.cancelAutoFocus();

        // Test the case calling cancelAutoFocus and release in a row.
        mCamera.autoFocus(mAutoFocusCallback);
        mCamera.cancelAutoFocus();
        mCamera.release();

        // Ensure the camera can be opened if release is called right after AF.
        mCamera = Camera.open(cameraId);
        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
        mCamera.startPreview();
        mCamera.autoFocus(mAutoFocusCallback);
        mCamera.release();

        terminateMessageLooper();
    }

    private void checkFocusDistanceNotChanging() throws Exception {
        float[] distances1 = new float[3];
        float[] distances2 = new float[3];
        Parameters parameters = mCamera.getParameters();
        parameters.getFocusDistances(distances1);
        Thread.sleep(100);
        parameters = mCamera.getParameters();
        parameters.getFocusDistances(distances2);
        assertEquals(distances1[Parameters.FOCUS_DISTANCE_NEAR_INDEX],
                     distances2[Parameters.FOCUS_DISTANCE_NEAR_INDEX]);
        assertEquals(distances1[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX],
                     distances2[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);
        assertEquals(distances1[Parameters.FOCUS_DISTANCE_FAR_INDEX],
                     distances2[Parameters.FOCUS_DISTANCE_FAR_INDEX]);
    }

    @UiThreadTest
    public void testMultipleCameras() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        Log.v(TAG, "total " + nCameras + " cameras");
        assertTrue(nCameras >= 0);

        boolean backCameraExist = false;
        CameraInfo info = new CameraInfo();
        for (int i = 0; i < nCameras; i++) {
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                backCameraExist = true;
                break;
            }
        }
        // Make sure original open still works. It must return a back-facing
        // camera.
        mCamera = Camera.open();
        if (mCamera != null) {
            mCamera.release();
            assertTrue(backCameraExist);
        } else {
            assertFalse(backCameraExist);
        }

        for (int id = -1; id <= nCameras; id++) {
            Log.v(TAG, "testing camera #" + id);

            boolean isBadId = (id < 0 || id >= nCameras);

            try {
                Camera.getCameraInfo(id, info);
                if (isBadId) {
                    fail("getCameraInfo should not accept bad cameraId (" + id + ")");
                }
            } catch (RuntimeException e) {
                if (!isBadId) throw e;
            }

            int facing = info.facing;
            int orientation = info.orientation;
            assertTrue(facing == CameraInfo.CAMERA_FACING_BACK ||
                       facing == CameraInfo.CAMERA_FACING_FRONT);
            assertTrue(orientation == 0 || orientation == 90 ||
                       orientation == 180 || orientation == 270);

            Camera camera = null;
            try {
                camera = Camera.open(id);
                if (isBadId) {
                    fail("open() should not accept bad cameraId (" + id + ")");
                }
            } catch (RuntimeException e) {
                if (!isBadId) throw e;
            } finally {
                if (camera != null) {
                    camera.release();
                }
            }
        }
    }

    @UiThreadTest
    public void testPreviewPictureSizesCombination() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewPictureSizesCombinationByCamera(id);
        }
    }

    private void testPreviewPictureSizesCombinationByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();
        PreviewCbForPreviewPictureSizesCombination callback =
            new PreviewCbForPreviewPictureSizesCombination();

        // Test combination of preview sizes and picture sizes. Pick four of each to test.
        // Do not test all combinations because it will timeout. Four is just a small number
        // and the test will not timeout.
        List<Size> previewSizes = parameters.getSupportedPreviewSizes();
        List<Size> pictureSizes = parameters.getSupportedPictureSizes();
        int previewSizeTestCount = Math.min(previewSizes.size(), 4);
        int pictureSizeTestCount = Math.min(pictureSizes.size(), 4);
        // Calculate the step so that the first one and the last one are always tested.
        float previewSizeIndexStep = (float) (previewSizes.size() - 1) / (previewSizeTestCount - 1);
        float pictureSizeIndexStep = (float) (pictureSizes.size() - 1) / (pictureSizeTestCount - 1);
        for (int i = 0; i < previewSizeTestCount; i++) {
            for (int j = 0; j < pictureSizeTestCount; j++) {
                Size previewSize = previewSizes.get(Math.round(previewSizeIndexStep * i));
                Size pictureSize = pictureSizes.get(Math.round(pictureSizeIndexStep * j));
                Log.v(TAG, "Test previewSize=(" + previewSize.width + "," +
                        previewSize.height + ") pictureSize=(" +
                        pictureSize.width + "," + pictureSize.height + ")");
                mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
                mCamera.setPreviewCallback(callback);
                callback.expectedPreviewSize = previewSize;
                parameters.setPreviewSize(previewSize.width, previewSize.height);
                parameters.setPictureSize(pictureSize.width, pictureSize.height);
                mCamera.setParameters(parameters);
                assertEquals(previewSize, mCamera.getParameters().getPreviewSize());
                assertEquals(pictureSize, mCamera.getParameters().getPictureSize());

                // Check if the preview size is the same as requested.
                mCamera.startPreview();
                waitForPreviewDone();
                assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);

                // Check if the picture size is the same as requested.
                mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
                waitForSnapshotDone();
                assertTrue(mJpegPictureCallbackResult);
                assertNotNull(mJpegData);
                BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
                bmpOptions.inJustDecodeBounds = true;
                BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions);
                assertEquals(pictureSize.width, bmpOptions.outWidth);
                assertEquals(pictureSize.height, bmpOptions.outHeight);
            }
        }
        terminateMessageLooper();
    }

    private final class PreviewCbForPreviewPictureSizesCombination
            implements android.hardware.Camera.PreviewCallback {
        public Size expectedPreviewSize;
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (data == null) {
                mPreviewCallbackResult = PREVIEW_CALLBACK_DATA_NULL;
                mPreviewDone.open();
                return;
            }
            Size size = camera.getParameters().getPreviewSize();
            int format = camera.getParameters().getPreviewFormat();
            int bitsPerPixel = ImageFormat.getBitsPerPixel(format);
            if (!expectedPreviewSize.equals(size) ||
                    calculateBufferSize(size.width, size.height,
                        format, bitsPerPixel) != data.length) {
                Log.e(TAG, "Expected preview width=" + expectedPreviewSize.width + ", height="
                        + expectedPreviewSize.height + ". Actual width=" + size.width + ", height="
                        + size.height);
                Log.e(TAG, "Frame data length=" + data.length + ". bitsPerPixel=" + bitsPerPixel);
                mPreviewCallbackResult = PREVIEW_CALLBACK_INVALID_FRAME_SIZE;
                mPreviewDone.open();
                return;
            }
            camera.setPreviewCallback(null);
            mPreviewCallbackResult = PREVIEW_CALLBACK_RECEIVED;
            mPreviewDone.open();
        }
    }

    @UiThreadTest
    public void testPreviewFpsRange() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewFpsRangeByCamera(id);
        }
    }

    private void testPreviewFpsRangeByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);

        // Test if the parameters exists and minimum fps <= maximum fps.
        int[] defaultFps = new int[2];
        Parameters parameters = mCamera.getParameters();
        parameters.getPreviewFpsRange(defaultFps);
        List<int[]> fpsList = parameters.getSupportedPreviewFpsRange();
        assertTrue(fpsList.size() > 0);
        boolean found = false;
        for(int[] fps: fpsList) {
            assertTrue(fps[Parameters.PREVIEW_FPS_MIN_INDEX] > 0);
            assertTrue(fps[Parameters.PREVIEW_FPS_MIN_INDEX] <=
                       fps[Parameters.PREVIEW_FPS_MAX_INDEX]);
            if (!found && Arrays.equals(defaultFps, fps)) {
                found = true;
            }
        }
        assertTrue("Preview fps range must be in the supported list.", found);

        // Test if the list is properly sorted.
        for (int i = 0; i < fpsList.size() - 1; i++) {
            int minFps1 = fpsList.get(i)[Parameters.PREVIEW_FPS_MIN_INDEX];
            int maxFps1 = fpsList.get(i)[Parameters.PREVIEW_FPS_MAX_INDEX];
            int minFps2 = fpsList.get(i + 1)[Parameters.PREVIEW_FPS_MIN_INDEX];
            int maxFps2 = fpsList.get(i + 1)[Parameters.PREVIEW_FPS_MAX_INDEX];
            assertTrue(maxFps1 < maxFps2
                    || (maxFps1 == maxFps2 && minFps1 < minFps2));
        }

        // Test if the actual fps is within fps range.
        Size size = parameters.getPreviewSize();
        int format = mCamera.getParameters().getPreviewFormat();
        int bitsPerPixel = ImageFormat.getBitsPerPixel(format);
        byte[] buffer1 = new byte[size.width * size.height * bitsPerPixel / 8];
        byte[] buffer2 = new byte[size.width * size.height * bitsPerPixel / 8];
        byte[] buffer3 = new byte[size.width * size.height * bitsPerPixel / 8];
        FpsRangePreviewCb callback = new FpsRangePreviewCb();
        int[] readBackFps = new int[2];
        for (int[] fps: fpsList) {
            parameters = mCamera.getParameters();
            parameters.setPreviewFpsRange(fps[Parameters.PREVIEW_FPS_MIN_INDEX],
                                          fps[Parameters.PREVIEW_FPS_MAX_INDEX]);
            callback.reset(fps[Parameters.PREVIEW_FPS_MIN_INDEX] / 1000.0,
                           fps[Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.0);
            mCamera.setParameters(parameters);
            parameters = mCamera.getParameters();
            parameters.getPreviewFpsRange(readBackFps);
            MoreAsserts.assertEquals(fps, readBackFps);
            mCamera.addCallbackBuffer(buffer1);
            mCamera.addCallbackBuffer(buffer2);
            mCamera.addCallbackBuffer(buffer3);
            mCamera.setPreviewCallbackWithBuffer(callback);
            mCamera.startPreview();
            try {
                // Test the frame rate for a while.
                Thread.sleep(3000);
            } catch(Exception e) {
                // ignore
            }
            mCamera.stopPreview();
        }

        // Test the invalid fps cases.
        parameters = mCamera.getParameters();
        parameters.setPreviewFpsRange(-1, -1);
        try {
            mCamera.setParameters(parameters);
            fail("Should throw an exception if fps range is negative.");
        } catch (RuntimeException e) {
            // expected
        }
        parameters.setPreviewFpsRange(10, 5);
        try {
            mCamera.setParameters(parameters);
            fail("Should throw an exception if fps range is invalid.");
        } catch (RuntimeException e) {
            // expected
        }

        terminateMessageLooper();
    }

    private final class FpsRangePreviewCb
            implements android.hardware.Camera.PreviewCallback {
        private double mMinFps, mMaxFps, mMaxFrameInterval, mMinFrameInterval;
        // An array storing the arrival time of the frames in the last second.
        private ArrayList<Long> mFrames = new ArrayList<Long>();
        private long firstFrameArrivalTime;

        public void reset(double minFps, double maxFps) {
            this.mMinFps = minFps;
            this.mMaxFps = maxFps;
            mMaxFrameInterval = 1000.0 / mMinFps;
            mMinFrameInterval = 1000.0 / mMaxFps;
            Log.v(TAG, "Min fps=" + mMinFps + ". Max fps=" + mMaxFps
                    + ". Min frame interval=" + mMinFrameInterval
                    + ". Max frame interval=" + mMaxFrameInterval);
            mFrames.clear();
            firstFrameArrivalTime = 0;
        }

        // This method tests if the actual fps is between minimum and maximum.
        // It also tests if the frame interval is too long.
        public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
            long arrivalTime = System.currentTimeMillis();
            camera.addCallbackBuffer(data);
            if (firstFrameArrivalTime == 0) firstFrameArrivalTime = arrivalTime;

            // Remove the frames that arrived before the last second.
            Iterator<Long> it = mFrames.iterator();
            while(it.hasNext()) {
                long time = it.next();
                if (arrivalTime - time > 1000 && mFrames.size() > 2) {
                    it.remove();
                } else {
                    break;
                }
            }

            // Start the test after one second.
            if (arrivalTime - firstFrameArrivalTime > 1000) {
                assertTrue(mFrames.size() >= 2);

                // Check the frame interval and fps. The interval check
                // considers the time variance passing frames from the camera
                // hardware to the callback. It should be a constant time, not a
                // ratio. The fps check is more strict because individual
                // variance is averaged out.

                // Check if the frame interval is too large or too small.
                // x100 = percent, intervalMargin should be bigger than fpsMargin considering that
                // fps will be in the order of 10.
                double intervalMargin = 0.9;
                long lastArrivalTime = mFrames.get(mFrames.size() - 1);
                double interval = arrivalTime - lastArrivalTime;
                if (LOGV) Log.v(TAG, "Frame interval=" + interval);
                assertTrue("Frame interval (" + interval + "ms) is too large." +
                        " mMaxFrameInterval=" + mMaxFrameInterval + "ms",
                        interval < mMaxFrameInterval * (1.0 + intervalMargin));
                assertTrue("Frame interval (" + interval + "ms) is too small." +
                        " mMinFrameInterval=" + mMinFrameInterval + "ms",
                        interval > mMinFrameInterval * (1.0 - intervalMargin));

                // Check if the fps is within range.
                double fpsMargin = 0.5; // x100 = percent
                double avgInterval = (double)(arrivalTime - mFrames.get(0))
                        / mFrames.size();
                double fps = 1000.0 / avgInterval;
                assertTrue("Actual fps (" + fps + ") should be larger than " +
                           "min fps (" + mMinFps + ")",
                           fps >= mMinFps * (1.0 - fpsMargin));
                assertTrue("Actual fps (" + fps + ") should be smaller than " +
                           "max fps (" + mMaxFps + ")",
                           fps <= mMaxFps * (1.0 + fpsMargin));
            }
            // Add the arrival time of this frame to the list.
            mFrames.add(arrivalTime);
        }
    }

    private void assertEquals(Size expected, Size actual) {
        assertEquals(expected.width, actual.width);
        assertEquals(expected.height, actual.height);
    }

    private void assertEquals(float[] expected, float[] actual) {
        assertEquals(expected.length, actual.length);
        for (int i = 0; i < expected.length; i++) {
            assertEquals(expected[i], actual[i], 0.000001f);
        }
    }

    private void assertNoLetters(String value, String key) {
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            assertFalse("Parameter contains invalid characters. key,value=("
                    + key + "," + value + ")",
                    Character.isLetter(c) && c != 'x');
        }
    }

    @UiThreadTest
    public void testSceneMode() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testSceneModeByCamera(id);
        }
    }

    private class SceneModeSettings {
        public String mScene, mFlash, mFocus, mWhiteBalance;
        public List<String> mSupportedFlash, mSupportedFocus, mSupportedWhiteBalance;

        public SceneModeSettings(Parameters parameters) {
            mScene = parameters.getSceneMode();
            mFlash = parameters.getFlashMode();
            mFocus = parameters.getFocusMode();
            mWhiteBalance = parameters.getWhiteBalance();
            mSupportedFlash = parameters.getSupportedFlashModes();
            mSupportedFocus = parameters.getSupportedFocusModes();
            mSupportedWhiteBalance = parameters.getSupportedWhiteBalance();
        }
    }

    private void testSceneModeByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();
        List<String> supportedSceneModes = parameters.getSupportedSceneModes();
        if (supportedSceneModes != null) {
            assertEquals(Parameters.SCENE_MODE_AUTO, parameters.getSceneMode());
            SceneModeSettings autoSceneMode = new SceneModeSettings(parameters);

            // Store all scene mode affected settings.
            SceneModeSettings[] settings = new SceneModeSettings[supportedSceneModes.size()];
            for (int i = 0; i < supportedSceneModes.size(); i++) {
                parameters.setSceneMode(supportedSceneModes.get(i));
                mCamera.setParameters(parameters);
                parameters = mCamera.getParameters();
                settings[i] = new SceneModeSettings(parameters);
            }

            // Make sure scene mode settings are consistent before preview and
            // after preview.
            mCamera.startPreview();
            waitForPreviewDone();
            for (int i = 0; i < supportedSceneModes.size(); i++) {
                String sceneMode = supportedSceneModes.get(i);
                parameters.setSceneMode(sceneMode);
                mCamera.setParameters(parameters);
                parameters = mCamera.getParameters();

                // In auto scene mode, camera HAL will not remember the previous
                // flash, focus, and white-balance. It will just take values set
                // by parameters. But the supported flash, focus, and
                // white-balance should still be restored in auto scene mode.
                if (!Parameters.SCENE_MODE_AUTO.equals(sceneMode)) {
                    assertEquals("Flash is inconsistent in scene mode " + sceneMode,
                            settings[i].mFlash, parameters.getFlashMode());
                    assertEquals("Focus is inconsistent in scene mode " + sceneMode,
                            settings[i].mFocus, parameters.getFocusMode());
                    assertEquals("White balance is inconsistent in scene mode " + sceneMode,
                            settings[i].mWhiteBalance, parameters.getWhiteBalance());
                }
                assertEquals("Suppported flash modes are inconsistent in scene mode " + sceneMode,
                        settings[i].mSupportedFlash, parameters.getSupportedFlashModes());
                assertEquals("Suppported focus modes are inconsistent in scene mode " + sceneMode,
                        settings[i].mSupportedFocus, parameters.getSupportedFocusModes());
                assertEquals("Suppported white balance are inconsistent in scene mode " + sceneMode,
                        settings[i].mSupportedWhiteBalance, parameters.getSupportedWhiteBalance());
            }

            for (int i = 0; i < settings.length; i++) {
                if (Parameters.SCENE_MODE_AUTO.equals(settings[i].mScene)) continue;

                // Both the setting and the supported settings may change. It is
                // allowed to have more than one supported settings in scene
                // modes. For example, in night scene mode, supported flash
                // modes can have on and off.
                if (autoSceneMode.mSupportedFlash != null) {
                    assertTrue(settings[i].mSupportedFlash.contains(settings[i].mFlash));
                    for (String mode: settings[i].mSupportedFlash) {
                        assertTrue(autoSceneMode.mSupportedFlash.contains(mode));
                    }
                }
                if (autoSceneMode.mSupportedFocus != null) {
                    assertTrue(settings[i].mSupportedFocus.contains(settings[i].mFocus));
                    for (String mode: settings[i].mSupportedFocus) {
                        assertTrue(autoSceneMode.mSupportedFocus.contains(mode));
                    }
                }
                if (autoSceneMode.mSupportedWhiteBalance != null) {
                    assertTrue(settings[i].mSupportedWhiteBalance.contains(settings[i].mWhiteBalance));
                    for (String mode: settings[i].mSupportedWhiteBalance) {
                        assertTrue(autoSceneMode.mSupportedWhiteBalance.contains(mode));
                    }
                }
            }
        }
        terminateMessageLooper();
    }

    @UiThreadTest
    public void testInvalidParameters() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testInvalidParametersByCamera(id);
        }
    }

    private void testInvalidParametersByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        // Test flash mode.
        Parameters parameters = mCamera.getParameters();
        List<String> list = parameters.getSupportedFlashModes();
        if (list != null && list.size() > 0) {
            String original = parameters.getFlashMode();
            parameters.setFlashMode("invalid");
            try {
                mCamera.setParameters(parameters);
                fail("Should throw exception for invalid parameters");
            } catch (RuntimeException e) {
                // expected
            }
            parameters = mCamera.getParameters();
            assertEquals(original, parameters.getFlashMode());
        }

        // Test focus mode.
        String originalFocus = parameters.getFocusMode();
        parameters.setFocusMode("invalid");
        try {
            mCamera.setParameters(parameters);
            fail("Should throw exception for invalid parameters");
        } catch (RuntimeException e) {
            // expected
        }
        parameters = mCamera.getParameters();
        assertEquals(originalFocus, parameters.getFocusMode());

        // Test preview size.
        Size originalSize = parameters.getPreviewSize();
        parameters.setPreviewSize(-1, -1);
        try {
            mCamera.setParameters(parameters);
            fail("Should throw exception for invalid parameters");
        } catch (RuntimeException e) {
            // expected
        }
        parameters = mCamera.getParameters();
        assertEquals(originalSize, parameters.getPreviewSize());

        terminateMessageLooper();
    }

    @UiThreadTest
    public void testGetParameterDuringFocus() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testGetParameterDuringFocusByCamera(id);
        }
    }

    private void testGetParameterDuringFocusByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        mCamera.startPreview();
        Parameters parameters = mCamera.getParameters();
        for (String focusMode: parameters.getSupportedFocusModes()) {
            if (focusMode.equals(parameters.FOCUS_MODE_AUTO)
                    || focusMode.equals(parameters.FOCUS_MODE_MACRO)) {
                parameters.setFocusMode(focusMode);
                mCamera.setParameters(parameters);
                mCamera.autoFocus(mAutoFocusCallback);
                // This should not crash or throw exception.
                mCamera.getParameters();
                waitForFocusDone();


                mCamera.autoFocus(mAutoFocusCallback);
                // Add a small delay to make sure focus has started.
                Thread.sleep(100);
                // This should not crash or throw exception.
                mCamera.getParameters();
                waitForFocusDone();
            }
        }
        terminateMessageLooper();
    }

    @UiThreadTest
    public void testPreviewFormats() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewFormatsByCamera(id);
        }
    }

    private void testPreviewFormatsByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();
        for (int format: parameters.getSupportedPreviewFormats()) {
            Log.v(TAG, "Test preview format " + format);
            parameters.setPreviewFormat(format);
            mCamera.setParameters(parameters);
            mCamera.setOneShotPreviewCallback(mPreviewCallback);
            mCamera.startPreview();
            waitForPreviewDone();
            assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);
        }
        terminateMessageLooper();
    }

    @UiThreadTest
    public void testMultiCameraRelease() throws Exception {
        // Verify that multiple cameras exist, and that they can be opened at the same time
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Checking pre-conditions.");
        int nCameras = Camera.getNumberOfCameras();
        if (nCameras < 2) {
            Log.i(TAG, "Test multi-camera release: Skipping test because only 1 camera available");
            return;
        }

        Camera testCamera0 = Camera.open(0);
        Camera testCamera1 = null;
        try {
            testCamera1 = Camera.open(1);
        } catch (RuntimeException e) {
            // Can't open two cameras at once
            Log.i(TAG, "testMultiCameraRelease: Skipping test because only 1 camera "+
                  "could be opened at once. Second open threw: " + e);
            testCamera0.release();
            return;
        }
        testCamera0.release();
        testCamera1.release();

        // Start first camera
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 0");
        initializeMessageLooper(0);
        SimplePreviewStreamCb callback0 = new SimplePreviewStreamCb(0);
        mCamera.setPreviewCallback(callback0);
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 0");
        mCamera.startPreview();
        // Run preview for a bit
        for (int f = 0; f < 100; f++) {
            mPreviewDone.close();
            assertTrue("testMultiCameraRelease: First camera preview timed out on frame " + f + "!",
                       mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE));
        }
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
        mCamera.stopPreview();
        // Save message looper and camera to deterministically release them, instead
        // of letting GC do it at some point.
        Camera firstCamera = mCamera;
        Looper firstLooper = mLooper;
        //terminateMessageLooper(); // Intentionally not calling this
        // Preview surface should be released though!
        mCamera.setPreviewDisplay(null);

        // Start second camera without releasing the first one (will
        // set mCamera and mLooper to new objects)
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 1");
        initializeMessageLooper(1);
        SimplePreviewStreamCb callback1 = new SimplePreviewStreamCb(1);
        mCamera.setPreviewCallback(callback1);
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 1");
        mCamera.startPreview();
        // Run preview for a bit - GC of first camera instance should not impact the second's
        // operation.
        for (int f = 0; f < 100; f++) {
            mPreviewDone.close();
            assertTrue("testMultiCameraRelease: Second camera preview timed out on frame " + f + "!",
                       mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE));
            if (f == 50) {
                // Release first camera mid-preview, should cause no problems
                if (LOGV) Log.v(TAG, "testMultiCameraRelease: Releasing camera 0");
                firstCamera.release();
            }
        }
        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
        mCamera.stopPreview();

        firstLooper.quit();
        terminateMessageLooper();
    }

    // This callback just signals on the condition variable, making it useful for checking that
    // preview callbacks don't stop unexpectedly
    private final class SimplePreviewStreamCb
            implements android.hardware.Camera.PreviewCallback {
        private int mId;
        public SimplePreviewStreamCb(int id) {
            mId = id;
        }
        public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
            if (LOGV) Log.v(TAG, "Preview frame callback, id " + mId + ".");
            mPreviewDone.open();
        }
    }

    @UiThreadTest
    public void testFocusAreas() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);

            initializeMessageLooper(id);
            Parameters parameters = mCamera.getParameters();
            int maxNumFocusAreas = parameters.getMaxNumFocusAreas();
            assertTrue(maxNumFocusAreas >= 0);
            if (maxNumFocusAreas > 0) {
                List<String> focusModes = parameters.getSupportedFocusModes();
                assertTrue(focusModes.contains(Parameters.FOCUS_MODE_AUTO));
                testAreas(FOCUS_AREA, maxNumFocusAreas);
            }
            terminateMessageLooper();
        }
    }

    @UiThreadTest
    public void testMeteringAreas() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            Parameters parameters = mCamera.getParameters();
            int maxNumMeteringAreas = parameters.getMaxNumMeteringAreas();
            assertTrue(maxNumMeteringAreas >= 0);
            if (maxNumMeteringAreas > 0) {
                testAreas(METERING_AREA, maxNumMeteringAreas);
            }
            terminateMessageLooper();
        }
    }

    private void testAreas(int type, int maxNumAreas) throws Exception {
        mCamera.startPreview();

        // Test various valid cases.
        testValidAreas(type, null);                                  // the default area
        testValidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1)); // biggest area
        testValidAreas(type, makeAreas(-500, -500, 500, 500, 1000)); // medium area & biggest weight
        testValidAreas(type, makeAreas(0, 0, 1, 1, 1));              // smallest area

        ArrayList<Area> areas = new ArrayList();
        if (maxNumAreas > 1) {
            // Test overlapped areas.
            testValidAreas(type, makeAreas(-250, -250, 250, 250, 1, 0, 0, 500, 500, 2));
            // Test completely disjoint areas.
            testValidAreas(type, makeAreas(-250, -250, 0, 0, 1, 900, 900, 1000, 1000, 1));
            // Test the maximum number of areas.
            testValidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1000, maxNumAreas));
        }

        // Test various invalid cases.
        testInvalidAreas(type, makeAreas(-1001, -1000, 1000, 1000, 1));    // left should >= -1000
        testInvalidAreas(type, makeAreas(-1000, -1001, 1000, 1000, 1));    // top should >= -1000
        testInvalidAreas(type, makeAreas(-1000, -1000, 1001, 1000, 1));    // right should <= 1000
        testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1001, 1));    // bottom should <= 1000
        testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 0));    // weight should >= 1
        testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1001, 1001)); // weight should <= 1000
        testInvalidAreas(type, makeAreas(500, -1000, 500, 1000, 1));       // left should < right
        testInvalidAreas(type, makeAreas(-1000, 500, 1000, 500, 1));       // top should < bottom
        testInvalidAreas(type, makeAreas(500, -1000, 499, 1000, 1));       // left should < right
        testInvalidAreas(type, makeAreas(-1000, 500, 100, 499, 1));        // top should < bottom
        testInvalidAreas(type, makeAreas(-250, -250, 250, 250, -1));       // weight should >= 1
        // Test when the number of areas exceeds maximum.
        testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1000, maxNumAreas + 1));
    }

    private static ArrayList<Area> makeAreas(int left, int top, int right, int bottom, int weight) {
        ArrayList<Area> areas = new ArrayList<Area>();
        areas.add(new Area(new Rect(left, top, right, bottom), weight));
        return areas;
    }

    private static ArrayList<Area> makeAreas(int left, int top, int right, int bottom,
            int weight, int number) {
        ArrayList<Area> areas = new ArrayList<Area>();
        for (int i = 0; i < number; i++) {
            areas.add(new Area(new Rect(left, top, right, bottom), weight));
        }
        return areas;
    }

    private static ArrayList<Area> makeAreas(int left1, int top1, int right1,
            int bottom1, int weight1, int left2, int top2, int right2,
            int bottom2, int weight2) {
        ArrayList<Area> areas = new ArrayList<Area>();
        areas.add(new Area(new Rect(left1, top1, right1, bottom1), weight1));
        areas.add(new Area(new Rect(left2, top2, right2, bottom2), weight2));
        return areas;
    }

    private void testValidAreas(int areaType, ArrayList<Area> areas) {
        if (areaType == FOCUS_AREA) {
            testValidFocusAreas(areas);
        } else {
            testValidMeteringAreas(areas);
        }
    }

    private void testInvalidAreas(int areaType, ArrayList<Area> areas) {
        if (areaType == FOCUS_AREA) {
            testInvalidFocusAreas(areas);
        } else {
            testInvalidMeteringAreas(areas);
        }
    }

    private void testValidFocusAreas(ArrayList<Area> areas) {
        Parameters parameters = mCamera.getParameters();
        parameters.setFocusAreas(areas);
        mCamera.setParameters(parameters);
        parameters = mCamera.getParameters();
        assertEquals(areas, parameters.getFocusAreas());
        mCamera.autoFocus(mAutoFocusCallback);
        waitForFocusDone();
    }

    private void testInvalidFocusAreas(ArrayList<Area> areas) {
        Parameters parameters = mCamera.getParameters();
        List<Area> originalAreas = parameters.getFocusAreas();
        try {
            parameters.setFocusAreas(areas);
            mCamera.setParameters(parameters);
            fail("Should throw exception when focus area is invalid.");
        } catch (RuntimeException e) {
            parameters = mCamera.getParameters();
            assertEquals(originalAreas, parameters.getFocusAreas());
        }
    }

    private void testValidMeteringAreas(ArrayList<Area> areas) {
        Parameters parameters = mCamera.getParameters();
        parameters.setMeteringAreas(areas);
        mCamera.setParameters(parameters);
        parameters = mCamera.getParameters();
        assertEquals(areas, parameters.getMeteringAreas());
    }

    private void testInvalidMeteringAreas(ArrayList<Area> areas) {
        Parameters parameters = mCamera.getParameters();
        List<Area> originalAreas = parameters.getMeteringAreas();
        try {
            parameters.setMeteringAreas(areas);
            mCamera.setParameters(parameters);
            fail("Should throw exception when metering area is invalid.");
        } catch (RuntimeException e) {
            parameters = mCamera.getParameters();
            assertEquals(originalAreas, parameters.getMeteringAreas());
        }
    }

    // Apps should be able to call startPreview in jpeg callback.
    @UiThreadTest
    public void testJpegCallbackStartPreview() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testJpegCallbackStartPreviewByCamera(id);
        }
    }

    private void testJpegCallbackStartPreviewByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        mCamera.startPreview();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, new JpegStartPreviewCallback());
        waitForSnapshotDone();
        terminateMessageLooper();
        assertTrue(mJpegPictureCallbackResult);
    }

    private final class JpegStartPreviewCallback implements PictureCallback {
        public void onPictureTaken(byte[] rawData, Camera camera) {
            try {
                camera.startPreview();
                mJpegPictureCallbackResult = true;
            } catch (Exception e) {
            }
            mSnapshotDone.open();
        }
    }

    @UiThreadTest
    public void testRecordingHint() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testRecordingHintByCamera(id);
        }
    }

    private void testRecordingHintByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters parameters = mCamera.getParameters();

        SurfaceHolder holder = getActivity().getSurfaceView().getHolder();
        CamcorderProfile profile = CamcorderProfile.get(cameraId,
                CamcorderProfile.QUALITY_LOW);

        setPreviewSizeByProfile(parameters, profile);

        // Test recording videos and taking pictures when the hint is off and on.
        for (int i = 0; i < 2; i++) {
            parameters.setRecordingHint(i == 0 ? false : true);
            mCamera.setParameters(parameters);
            mCamera.startPreview();
            recordVideoSimple(profile, holder);
            mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
            waitForSnapshotDone();
            assertTrue(mJpegPictureCallbackResult);
        }

        // Can change recording hint when the preview is active.
        mCamera.startPreview();
        parameters.setRecordingHint(false);
        mCamera.setParameters(parameters);
        parameters.setRecordingHint(true);
        mCamera.setParameters(parameters);
        terminateMessageLooper();
    }

    private void recordVideoSimple(CamcorderProfile profile,
            SurfaceHolder holder) throws Exception {
        mCamera.unlock();
        MediaRecorder recorder = new MediaRecorder();
        try {
            recorder.setCamera(mCamera);
            recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            recorder.setProfile(profile);
            recorder.setOutputFile("/dev/null");
            recorder.setPreviewDisplay(holder.getSurface());
            recorder.prepare();
            recorder.start();
            Thread.sleep(2000);
            recorder.stop();
        } finally {
            recorder.release();
            mCamera.lock();
        }
    }

    @UiThreadTest
    public void testAutoExposureLock() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            Parameters parameters = mCamera.getParameters();
            boolean aeLockSupported = parameters.isAutoExposureLockSupported();
            if (aeLockSupported) {
                subtestLockCommon(AUTOEXPOSURE_LOCK);
                subtestLockAdditionalAE();
            }
            terminateMessageLooper();
        }
    }

    @UiThreadTest
    public void testAutoWhiteBalanceLock() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            Parameters parameters = mCamera.getParameters();
            boolean awbLockSupported = parameters.isAutoWhiteBalanceLockSupported();
            if (awbLockSupported) {
                subtestLockCommon(AUTOWHITEBALANCE_LOCK);
                subtestLockAdditionalAWB();
            }
            terminateMessageLooper();
        }
    }

    @UiThreadTest
    public void test3ALockInteraction() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            initializeMessageLooper(id);
            Parameters parameters = mCamera.getParameters();
            boolean locksSupported =
                    parameters.isAutoWhiteBalanceLockSupported() &&
                    parameters.isAutoExposureLockSupported();
            if (locksSupported) {
                subtestLockInteractions();
            }
            terminateMessageLooper();
        }
    }

    private void subtestLockCommon(int type) {
        // Verify lock is not set on open()
        assert3ALockState("Lock not released after open()", type, false);

        // Verify lock can be set, unset before preview
        set3ALockState(true, type);
        assert3ALockState("Lock could not be set before 1st preview!",
                type, true);

        set3ALockState(false, type);
        assert3ALockState("Lock could not be unset before 1st preview!",
                type, false);

        // Verify preview start does not set lock
        mCamera.startPreview();
        assert3ALockState("Lock state changed by preview start!", type, false);

        // Verify lock can be set, unset during preview
        set3ALockState(true, type);
        assert3ALockState("Lock could not be set during preview!", type, true);

        set3ALockState(false, type);
        assert3ALockState("Lock could not be unset during preview!",
                type, false);

        // Verify lock is not cleared by stop preview
        set3ALockState(true, type);
        mCamera.stopPreview();
        assert3ALockState("Lock was cleared by stopPreview!", type, true);

        // Verify that preview start does not clear lock
        set3ALockState(true, type);
        mCamera.startPreview();
        assert3ALockState("Lock state changed by preview start!", type, true);

        // Verify that taking a picture does not clear the lock
        set3ALockState(true, type);
        mCamera.takePicture(mShutterCallback, mRawPictureCallback,
                mJpegPictureCallback);
        waitForSnapshotDone();
        assert3ALockState("Lock state was cleared by takePicture!", type, true);

        mCamera.startPreview();
        Parameters parameters = mCamera.getParameters();
        for (String focusMode: parameters.getSupportedFocusModes()) {
            // TODO: Test this for other focus modes as well, once agreement is
            // reached on which ones it should apply to
            if (!Parameters.FOCUS_MODE_AUTO.equals(focusMode) ) {
                continue;
            }

            parameters.setFocusMode(focusMode);
            mCamera.setParameters(parameters);

            // Verify that autoFocus does not change the lock
            set3ALockState(false, type);
            mCamera.autoFocus(mAutoFocusCallback);
            assert3ALockState("Lock was set by autoFocus in mode: " + focusMode, type, false);
            assertTrue(waitForFocusDone());
            assert3ALockState("Lock was set by autoFocus in mode: " + focusMode, type, false);

            // Verify that cancelAutoFocus does not change the lock
            mCamera.cancelAutoFocus();
            assert3ALockState("Lock was set by cancelAutoFocus!", type, false);

            // Verify that autoFocus does not change the lock
            set3ALockState(true, type);
            mCamera.autoFocus(mAutoFocusCallback);
            assert3ALockState("Lock was cleared by autoFocus in mode: " + focusMode, type, true);
            assertTrue(waitForFocusDone());
            assert3ALockState("Lock was cleared by autoFocus in mode: " + focusMode, type, true);

            // Verify that cancelAutoFocus does not change the lock
            mCamera.cancelAutoFocus();
            assert3ALockState("Lock was cleared by cancelAutoFocus!", type, true);
        }
        mCamera.stopPreview();
    }

    private void subtestLockAdditionalAE() {
        // Verify that exposure compensation can be used while
        // AE lock is active
        mCamera.startPreview();
        Parameters parameters = mCamera.getParameters();
        parameters.setAutoExposureLock(true);
        mCamera.setParameters(parameters);
        parameters.setExposureCompensation(parameters.getMaxExposureCompensation());
        mCamera.setParameters(parameters);
        parameters = mCamera.getParameters();
        assertTrue("Could not adjust exposure compensation with AE locked!",
                parameters.getExposureCompensation() ==
                parameters.getMaxExposureCompensation() );

        parameters.setExposureCompensation(parameters.getMinExposureCompensation());
        mCamera.setParameters(parameters);
        parameters = mCamera.getParameters();
        assertTrue("Could not adjust exposure compensation with AE locked!",
                parameters.getExposureCompensation() ==
                parameters.getMinExposureCompensation() );
        mCamera.stopPreview();
    }

    private void subtestLockAdditionalAWB() {
        // Verify that switching AWB modes clears AWB lock
        mCamera.startPreview();
        Parameters parameters = mCamera.getParameters();
        String firstWb = null;
        for ( String wbMode: parameters.getSupportedWhiteBalance() ) {
            if (firstWb == null) {
                firstWb = wbMode;
            }
            parameters.setWhiteBalance(firstWb);
            mCamera.setParameters(parameters);
            parameters.setAutoWhiteBalanceLock(true);
            mCamera.setParameters(parameters);

            parameters.setWhiteBalance(wbMode);
            mCamera.setParameters(parameters);

            if (firstWb == wbMode) {
                assert3ALockState("AWB lock was cleared when WB mode was unchanged!",
                        AUTOWHITEBALANCE_LOCK, true);
            } else {
                assert3ALockState("Changing WB mode did not clear AWB lock!",
                        AUTOWHITEBALANCE_LOCK, false);
            }
        }
        mCamera.stopPreview();
    }

    private void subtestLockInteractions() {
        // Verify that toggling AE does not change AWB lock state
        set3ALockState(false, AUTOWHITEBALANCE_LOCK);
        set3ALockState(false, AUTOEXPOSURE_LOCK);

        set3ALockState(true, AUTOEXPOSURE_LOCK);
        assert3ALockState("Changing AE lock affected AWB lock!",
                AUTOWHITEBALANCE_LOCK, false);

        set3ALockState(false, AUTOEXPOSURE_LOCK);
        assert3ALockState("Changing AE lock affected AWB lock!",
                AUTOWHITEBALANCE_LOCK, false);

        set3ALockState(true, AUTOWHITEBALANCE_LOCK);

        set3ALockState(true, AUTOEXPOSURE_LOCK);
        assert3ALockState("Changing AE lock affected AWB lock!",
                AUTOWHITEBALANCE_LOCK, true);

        set3ALockState(false, AUTOEXPOSURE_LOCK);
        assert3ALockState("Changing AE lock affected AWB lock!",
                AUTOWHITEBALANCE_LOCK, true);

        // Verify that toggling AWB does not change AE lock state
        set3ALockState(false, AUTOWHITEBALANCE_LOCK);
        set3ALockState(false, AUTOEXPOSURE_LOCK);

        set3ALockState(true, AUTOWHITEBALANCE_LOCK);
        assert3ALockState("Changing AWB lock affected AE lock!",
                AUTOEXPOSURE_LOCK, false);

        set3ALockState(false, AUTOWHITEBALANCE_LOCK);
        assert3ALockState("Changing AWB lock affected AE lock!",
                AUTOEXPOSURE_LOCK, false);

        set3ALockState(true, AUTOEXPOSURE_LOCK);

        set3ALockState(true, AUTOWHITEBALANCE_LOCK);
        assert3ALockState("Changing AWB lock affected AE lock!",
                AUTOEXPOSURE_LOCK, true);

        set3ALockState(false, AUTOWHITEBALANCE_LOCK);
        assert3ALockState("Changing AWB lock affected AE lock!",
                AUTOEXPOSURE_LOCK, true);
    }

    private void assert3ALockState(String msg, int type, boolean state) {
        Parameters parameters = mCamera.getParameters();
        switch (type) {
            case AUTOEXPOSURE_LOCK:
                assertTrue(msg, state == parameters.getAutoExposureLock());
                break;
            case AUTOWHITEBALANCE_LOCK:
                assertTrue(msg, state == parameters.getAutoWhiteBalanceLock());
                break;
            default:
                assertTrue("Unknown lock type " + type, false);
                break;
        }
    }

    private void set3ALockState(boolean state, int type) {
        Parameters parameters = mCamera.getParameters();
        switch (type) {
            case AUTOEXPOSURE_LOCK:
                parameters.setAutoExposureLock(state);
                break;
            case AUTOWHITEBALANCE_LOCK:
                parameters.setAutoWhiteBalanceLock(state);
                break;
            default:
                assertTrue("Unknown lock type "+type, false);
                break;
        }
        mCamera.setParameters(parameters);
    }

    @UiThreadTest
    public void testFaceDetection() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testFaceDetectionByCamera(id);
        }
    }

    private void testFaceDetectionByCamera(int cameraId) throws Exception {
        final int FACE_DETECTION_TEST_DURATION = 3000;
        initializeMessageLooper(cameraId);
        mCamera.startPreview();
        Parameters parameters = mCamera.getParameters();
        int maxNumOfFaces = parameters.getMaxNumDetectedFaces();
        assertTrue(maxNumOfFaces >= 0);
        if (maxNumOfFaces == 0) {
            try {
                mCamera.startFaceDetection();
                fail("Should throw an exception if face detection is not supported.");
            } catch (IllegalArgumentException e) {
                // expected
            }
            terminateMessageLooper();
            return;
        }

        mCamera.startFaceDetection();
        try {
            mCamera.startFaceDetection();
            fail("Starting face detection twice should throw an exception");
        } catch (RuntimeException e) {
            // expected
        }
        FaceListener listener = new FaceListener();
        mCamera.setFaceDetectionListener(listener);
        // Sleep some time so the camera has chances to detect faces.
        Thread.sleep(FACE_DETECTION_TEST_DURATION);
        // The face callback runs in another thread. Release the camera and stop
        // the looper. So we do not access the face array from two threads at
        // the same time.
        terminateMessageLooper();

        // Check if the optional fields are supported.
        boolean optionalFieldSupported = false;
        Face firstFace = null;
        for (Face[] faces: listener.mFacesArray) {
            for (Face face: faces) {
                if (face != null) firstFace = face;
            }
        }
        if (firstFace != null) {
            if (firstFace.id != -1 || firstFace.leftEye != null
                    || firstFace.rightEye != null || firstFace.mouth != null) {
                optionalFieldSupported = true;
            }
        }

        // Verify the faces array.
        for (Face[] faces: listener.mFacesArray) {
            testFaces(faces, maxNumOfFaces, optionalFieldSupported);
        }

        // After taking a picture, face detection should be started again.
        // Also make sure autofocus move callback is supported.
        initializeMessageLooper(cameraId);
        mCamera.setAutoFocusMoveCallback(mAutoFocusMoveCallback);
        mCamera.startPreview();
        mCamera.startFaceDetection();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();
        mCamera.startPreview();
        mCamera.startFaceDetection();
        terminateMessageLooper();
    }

    private class FaceListener implements FaceDetectionListener {
        public ArrayList<Face[]> mFacesArray = new ArrayList<Face[]>();

        @Override
        public void onFaceDetection(Face[] faces, Camera camera) {
            mFacesArray.add(faces);
        }
    }

    private void testFaces(Face[] faces, int maxNumOfFaces,
            boolean optionalFieldSupported) {
        Rect bounds = new Rect(-1000, -1000, 1000, 1000);
        assertNotNull(faces);
        assertTrue(faces.length <= maxNumOfFaces);
        for (int i = 0; i < faces.length; i++) {
            Face face = faces[i];
            Rect rect = face.rect;
            // Check the bounds.
            assertNotNull(rect);
            assertTrue(rect.width() > 0);
            assertTrue(rect.height() > 0);
            assertTrue("Coordinates out of bounds. rect=" + rect,
                    bounds.contains(rect) || Rect.intersects(bounds, rect));

            // Check the score.
            assertTrue(face.score >= 1 && face.score <= 100);

            // Check id, left eye, right eye, and the mouth.
            // Optional fields should be all valid or none of them.
            if (!optionalFieldSupported) {
                assertEquals(-1, face.id);
                assertNull(face.leftEye);
                assertNull(face.rightEye);
                assertNull(face.mouth);
            } else {
                assertTrue(face.id != -1);
                assertNotNull(face.leftEye);
                assertNotNull(face.rightEye);
                assertNotNull(face.mouth);
                assertTrue(bounds.contains(face.leftEye.x, face.leftEye.y));
                assertTrue(bounds.contains(face.rightEye.x, face.rightEye.y));
                assertTrue(bounds.contains(face.mouth.x, face.mouth.y));
                // ID should be unique.
                if (i != faces.length - 1) {
                    assertTrue(face.id != faces[i + 1].id);
                }
            }
        }
    }

    @UiThreadTest
    public void testVideoSnapshot() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testVideoSnapshotByCamera(id);
        }
    }

    private static final int[] mCamcorderProfileList = {
        CamcorderProfile.QUALITY_1080P,
        CamcorderProfile.QUALITY_480P,
        CamcorderProfile.QUALITY_720P,
        CamcorderProfile.QUALITY_CIF,
        CamcorderProfile.QUALITY_HIGH,
        CamcorderProfile.QUALITY_LOW,
        CamcorderProfile.QUALITY_QCIF,
        CamcorderProfile.QUALITY_QVGA,
    };

    private void testVideoSnapshotByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Camera.Parameters parameters = mCamera.getParameters();
        terminateMessageLooper();
        if (!parameters.isVideoSnapshotSupported()) {
            return;
        }

        SurfaceHolder holder = getActivity().getSurfaceView().getHolder();

        for (int profileId: mCamcorderProfileList) {
            if (!CamcorderProfile.hasProfile(cameraId, profileId)) {
                continue;
            }
            initializeMessageLooper(cameraId);
            // Set the preview size.
            CamcorderProfile profile = CamcorderProfile.get(cameraId,
                    profileId);
            setPreviewSizeByProfile(parameters, profile);

            // Set the biggest picture size.
            Size biggestSize = mCamera.new Size(-1, -1);
            for (Size size: parameters.getSupportedPictureSizes()) {
                if (biggestSize.width < size.width) {
                    biggestSize = size;
                }
            }
            parameters.setPictureSize(biggestSize.width, biggestSize.height);

            mCamera.setParameters(parameters);
            mCamera.startPreview();
            mCamera.unlock();
            MediaRecorder recorder = new MediaRecorder();
            try {
                recorder.setCamera(mCamera);
                recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
                recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                recorder.setProfile(profile);
                recorder.setOutputFile("/dev/null");
                recorder.setPreviewDisplay(holder.getSurface());
                recorder.prepare();
                recorder.start();
                subtestTakePictureByCamera(true,
                        profile.videoFrameWidth, profile.videoFrameHeight);
                testJpegExifByCamera(true);
                testJpegThumbnailSizeByCamera(true,
                        profile.videoFrameWidth, profile.videoFrameHeight);
                Thread.sleep(2000);
                recorder.stop();
            } finally {
                recorder.release();
                mCamera.lock();
            }
            mCamera.stopPreview();
            terminateMessageLooper();
        }
    }

    public void testPreviewCallbackWithPicture() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testPreviewCallbackWithPictureByCamera(id);
        }
    }

    private void testPreviewCallbackWithPictureByCamera(int cameraId)
            throws Exception {
        initializeMessageLooper(cameraId);

        SimplePreviewStreamCb callback = new SimplePreviewStreamCb(1);
        mCamera.setPreviewCallback(callback);

        Log.v(TAG, "Starting preview");
        mCamera.startPreview();

        // Wait until callbacks are flowing
        for (int i = 0; i < 30; i++) {
            assertTrue("testPreviewCallbackWithPicture: Not receiving preview callbacks!",
                    mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE ) );
            mPreviewDone.close();
        }

        // Now take a picture
        Log.v(TAG, "Taking picture now");

        Size pictureSize = mCamera.getParameters().getPictureSize();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback,
                mJpegPictureCallback);

        waitForSnapshotDone();

        assertTrue("Shutter callback not received", mShutterCallbackResult);
        assertTrue("Raw picture callback not received", mRawPictureCallbackResult);
        assertTrue("Jpeg picture callback not received", mJpegPictureCallbackResult);
        assertNotNull(mJpegData);
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions);
        assertEquals(pictureSize.width, bmpOptions.outWidth);
        assertEquals(pictureSize.height, bmpOptions.outHeight);

        // Restart preview, confirm callbacks still happen
        Log.v(TAG, "Restarting preview");
        mCamera.startPreview();

        for (int i = 0; i < 30; i++) {
            assertTrue("testPreviewCallbackWithPicture: Not receiving preview callbacks!",
                    mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE ) );
            mPreviewDone.close();
        }

        mCamera.stopPreview();

        terminateMessageLooper();
    }

    public void testEnableShutterSound() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testEnableShutterSoundByCamera(id);
        }
    }

    private void testEnableShutterSoundByCamera(int id) throws Exception {
        CameraInfo info = new CameraInfo();

        Camera.getCameraInfo(id, info);

        initializeMessageLooper(id);

        boolean result;
        Log.v(TAG, "testEnableShutterSoundByCamera: canDisableShutterSound: " +
                info.canDisableShutterSound);
        result = mCamera.enableShutterSound(false);
        assertTrue(result == info.canDisableShutterSound);
        result = mCamera.enableShutterSound(true);
        assertTrue(result);

        terminateMessageLooper();
    }

}
