/*
 * 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.content.pm.PackageManager;
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.hardware.cts.helpers.CameraUtils;
import android.media.CamcorderProfile;
import android.media.ExifInterface;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.ConditionVariable;
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
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.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;

import junit.framework.AssertionFailedError;

/**
 * This test case must run with hardware. It can't be tested in emulator
 */
@AppModeFull
@LargeTest
public class CameraTest extends ActivityInstrumentationTestCase2<CameraCtsActivity> {
    private static final String TAG = "CameraTest";
    private static final String PACKAGE = "android.hardware.cts";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    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;

    // For external camera recording
    private static final int DEFAULT_VIDEO_WIDTH = 176;
    private static final int DEFAULT_VIDEO_HEIGHT = 144;
    private static final int VIDEO_BIT_RATE_IN_BPS = 128000;

    // Some exif tags that are not defined by ExifInterface but supported.
    private static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
    private static final String TAG_SUBSEC_TIME = "SubSecTime";
    private static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
    private static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";

    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;
    boolean mIsExternalCamera;

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

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        // to starCtsActivity.
        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 {
                    mIsExternalCamera = CameraUtils.isExternal(
                            getInstrumentation().getContext(), cameraId);
                } catch (Exception e) {
                    Log.e(TAG, "Unable to query external camera!" + e);
                }

                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 (VERBOSE) 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 {
        terminateMessageLooper(false);
    }

    /*
     * Terminates the message looper thread, optionally allowing evict error
     */
    private void terminateMessageLooper(boolean allowEvict) 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;
        if (allowEvict) {
            assertTrue("Got unexpected camera error callback.",
                    (NO_ERROR == mCameraErrorCode ||
                    Camera.CAMERA_ERROR_EVICTED == mCameraErrorCode));
        } else {
            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 (VERBOSE) {
            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 (VERBOSE) {
                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 (VERBOSE) Log.v(TAG, "notify the preview callback");
            mPreviewDone.open();
            if (VERBOSE) Log.v(TAG, "Preview callback stop");
        }
    }

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

    //Implement the RawPictureCallback
    private final class RawPictureCallback implements PictureCallback {
        public void onPictureTaken(byte [] rawData, Camera camera) {
            mRawPictureCallbackResult = true;
            if (VERBOSE) 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 (VERBOSE) {
                        Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawData.length);
                    }
                } else {
                    mJpegPictureCallbackResult = false;
                }
                mSnapshotDone.open();
                if (VERBOSE) 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 (VERBOSE) 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 (VERBOSE) Log.v(TAG, "check preview callback");
        mCamera.startPreview();
        waitForPreviewDone();
        mCamera.setPreviewCallback(null);
    }

    /**
     * Start preview and wait for the first preview callback, which indicates the
     * preview becomes active.
     */
    private void blockingStartPreview() {
        mCamera.setPreviewCallback(new SimplePreviewStreamCb(/*Id*/0));
        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 (VERBOSE) 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();

        Size QCIF = mCamera.new Size(176, 144);
        Size VGA = mCamera.new Size(640, 480);
        Size defaultPicSize = parameters.getPictureSize();

        for (Size size: parameters.getSupportedPreviewSizes()) {
            mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
            mCamera.setPreviewCallback(mPreviewCallback);
            parameters.setPreviewSize(size.width, size.height);
            if (size.equals(QCIF)) {
                parameters.setPictureSize(VGA.width, VGA.height);
            } else {
                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.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 testStabilizationOneShotPreviewCallback() throws Exception {
        int nCameras = Camera.getNumberOfCameras();
        for (int id = 0; id < nCameras; id++) {
            Log.v(TAG, "Camera id=" + id);
            testStabilizationOneShotPreviewCallbackByCamera(id);
        }
    }

    private void testStabilizationOneShotPreviewCallbackByCamera(int cameraId) throws Exception {
        initializeMessageLooper(cameraId);
        Parameters params = mCamera.getParameters();
        if(!params.isVideoStabilizationSupported()) {
            terminateMessageLooper();
            return;
        }
        //Check whether we can support preview callbacks along with stabilization
        params.setVideoStabilization(true);
        mCamera.setParameters(params);
        mCamera.setOneShotPreviewCallback(mPreviewCallback);
        checkPreviewCallback();
        terminateMessageLooper();
        assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);
    }

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

        if (mIsExternalCamera) {
            // External camera by default reports -1.0, but don't fail if
            // the HAL implementation somehow chooses to report this information.
            assertTrue(focalLength == -1.0 || focalLength > 0);
            assertTrue(horizontalViewAngle == -1.0 ||
                    (horizontalViewAngle > 0 && horizontalViewAngle <= 360));
            assertTrue(verticalViewAngle == -1.0 ||
                    (verticalViewAngle > 0 && verticalViewAngle <= 360));
        } else {
            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)));
        Size pictureSize = p.getPictureSize();

        // 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());
        // Primary image should still be valid for no thumbnail capture.
        BitmapFactory.decodeFile(JPEG_PATH, bmpOptions);
        if (!recording) {
            assertTrue("Jpeg primary image size should match requested size",
                    bmpOptions.outWidth == pictureSize.width &&
                    bmpOptions.outHeight == pictureSize.height);
        } else {
            assertTrue(bmpOptions.outWidth >= recordingWidth ||
                    bmpOptions.outWidth == size.width);
            assertTrue(bmpOptions.outHeight >= recordingHeight ||
                    bmpOptions.outHeight == size.height);
        }

        assertNotNull("Jpeg primary image data should be decodable",
                BitmapFactory.decodeFile(JPEG_PATH));
    }

    @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 {
        if (!recording) mCamera.startPreview();
        // Get current time in milliseconds, removing the millisecond part
        long captureStartTime = System.currentTimeMillis() / 1000 * 1000;
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
        waitForSnapshotDone();

        Camera.Parameters parameters = mCamera.getParameters();
        double focalLength = parameters.getFocalLength();

        // Test various exif tags.
        ExifInterface exif = new ExifInterface(JPEG_PATH);
        StringBuffer failedCause = new StringBuffer("Jpeg exif test failed:\n");
        boolean extraExiftestPassed = checkExtraExifTagsSucceeds(failedCause, exif);

        if (VERBOSE) Log.v(TAG, "Testing exif tag TAG_DATETIME");
        String datetime = exif.getAttribute(ExifInterface.TAG_DATETIME);
        assertNotNull(datetime);
        assertTrue(datetime.length() == 19); // EXIF spec is "yyyy:MM:dd HH:mm:ss".
        // Datetime should be local time.
        SimpleDateFormat exifDateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
        try {
            Date exifDateTime = exifDateFormat.parse(datetime);
            long captureFinishTime = exifDateTime.getTime();
            long timeDelta = captureFinishTime - captureStartTime;
            assertTrue(String.format("Snapshot delay (%d ms) is not in range of [0, %d]", timeDelta,
                    WAIT_FOR_SNAPSHOT_TO_COMPLETE),
                    timeDelta >= 0 && timeDelta <= WAIT_FOR_SNAPSHOT_TO_COMPLETE);
        } catch (ParseException e) {
            fail(String.format("Invalid string value on exif tag TAG_DATETIME: %s", datetime));
        }
        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.
        if (VERBOSE) Log.v(TAG, "Testing exif GPS 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 (VERBOSE) Log.v(TAG, "Testing exif GPS tag removal");
        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);
    }

    /**
     * Sanity check of some extra exif tags.
     * <p>
     * Sanity check some extra exif tags without asserting the check failures
     * immediately. When a failure is detected, the failure cause is logged,
     * the rest of the tests are still executed. The caller can assert with the
     * failure cause based on the returned test status.
     * </p>
     *
     * @param logBuf Log failure cause to this StringBuffer if there is
     * any failure.
     * @param exif The exif data associated with a jpeg image being tested.
     * @return true if no test failure is found, false if there is any failure.
     */
    private boolean checkExtraExifTagsSucceeds(StringBuffer logBuf, ExifInterface exif) {
        if (logBuf == null || exif == null) {
            throw new IllegalArgumentException("failureCause and exif shouldn't be null");
        }

        if (VERBOSE) Log.v(TAG, "Testing extra exif tags");
        boolean allTestsPassed = true;
        boolean passedSoFar = true;
        String failureMsg;

        // TAG_EXPOSURE_TIME
        // ExifInterface API gives exposure time value in the form of float instead of rational
        String exposureTime = exif.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
        passedSoFar = expectNotNull("Exif TAG_EXPOSURE_TIME is null!", logBuf, exposureTime);
        if (passedSoFar) {
            double exposureTimeValue = Double.parseDouble(exposureTime);
            failureMsg = "Exif exposure time " + exposureTime + " should be a positive value";
            passedSoFar = expectTrue(failureMsg, logBuf, exposureTimeValue > 0);
        }
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_APERTURE
        // ExifInterface API gives aperture value in the form of float instead of rational
        String aperture = exif.getAttribute(ExifInterface.TAG_APERTURE);
        passedSoFar = expectNotNull("Exif TAG_APERTURE is null!", logBuf, aperture);
        if (passedSoFar) {
            double apertureValue = Double.parseDouble(aperture);
            passedSoFar = expectTrue("Exif TAG_APERTURE value " + aperture + " should be positive!",
                    logBuf, apertureValue > 0);
        }
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_FLASH
        String flash = exif.getAttribute(ExifInterface.TAG_FLASH);
        passedSoFar = expectNotNull("Exif TAG_FLASH is null!", logBuf, flash);
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_WHITE_BALANCE
        String whiteBalance = exif.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
        passedSoFar = expectNotNull("Exif TAG_WHITE_BALANCE is null!", logBuf, whiteBalance);
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_MAKE
        String make = exif.getAttribute(ExifInterface.TAG_MAKE);
        passedSoFar = expectNotNull("Exif TAG_MAKE is null!", logBuf, make);
        if (passedSoFar) {
            passedSoFar = expectTrue("Exif TAG_MODEL value: " + make
                    + " should match build manufacturer: " + Build.MANUFACTURER, logBuf,
                    make.equals(Build.MANUFACTURER));
        }
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_MODEL
        String model = exif.getAttribute(ExifInterface.TAG_MODEL);
        passedSoFar = expectNotNull("Exif TAG_MODEL is null!", logBuf, model);
        if (passedSoFar) {
            passedSoFar = expectTrue("Exif TAG_MODEL value: " + model
                    + " should match build manufacturer: " + Build.MODEL, logBuf,
                    model.equals(Build.MODEL));
        }
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_ISO
        int iso = exif.getAttributeInt(ExifInterface.TAG_ISO, -1);
        passedSoFar = expectTrue("Exif ISO value " + iso + " is invalid", logBuf, iso > 0);
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
        String digitizedTime = exif.getAttribute(TAG_DATETIME_DIGITIZED);
        passedSoFar = expectNotNull("Exif TAG_DATETIME_DIGITIZED is null!", logBuf, digitizedTime);
        if (passedSoFar) {
            String datetime = exif.getAttribute(ExifInterface.TAG_DATETIME);
            passedSoFar = expectNotNull("Exif TAG_DATETIME is null!", logBuf, datetime);
            if (passedSoFar) {
                passedSoFar = expectTrue("dataTime should match digitizedTime", logBuf,
                        digitizedTime.equals(datetime));
            }
        }
        allTestsPassed = allTestsPassed && passedSoFar;

        /**
         * TAG_SUBSEC_TIME. Since the sub second tag strings are truncated to at
         * most 9 digits in ExifInterface implementation, use getAttributeInt to
         * sanitize it. When the default value -1 is returned, it means that
         * this exif tag either doesn't exist or is a non-numerical invalid
         * string. Same rule applies to the rest of sub second tags.
         */
        int subSecTime = exif.getAttributeInt(TAG_SUBSEC_TIME, -1);
        passedSoFar = expectTrue(
                "Exif TAG_SUBSEC_TIME value is null or invalid!", logBuf, subSecTime > 0);
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_SUBSEC_TIME_ORIG
        int subSecTimeOrig = exif.getAttributeInt(TAG_SUBSEC_TIME_ORIG, -1);
        passedSoFar = expectTrue(
                "Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!", logBuf, subSecTimeOrig > 0);
        allTestsPassed = allTestsPassed && passedSoFar;

        // TAG_SUBSEC_TIME_DIG
        int subSecTimeDig = exif.getAttributeInt(TAG_SUBSEC_TIME_DIG, -1);
        passedSoFar = expectTrue(
                "Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", logBuf, subSecTimeDig > 0);
        allTestsPassed = allTestsPassed && passedSoFar;

        return allTestsPassed;
    }

    /**
     * Check if object is null and log failure msg.
     *
     * @param msg Failure msg.
     * @param logBuffer StringBuffer to log the failure msg.
     * @param obj Object to test.
     * @return true if object is not null, otherwise return false.
     */
    private boolean expectNotNull(String msg, StringBuffer logBuffer, Object obj)
    {
        if (obj == null) {
            logBuffer.append(msg + "\n");
        }
        return (obj != null);
    }

    /**
     * Check if condition is false and log failure msg.
     *
     * @param msg Failure msg.
     * @param logBuffer StringBuffer to log the failure msg.
     * @param condition Condition to test.
     * @return The value of the condition.
     */
    private boolean expectTrue(String msg, StringBuffer logBuffer, boolean condition) {
        if (!condition) {
            logBuffer.append(msg + "\n");
        }
        return condition;
    }

    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, getGpsDateTimeFromJpeg(exif) / 1000);
    }

    private long getGpsDateTimeFromJpeg(ExifInterface exif) {
        String date = exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
        String time = exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
        if (date == null || time == null) return -1;

        String dateTimeString = date + ' ' + time;
        ParsePosition pos = new ParsePosition(0);
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

            Date datetime = formatter.parse(dateTimeString, pos);
            if (datetime == null) return -1;
            return datetime.getTime();
        } catch (IllegalArgumentException ex) {
            return -1;
        }
    }

    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 = null; // Used for built-in camera
        Camera.Size videoSize = null; // Used for external camera

        // Set the preview size.
        if (mIsExternalCamera) {
            videoSize = setupExternalCameraRecord(parameters);
        } else {
            profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW);
            setPreviewSizeByProfile(parameters, profile);
        }

        mCamera.setParameters(parameters);
        mCamera.setPreviewDisplay(surfaceHolder);
        mCamera.startPreview();
        mCamera.lock();  // Locking again from the same process has no effect.
        try {
            if (mIsExternalCamera) {
                recordVideoBySize(videoSize, surfaceHolder);
            } else {
                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
        }

        if (mIsExternalCamera) {
            recordVideoBySize(videoSize, surfaceHolder);
        } else {
            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 Camera.Size setupExternalCameraRecord(Parameters parameters) {
        assertTrue(parameters.getSupportedVideoSizes() != null);
        assertTrue(parameters.getSupportedVideoSizes().size() > 0);

        Camera.Size videoSize = null;
        for (Camera.Size sz : parameters.getSupportedVideoSizes()) {
            if (sz.width >= DEFAULT_VIDEO_WIDTH && sz.height >= DEFAULT_VIDEO_HEIGHT) {
                videoSize = sz;
                break;
            }
        }
        assertNotNull(videoSize);
        parameters.setPreviewSize(videoSize.width, videoSize.height);
        return videoSize;
    }

    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 recordVideoBySize(Camera.Size size,
            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.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            recorder.setVideoEncodingBitRate(VIDEO_BIT_RATE_IN_BPS);
            recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
            recorder.setVideoSize(size.width, size.height);
            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();
        }
    }

    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();
        Size QCIF = mCamera.new Size(176, 144);
        Size VGA = mCamera.new Size(640, 480);
        Size defaultPicSize = parameters.getPictureSize();

        // Test all preview sizes.
        for (Size size: parameters.getSupportedPreviewSizes()) {
            if (size.equals(QCIF)) {
                parameters.setPictureSize(VGA.width, VGA.height);
            } else {
                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.height);
            }
            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;
        }

        Size QCIF = mCamera.new Size(176, 144);
        Size VGA = mCamera.new Size(640, 480);
        Size defaultPicSize = parameters.getPictureSize();

        // 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);
            if (size.equals(QCIF)) {
                parameters.setPictureSize(VGA.width, VGA.height);
            } else {
                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.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));
            }
            blockingStartPreview();

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

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

    // API exception on QCIF size. QCIF size along with anything larger than
    // 1920x1080 on either width/height is not guaranteed to be supported.
    private boolean isWaivedCombination(Size previewSize, Size pictureSize) {
        Size QCIF = mCamera.new Size(176, 144);
        Size FULL_HD = mCamera.new Size(1920, 1080);
        if (previewSize.equals(QCIF) && (pictureSize.width > FULL_HD.width ||
                pictureSize.height > FULL_HD.height)) {
            return true;
        }
        if (pictureSize.equals(QCIF) && (previewSize.width > FULL_HD.width ||
                previewSize.height > FULL_HD.height)) {
            return true;
        }
        return false;
    }

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

        // Test all combination of preview sizes and picture sizes.
        for (Size previewSize: parameters.getSupportedPreviewSizes()) {
            for (Size pictureSize: parameters.getSupportedPictureSizes()) {
                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);
                try {
                    mCamera.setParameters(parameters);
                } catch (RuntimeException e) {
                    if (isWaivedCombination(previewSize, pictureSize)) {
                        Log.i(TAG, String.format("Preview %dx%d and still %dx%d combination is" +
                                "waived", previewSize.width, previewSize.height,
                                pictureSize.width, pictureSize.height));
                        continue;
                    }
                    throw e;
                }

                assertEquals(previewSize, mCamera.getParameters().getPreviewSize());
                assertEquals(pictureSize, mCamera.getParameters().getPictureSize());

                // Check if the preview size is the same as requested.
                try {
                    mCamera.startPreview();
                } catch (RuntimeException e) {
                    if (isWaivedCombination(previewSize, pictureSize)) {
                        Log.i(TAG, String.format("Preview %dx%d and still %dx%d combination is" +
                                "waived", previewSize.width, previewSize.height,
                                pictureSize.width, pictureSize.height));
                        continue;
                    }
                    throw e;
                }
                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.
        final int INTERVAL_ERROR_THRESHOLD = 10;
        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();
            // See if any frame duration violations occurred during preview run
            AssertionFailedError e = callback.getDurationException();
            if (e != null) throw(e);
            int numIntervalError = callback.getNumIntervalError();
            if (numIntervalError > INTERVAL_ERROR_THRESHOLD) {
                fail(String.format(
                        "Too many preview callback frame intervals out of bounds: " +
                                "Count is %d, limit is %d",
                        numIntervalError, INTERVAL_ERROR_THRESHOLD));
            }
        }

        // 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;
        private AssertionFailedError mDurationException = null;
        private int numIntervalError;

        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;
            mDurationException = null;
            numIntervalError = 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 = SystemClock.elapsedRealtime();
            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;
                if (mIsExternalCamera) {
                    intervalMargin = 0.8;
                }
                long lastArrivalTime = mFrames.get(mFrames.size() - 1);
                double interval = arrivalTime - lastArrivalTime;
                if (VERBOSE) Log.v(TAG, "Frame interval=" + interval);

                try {
                    if (interval > mMaxFrameInterval * (1.0 + intervalMargin) ||
                            interval < mMinFrameInterval * (1.0 - intervalMargin)) {
                        Log.i(TAG, "Bad frame interval=" + interval + "ms. Out out range " +
                                mMinFrameInterval * (1.0 - intervalMargin) + "/" +
                                mMaxFrameInterval * (1.0 + intervalMargin));
                        numIntervalError++;
                    }
                    // Check if the fps is within range.
                    double fpsMargin = 0.5; // x100 = percent
                    if (mIsExternalCamera) {
                        fpsMargin = 0.6;
                    }
                    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));
                } catch (AssertionFailedError e) {
                    // Need to throw this only in the test body, instead of in
                    // the callback
                    if (mDurationException == null) {
                        mDurationException = e;
                    }
                }
            }
            // Add the arrival time of this frame to the list.
            mFrames.add(arrivalTime);
        }

        public AssertionFailedError getDurationException() {
            return mDurationException;
        }
        public int getNumIntervalError() {
            return numIntervalError;
        }
    }

    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.
            blockingStartPreview();
            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 (VERBOSE) 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 (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Opening camera 0");
        initializeMessageLooper(0);
        SimplePreviewStreamCb callback0 = new SimplePreviewStreamCb(0);
        mCamera.setPreviewCallback(callback0);
        if (VERBOSE) 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 (VERBOSE) 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 (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Opening camera 1");
        initializeMessageLooper(1);
        SimplePreviewStreamCb callback1 = new SimplePreviewStreamCb(1);
        mCamera.setPreviewCallback(callback1);
        if (VERBOSE) 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 (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Releasing camera 0");
                firstCamera.release();
            }
        }
        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
        mCamera.stopPreview();

        firstLooper.quit();
        terminateMessageLooper(true/*allowEvict*/);
    }

    // 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 (VERBOSE) 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 = null; // for built-in camera
        Camera.Size videoSize = null; // for external camera

        if (mIsExternalCamera) {
            videoSize = setupExternalCameraRecord(parameters);
        } else {
            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();
            if (mIsExternalCamera) {
                recordVideoSimpleBySize(videoSize, holder);
            } else {
                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 recordVideoSimpleBySize(Camera.Size size,
            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.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            recorder.setVideoEncodingBitRate(VIDEO_BIT_RATE_IN_BPS);
            recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
            recorder.setVideoSize(size.width, size.height);
            recorder.setOutputFile("/dev/null");
            recorder.setPreviewDisplay(holder.getSurface());
            recorder.prepare();
            recorder.start();
            Thread.sleep(2000);
            recorder.stop();
        } finally {
            recorder.release();
            mCamera.lock();
        }
    }

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

    public void testCameraExternalConnected() {
        if (getActivity().getPackageManager().
                hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL) ) {
            int nCameras = Camera.getNumberOfCameras();
            assertTrue("Devices with external camera support must have a camera connected for " +
                    "testing",
                    nCameras > 0);
            for (int id = 0; id < nCameras; id++) {
                try {
                    Camera c = Camera.open(id);
                    c.release();
                } catch (Throwable e) {
                    throw new AssertionError("Devices with external camera support must " +
                            "have all listed cameras be connected and openable for testing", e);
                }
            }
        }
    }
}
