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

import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.EncoderCapabilities;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.media.EncoderCapabilities.VideoEncoderCap;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.media.MediaMetadataRetriever;
import android.opengl.GLES20;
import android.os.ConditionVariable;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.support.test.filters.SmallTest;
import android.platform.test.annotations.RequiresDevice;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.view.Surface;

import android.util.Log;

import com.android.compatibility.common.util.MediaUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.InterruptedException;
import java.lang.Runnable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static android.media.MediaCodecInfo.CodecProfileLevel.*;

@SmallTest
@RequiresDevice
public class MediaRecorderTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
    private final String TAG = "MediaRecorderTest";
    private final String OUTPUT_PATH;
    private final String OUTPUT_PATH2;
    private static final float TOLERANCE = 0.0002f;
    private static final int RECORD_TIME_MS = 3000;
    private static final int RECORD_TIME_LAPSE_MS = 6000;
    private static final int RECORD_TIME_LONG_MS = 20000;
    private static final int RECORDED_DUR_TOLERANCE_MS = 1000;
    // Tolerate 4 frames off at maximum
    private static final float RECORDED_DUR_TOLERANCE_FRAMES = 4f;
    private static final int VIDEO_WIDTH = 176;
    private static final int VIDEO_HEIGHT = 144;
    private static int mVideoWidth = VIDEO_WIDTH;
    private static int mVideoHeight = VIDEO_HEIGHT;
    private static final int VIDEO_BIT_RATE_IN_BPS = 128000;
    private static final double VIDEO_TIMELAPSE_CAPTURE_RATE_FPS = 1.0;
    private static final int AUDIO_BIT_RATE_IN_BPS = 12200;
    private static final int AUDIO_NUM_CHANNELS = 1;
    private static final int AUDIO_SAMPLE_RATE_HZ = 8000;
    private static final long MAX_FILE_SIZE = 5000;
    private static final int MAX_FILE_SIZE_TIMEOUT_MS = 5 * 60 * 1000;
    private static final int MAX_DURATION_MSEC = 2000;
    private static final float LATITUDE = 0.0000f;
    private static final float LONGITUDE  = -180.0f;
    private static final int NORMAL_FPS = 30;
    private static final int TIME_LAPSE_FPS = 5;
    private static final int SLOW_MOTION_FPS = 120;
    private static final List<VideoEncoderCap> mVideoEncoders =
            EncoderCapabilities.getVideoEncoders();

    private boolean mOnInfoCalled;
    private boolean mOnErrorCalled;
    private File mOutFile;
    private File mOutFile2;
    private Camera mCamera;
    private MediaStubActivity mActivity = null;
    private int mFileIndex;

    private MediaRecorder mMediaRecorder;
    private ConditionVariable mMaxDurationCond;
    private ConditionVariable mMaxFileSizeCond;
    private ConditionVariable mMaxFileSizeApproachingCond;
    private ConditionVariable mNextOutputFileStartedCond;
    private boolean mExpectMaxFileCond;

    // movie length, in frames
    private static final int NUM_FRAMES = 120;

    private static final int TEST_R0 = 0;                   // RGB equivalent of {0,0,0} (BT.601)
    private static final int TEST_G0 = 136;
    private static final int TEST_B0 = 0;
    private static final int TEST_R1 = 236;                 // RGB equivalent of {120,160,200} (BT.601)
    private static final int TEST_G1 = 50;
    private static final int TEST_B1 = 186;

    private final static String AVC = MediaFormat.MIMETYPE_VIDEO_AVC;

    public MediaRecorderTest() {
        super("android.media.cts", MediaStubActivity.class);
        OUTPUT_PATH = new File(Environment.getExternalStorageDirectory(),
                "record.out").getAbsolutePath();
        OUTPUT_PATH2 = new File(Environment.getExternalStorageDirectory(),
                "record2.out").getAbsolutePath();
    }

    private void completeOnUiThread(final Runnable runnable) {
        final CountDownLatch latch = new CountDownLatch(1);
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                runnable.run();
                latch.countDown();
            }
        });
        try {
            // if UI thread does not run, things will fail anyway
            assertTrue(latch.await(10, TimeUnit.SECONDS));
        } catch (java.lang.InterruptedException e) {
            fail("should not be interrupted");
        }
    }

    @Override
    protected void setUp() throws Exception {
        mActivity = getActivity();
        completeOnUiThread(new Runnable() {
            @Override
            public void run() {
                mMediaRecorder = new MediaRecorder();
                mOutFile = new File(OUTPUT_PATH);
                mOutFile2 = new File(OUTPUT_PATH2);
                mFileIndex = 0;

                mMaxDurationCond = new ConditionVariable();
                mMaxFileSizeCond = new ConditionVariable();
                mMaxFileSizeApproachingCond = new ConditionVariable();
                mNextOutputFileStartedCond = new ConditionVariable();
                mExpectMaxFileCond = true;

                mMediaRecorder.setOutputFile(OUTPUT_PATH);
                mMediaRecorder.setOnInfoListener(new OnInfoListener() {
                    public void onInfo(MediaRecorder mr, int what, int extra) {
                        mOnInfoCalled = true;
                        if (what ==
                            MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
                            Log.v(TAG, "max duration reached");
                            mMaxDurationCond.open();
                        } else if (what ==
                            MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
                            Log.v(TAG, "max file size reached");
                            mMaxFileSizeCond.open();
                        }
                    }
                });
                mMediaRecorder.setOnErrorListener(new OnErrorListener() {
                    public void onError(MediaRecorder mr, int what, int extra) {
                        mOnErrorCalled = true;
                    }
                });
            }
        });
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        if (mMediaRecorder != null) {
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
        if (mOutFile != null && mOutFile.exists()) {
            mOutFile.delete();
        }
        if (mOutFile2 != null && mOutFile2.exists()) {
            mOutFile2.delete();
        }
        if (mCamera != null)  {
            mCamera.release();
            mCamera = null;
        }
        mMaxDurationCond.close();
        mMaxDurationCond = null;
        mMaxFileSizeCond.close();
        mMaxFileSizeCond = null;
        mMaxFileSizeApproachingCond.close();
        mMaxFileSizeApproachingCond = null;
        mNextOutputFileStartedCond.close();
        mNextOutputFileStartedCond = null;
        mActivity = null;
        super.tearDown();
    }

    public void testRecorderCamera() throws Exception {
        int width;
        int height;
        Camera camera = null;
        if (!hasCamera()) {
            return;
        }
        // Try to get camera profile for QUALITY_LOW; if unavailable,
        // set the video size to default value.
        CamcorderProfile profile = CamcorderProfile.get(
                0 /* cameraId */, CamcorderProfile.QUALITY_LOW);
        if (profile != null) {
            width = profile.videoFrameWidth;
            height = profile.videoFrameHeight;
        } else {
            width = VIDEO_WIDTH;
            height = VIDEO_HEIGHT;
        }
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
        mMediaRecorder.setVideoSize(width, height);
        mMediaRecorder.setVideoEncodingBitRate(VIDEO_BIT_RATE_IN_BPS);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.prepare();
        mMediaRecorder.start();
        Thread.sleep(RECORD_TIME_MS);


        // verify some getMetrics() behaviors while we're here.
        PersistableBundle metrics = mMediaRecorder.getMetrics();
        if (metrics == null) {
            fail("MediaRecorder.getMetrics() returned null metrics");
        } else if (metrics.isEmpty()) {
            fail("MediaRecorder.getMetrics() returned empty metrics");
        } else {
            int size = metrics.size();
            Set<String> keys = metrics.keySet();

            if (size == 0) {
                fail("MediaRecorder.getMetrics().size() reports empty record");
            }

            if (keys == null) {
                fail("MediaMetricsSet returned no keys");
            } else if (keys.size() != size) {
                fail("MediaMetricsSet.keys().size() mismatch MediaMetricsSet.size()");
            }

            // ensure existence of some known fields
            int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
            if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
                fail("getMetrics() videoEncodeBitrate set " +
                     VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
            }

            // valid values are -1.0 and >= 0;
            // tolerate some floating point rounding variability
            double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -2);
            if (captureFrameRate < 0.) {
                assertEquals("getMetrics() capture framerate=" + captureFrameRate, -1.0, captureFrameRate, 0.001);
            }
        }


        mMediaRecorder.stop();
        checkOutputExist();
    }

    public void testRecorderMPEG2TS() throws Exception {
        int width;
        int height;
        Camera camera = null;
        if (!hasCamera()) {
            MediaUtils.skipTest("no camera");
            return;
        }
        if (!hasMicrophone() || !hasAac()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        // Try to get camera profile for QUALITY_LOW; if unavailable,
        // set the video size to default value.
        CamcorderProfile profile = CamcorderProfile.get(
                0 /* cameraId */, CamcorderProfile.QUALITY_LOW);
        if (profile != null) {
            width = profile.videoFrameWidth;
            height = profile.videoFrameHeight;
        } else {
            width = VIDEO_WIDTH;
            height = VIDEO_HEIGHT;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.setVideoSize(width, height);
        mMediaRecorder.setVideoEncodingBitRate(VIDEO_BIT_RATE_IN_BPS);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.prepare();
        mMediaRecorder.start();
        Thread.sleep(RECORD_TIME_MS);

        // verify some getMetrics() behaviors while we're here.
        PersistableBundle metrics = mMediaRecorder.getMetrics();
        if (metrics == null) {
            fail("MediaRecorder.getMetrics() returned null metrics");
        } else if (metrics.isEmpty()) {
            fail("MediaRecorder.getMetrics() returned empty metrics");
        } else {
            int size = metrics.size();
            Set<String> keys = metrics.keySet();

            if (size == 0) {
                fail("MediaRecorder.getMetrics().size() reports empty record");
            }

            if (keys == null) {
                fail("MediaMetricsSet returned no keys");
            } else if (keys.size() != size) {
                fail("MediaMetricsSet.keys().size() mismatch MediaMetricsSet.size()");
            }

            // ensure existence of some known fields
            int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
            if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
                fail("getMetrics() videoEncodeBitrate set " +
                     VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
            }

            // valid values are -1.0 and >= 0;
            // tolerate some floating point rounding variability
            double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -2);
            if (captureFrameRate < 0.) {
                assertEquals("getMetrics() capture framerate=" + captureFrameRate, -1.0, captureFrameRate, 0.001);
            }
        }

        mMediaRecorder.stop();
        checkOutputExist();
    }

    @UiThreadTest
    public void testSetCamera() throws Exception {
        recordVideoUsingCamera(false, false);
    }

    public void testRecorderTimelapsedVideo() throws Exception {
        recordVideoUsingCamera(true, false);
    }

    public void testRecorderPauseResume() throws Exception {
        recordVideoUsingCamera(false, true);
    }

    public void testRecorderPauseResumeOnTimeLapse() throws Exception {
        recordVideoUsingCamera(true, true);
    }

    private void recordVideoUsingCamera(boolean timelapse, boolean pause) throws Exception {
        int nCamera = Camera.getNumberOfCameras();
        int durMs = timelapse? RECORD_TIME_LAPSE_MS: RECORD_TIME_MS;
        for (int cameraId = 0; cameraId < nCamera; cameraId++) {
            mCamera = Camera.open(cameraId);
            setSupportedResolution(mCamera);
            recordVideoUsingCamera(mCamera, OUTPUT_PATH, durMs, timelapse, pause);
            mCamera.release();
            mCamera = null;
            assertTrue(checkLocationInFile(OUTPUT_PATH));
        }
    }

    private void setSupportedResolution(Camera camera) {
        Camera.Parameters parameters = camera.getParameters();
        List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes();
        // getSupportedVideoSizes returns null when separate video/preview size
        // is not supported.
        if (videoSizes == null) {
            videoSizes = parameters.getSupportedPreviewSizes();
        }
        int minVideoWidth = Integer.MAX_VALUE;
        int minVideoHeight = Integer.MAX_VALUE;
        for (Camera.Size size : videoSizes)
        {
            if (size.width == VIDEO_WIDTH && size.height == VIDEO_HEIGHT) {
                mVideoWidth = VIDEO_WIDTH;
                mVideoHeight = VIDEO_HEIGHT;
                return;
            }
            if (size.width < minVideoWidth || size.height < minVideoHeight) {
                minVideoWidth = size.width;
                minVideoHeight = size.height;
            }
        }
        // Use minimum resolution to avoid that one frame size exceeds file size limit.
        mVideoWidth = minVideoWidth;
        mVideoHeight = minVideoHeight;
    }

    private void recordVideoUsingCamera(
            Camera camera, String fileName, int durMs, boolean timelapse, boolean pause)
        throws Exception {
        // FIXME:
        // We should add some test case to use Camera.Parameters.getPreviewFpsRange()
        // to get the supported video frame rate range.
        Camera.Parameters params = camera.getParameters();
        int frameRate = params.getPreviewFrameRate();

        camera.unlock();
        mMediaRecorder.setCamera(camera);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        mMediaRecorder.setVideoFrameRate(frameRate);
        mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.setOutputFile(fileName);
        mMediaRecorder.setLocation(LATITUDE, LONGITUDE);
        final double captureRate = VIDEO_TIMELAPSE_CAPTURE_RATE_FPS;
        if (timelapse) {
            mMediaRecorder.setCaptureRate(captureRate);
        }

        mMediaRecorder.prepare();
        mMediaRecorder.start();
        if (pause) {
            Thread.sleep(durMs / 2);
            mMediaRecorder.pause();
            Thread.sleep(durMs / 2);
            mMediaRecorder.resume();
            Thread.sleep(durMs / 2);
        } else {
            Thread.sleep(durMs);
        }
        mMediaRecorder.stop();
        assertTrue(mOutFile.exists());

        int targetDurMs = timelapse? ((int) (durMs * (captureRate / frameRate))): durMs;
        boolean hasVideo = true;
        boolean hasAudio = timelapse? false: true;
        checkTracksAndDuration(targetDurMs, hasVideo, hasAudio, fileName, frameRate);
    }

    private void checkTracksAndDuration(
            int targetMs, boolean hasVideo, boolean hasAudio, String fileName,
            float frameRate) throws Exception {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(fileName);
        String hasVideoStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
        String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
        assertTrue(hasVideo? hasVideoStr != null : hasVideoStr == null);
        assertTrue(hasAudio? hasAudioStr != null : hasAudioStr == null);
        // FIXME:
        // If we could use fixed frame rate for video recording, we could also do more accurate
        // check on the duration.
        String durStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        assertTrue(durStr != null);
        int duration = Integer.parseInt(durStr);
        assertTrue("duration is non-positive: dur = " + duration, duration > 0);
        if (targetMs != 0) {
            float toleranceMs = RECORDED_DUR_TOLERANCE_FRAMES * (1000f / frameRate);
            assertTrue(String.format("duration is too large: dur = %d, target = %d, tolerance = %f",
                        duration, targetMs, toleranceMs),
                    duration <= targetMs + toleranceMs);
        }

        retriever.release();
        retriever = null;
    }

    private boolean checkLocationInFile(String fileName) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(fileName);
        String location = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
        if (location == null) {
            retriever.release();
            Log.v(TAG, "No location information found in file " + fileName);
            return false;
        }

        // parsing String location and recover the location inforamtion in floats
        // Make sure the tolerance is very small - due to rounding errors?.
        Log.v(TAG, "location: " + location);

        // Trim the trailing slash, if any.
        int lastIndex = location.lastIndexOf('/');
        if (lastIndex != -1) {
            location = location.substring(0, lastIndex);
        }

        // Get the position of the -/+ sign in location String, which indicates
        // the beginning of the longtitude.
        int index = location.lastIndexOf('-');
        if (index == -1) {
            index = location.lastIndexOf('+');
        }
        assertTrue("+ or - is not found", index != -1);
        assertTrue("+ or - is only found at the beginning", index != 0);
        float latitude = Float.parseFloat(location.substring(0, index));
        float longitude = Float.parseFloat(location.substring(index));
        assertTrue("Incorrect latitude: " + latitude, Math.abs(latitude - LATITUDE) <= TOLERANCE);
        assertTrue("Incorrect longitude: " + longitude, Math.abs(longitude - LONGITUDE) <= TOLERANCE);
        retriever.release();
        return true;
    }

    private void checkOutputExist() {
        assertTrue(mOutFile.exists());
        assertTrue(mOutFile.length() > 0);
        assertTrue(mOutFile.delete());
    }

    public void testRecorderVideo() throws Exception {
        if (!hasCamera()) {
            return;
        }
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mMediaRecorder.setOutputFile(OUTPUT_PATH2);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);

        FileOutputStream fos = new FileOutputStream(OUTPUT_PATH2);
        FileDescriptor fd = fos.getFD();
        mMediaRecorder.setOutputFile(fd);
        long maxFileSize = MAX_FILE_SIZE * 10;
        recordMedia(maxFileSize, mOutFile2);
        assertFalse(checkLocationInFile(OUTPUT_PATH2));
        fos.close();
    }

    public void testSetOutputFile() throws Exception {
        if (!hasCamera()) {
            return;
        }
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.setOutputFile(mOutFile);
        long maxFileSize = MAX_FILE_SIZE * 10;
        recordMedia(maxFileSize, mOutFile);
    }

    public void testRecordingAudioInRawFormats() throws Exception {
        int testsRun = 0;
        if (hasAmrNb()) {
            testsRun += testRecordAudioInRawFormat(
                    MediaRecorder.OutputFormat.AMR_NB,
                    MediaRecorder.AudioEncoder.AMR_NB);
        }

        if (hasAmrWb()) {
            testsRun += testRecordAudioInRawFormat(
                    MediaRecorder.OutputFormat.AMR_WB,
                    MediaRecorder.AudioEncoder.AMR_WB);
        }

        if (hasAac()) {
            testsRun += testRecordAudioInRawFormat(
                    MediaRecorder.OutputFormat.AAC_ADTS,
                    MediaRecorder.AudioEncoder.AAC);
        }
        if (testsRun == 0) {
            MediaUtils.skipTest("no audio codecs or microphone");
        }
    }

    private int testRecordAudioInRawFormat(
            int fileFormat, int codec) throws Exception {
        if (!hasMicrophone()) {
            return 0; // skip
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(fileFormat);
        mMediaRecorder.setOutputFile(OUTPUT_PATH);
        mMediaRecorder.setAudioEncoder(codec);
        recordMedia(MAX_FILE_SIZE, mOutFile);
        return 1;
    }

    public void testRecordAudioFromAudioSourceUnprocessed() throws Exception {
        if (!hasMicrophone() || !hasAmrNb()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mMediaRecorder.setOutputFile(OUTPUT_PATH);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        recordMedia(MAX_FILE_SIZE, mOutFile);
    }

    public void testGetAudioSourceMax() throws Exception {
        final int max = MediaRecorder.getAudioSourceMax();
        assertTrue(MediaRecorder.AudioSource.DEFAULT <= max);
        assertTrue(MediaRecorder.AudioSource.MIC <= max);
        assertTrue(MediaRecorder.AudioSource.CAMCORDER <= max);
        assertTrue(MediaRecorder.AudioSource.VOICE_CALL <= max);
        assertTrue(MediaRecorder.AudioSource.VOICE_COMMUNICATION <= max);
        assertTrue(MediaRecorder.AudioSource.VOICE_DOWNLINK <= max);
        assertTrue(MediaRecorder.AudioSource.VOICE_RECOGNITION <= max);
        assertTrue(MediaRecorder.AudioSource.VOICE_UPLINK <= max);
        assertTrue(MediaRecorder.AudioSource.UNPROCESSED <= max);
    }

    public void testRecorderAudio() throws Exception {
        if (!hasMicrophone() || !hasAac()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        assertEquals(0, mMediaRecorder.getMaxAmplitude());
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setOutputFile(OUTPUT_PATH);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.setAudioChannels(AUDIO_NUM_CHANNELS);
        mMediaRecorder.setAudioSamplingRate(AUDIO_SAMPLE_RATE_HZ);
        mMediaRecorder.setAudioEncodingBitRate(AUDIO_BIT_RATE_IN_BPS);
        recordMedia(MAX_FILE_SIZE, mOutFile);
    }

    public void testOnInfoListener() throws Exception {
        if (!hasMicrophone() || !hasAac()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setMaxDuration(MAX_DURATION_MSEC);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.prepare();
        mMediaRecorder.start();
        Thread.sleep(RECORD_TIME_MS);
        assertTrue(mOnInfoCalled);
    }

    public void testSetMaxDuration() throws Exception {
        if (!hasMicrophone() || !hasAac()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        testSetMaxDuration(RECORD_TIME_LONG_MS, RECORDED_DUR_TOLERANCE_MS);
    }

    private void testSetMaxDuration(long durationMs, long toleranceMs) throws Exception {
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setMaxDuration((int)durationMs);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.prepare();
        mMediaRecorder.start();
        long startTimeMs = System.currentTimeMillis();
        if (!mMaxDurationCond.block(durationMs + toleranceMs)) {
            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_DURATION_REACHED");
        }
        long endTimeMs = System.currentTimeMillis();
        long actualDurationMs = endTimeMs - startTimeMs;
        mMediaRecorder.stop();
        checkRecordedTime(durationMs, actualDurationMs, toleranceMs);
    }

    private void checkRecordedTime(long expectedMs, long actualMs, long tolerance) {
        assertEquals(expectedMs, actualMs, tolerance);
        long actualFileDurationMs = getRecordedFileDurationMs(OUTPUT_PATH);
        assertEquals(actualFileDurationMs, actualMs, tolerance);
    }

    private int getRecordedFileDurationMs(final String fileName) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(fileName);
        String durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        assertNotNull(durationStr);
        return Integer.parseInt(durationStr);
    }

    public void testSetMaxFileSize() throws Exception {
        testSetMaxFileSize(512 * 1024, 50 * 1024);
    }

    private void testSetMaxFileSize(
            long fileSize, long tolerance) throws Exception {
        if (!hasMicrophone() || !hasCamera() || !hasAmrNb() || !hasH264()) {
            MediaUtils.skipTest("no microphone, camera, or codecs");
            return;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
        mMediaRecorder.setVideoEncodingBitRate(256000);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.setMaxFileSize(fileSize);
        mMediaRecorder.prepare();
        mMediaRecorder.start();

        // Recording a scene with moving objects would greatly help reduce
        // the time for waiting.
        if (!mMaxFileSizeCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
        }
        mMediaRecorder.stop();
        checkOutputFileSize(OUTPUT_PATH, fileSize, tolerance);
    }

    /**
     * Returns the first codec capable of encoding the specified MIME type, or null if no
     * match was found.
     */
    private static CodecCapabilities getCapsForPreferredCodecForMediaType(String mimeType) {
        // FIXME: select codecs based on the complete use-case, not just the mime
        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        for (MediaCodecInfo info : mcl.getCodecInfos()) {
            if (!info.isEncoder()) {
                continue;
            }

            String[] types = info.getSupportedTypes();
            for (int j = 0; j < types.length; j++) {
                if (types[j].equalsIgnoreCase(mimeType)) {
                    return info.getCapabilitiesForType(mimeType);
                }
            }
        }
        return null;
    }

    /**
     * Generates a frame of data using GL commands.
     */
    private void generateSurfaceFrame(int frameIndex, int width, int height) {
        frameIndex %= 8;

        int startX, startY;
        if (frameIndex < 4) {
            // (0,0) is bottom-left in GL
            startX = frameIndex * (width / 4);
            startY = height / 2;
        } else {
            startX = (7 - frameIndex) * (width / 4);
            startY = 0;
        }

        GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
        GLES20.glClearColor(TEST_R0 / 255.0f, TEST_G0 / 255.0f, TEST_B0 / 255.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
        GLES20.glScissor(startX, startY, width / 4, height / 2);
        GLES20.glClearColor(TEST_R1 / 255.0f, TEST_G1 / 255.0f, TEST_B1 / 255.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

    /**
     * Generates the presentation time for frame N, in microseconds.
     */
    private static long computePresentationTime(
            long startTimeOffset, int frameIndex, int frameRate) {
        return startTimeOffset + frameIndex * 1000000 / frameRate;
    }

    private void testLevel(String mediaType, int width, int height, int framerate,
            int bitrate, int profile, int requestedLevel, int... expectedLevels) throws Exception {
        CodecCapabilities cap = getCapsForPreferredCodecForMediaType(mediaType);
        if (cap == null) { // not supported
            return;
        }
        MediaCodecInfo.VideoCapabilities vCap = cap.getVideoCapabilities();
        if (!vCap.areSizeAndRateSupported(width, height, framerate)
            || !vCap.getBitrateRange().contains(bitrate * 1000)) {
            Log.i(TAG, "Skip the test");
            return;
        }

        Surface surface = MediaCodec.createPersistentInputSurface();
        if (surface == null) {
            return;
        }
        InputSurface encSurface = new InputSurface(surface);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setInputSurface(encSurface.getSurface());
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setOutputFile(mOutFile);

        try {
            mMediaRecorder.setVideoEncodingProfileLevel(-1, requestedLevel);
            fail("Expect IllegalArgumentException.");
        } catch (IllegalArgumentException e) {
            // Expect exception.
        }
        try {
            mMediaRecorder.setVideoEncodingProfileLevel(profile, -1);
            fail("Expect IllegalArgumentException.");
        } catch (IllegalArgumentException e) {
            // Expect exception.
        }

        mMediaRecorder.setVideoEncodingProfileLevel(profile, requestedLevel);
        mMediaRecorder.setVideoSize(width, height);
        mMediaRecorder.setVideoEncodingBitRate(bitrate * 1000);
        mMediaRecorder.setVideoFrameRate(framerate);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.prepare();
        encSurface.updateSize(width, height);
        mMediaRecorder.start();


        long startNsec = System.nanoTime();
        long startTimeOffset =  3000 / framerate;
        for (int i = 0; i < NUM_FRAMES; i++) {
            encSurface.makeCurrent();
            generateSurfaceFrame(i, width, height);
            long time = startNsec +
                    computePresentationTime(startTimeOffset, i, framerate) * 1000;
            encSurface.setPresentationTime(time);
            encSurface.swapBuffers();
        }

        mMediaRecorder.stop();

        assertTrue(mOutFile.exists());
        assertTrue(mOutFile.length() > 0);

        // Verify the recorded file profile/level,
        MediaExtractor ex = new MediaExtractor();
        ex.setDataSource(OUTPUT_PATH);
        for (int i = 0; i < ex.getTrackCount(); i++) {
            MediaFormat format = ex.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("video/")) {
                int finalProfile = format.getInteger(MediaFormat.KEY_PROFILE);
                if (finalProfile != profile) {
                    fail("Incorrect profile: " + finalProfile + " Expected: " + profile);
                }
                int finalLevel = format.getInteger(MediaFormat.KEY_LEVEL);
                boolean match = false;
                String expectLvls = new String();
                for (int level : expectedLevels) {
                    expectLvls += level;
                    if (finalLevel == level) {
                        match = true;
                        break;
                    }
                }
                if (!match) {
                    fail("Incorrect Level: " + finalLevel + " Expected: " + expectLvls);
                }
            }
        }
        mOutFile.delete();
        if (encSurface != null) {
            encSurface.release();
            encSurface = null;
        }
    }

    public void testProfileAvcBaselineLevel1() throws Exception {
        int profile = AVCProfileBaseline;

        if (!hasH264()) {
            MediaUtils.skipTest("no Avc codecs");
            return;
        }

        /*              W    H   fps kbps  profile  request level   expected levels */
        testLevel(AVC, 176, 144, 15, 64,   profile,  AVCLevel1, AVCLevel1);
        // Enable them when vendor fixes the failure
        //testLevel(AVC, 178, 144, 15, 64,   profile,  AVCLevel1, AVCLevel11);
        //testLevel(AVC, 178, 146, 15, 64,   profile,  AVCLevel1, AVCLevel11);
        //testLevel(AVC, 176, 144, 16, 64,   profile,  AVCLevel1, AVCLevel11);
        //testLevel(AVC, 176, 144, 15, 65,   profile,  AVCLevel1, AVCLevel1b);
        testLevel(AVC, 176, 144, 15, 64,   profile,  AVCLevel1b, AVCLevel1,
                AVCLevel1b);
        // testLevel(AVC, 176, 144, 15, 65,   profile,  AVCLevel2, AVCLevel1b,
        //        AVCLevel11, AVCLevel12, AVCLevel13, AVCLevel2);
    }


    public void testRecordExceedFileSizeLimit() throws Exception {
        if (!hasMicrophone() || !hasCamera() || !hasAmrNb() || !hasH264()) {
            MediaUtils.skipTest("no microphone, camera, or codecs");
            return;
        }
        long fileSize = 128 * 1024;
        long tolerance = 50 * 1024;
        List<String> recordFileList = new ArrayList<String>();
        mFileIndex = 0;

        // Override the handler in setup for test.
        mMediaRecorder.setOnInfoListener(new OnInfoListener() {
            public void onInfo(MediaRecorder mr, int what, int extra) {
                mOnInfoCalled = true;
                if (what ==
                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
                    Log.v(TAG, "max duration reached");
                    mMaxDurationCond.open();
                } else if (what ==
                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
                    if (!mExpectMaxFileCond) {
                        fail("Do not expect MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
                    } else {
                        Log.v(TAG, "max file size reached");
                        mMaxFileSizeCond.open();
                    }
                } else if (what ==
                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING) {
                    Log.v(TAG, "max file size is approaching");
                    mMaxFileSizeApproachingCond.open();

                    // Test passing a read-only FileDescriptor and expect IOException.
                    if (mFileIndex == 1) {
                        RandomAccessFile file = null;
                        try {
                            String path = OUTPUT_PATH + '0';
                            file = new RandomAccessFile(path, "r");
                            mMediaRecorder.setNextOutputFile(file.getFD());
                            fail("Expect IOException.");
                        } catch (IOException e) {
                            // Expected.
                        } finally {
                            try {
                                file.close();
                            } catch (IOException e) {
                                fail("Fail to close file");
                            }
                        }
                    }

                    // Test passing a read-only FileDescriptor and expect IOException.
                    if (mFileIndex == 2) {
                        ParcelFileDescriptor out = null;
                        String path = null;
                        try {
                            path = OUTPUT_PATH + '0';
                            out = ParcelFileDescriptor.open(new File(path),
                                    ParcelFileDescriptor.MODE_READ_ONLY | ParcelFileDescriptor.MODE_CREATE);
                            mMediaRecorder.setNextOutputFile(out.getFileDescriptor());
                            fail("Expect IOException.");
                        } catch (IOException e) {
                            // Expected.
                        } finally {
                            try {
                                out.close();
                            } catch (IOException e) {
                                fail("Fail to close file");
                            }
                        }
                    }

                    // Test passing a write-only FileDescriptor and expect NO IOException.
                    if (mFileIndex == 3) {
                        try {
                            ParcelFileDescriptor out = null;
                            String path = OUTPUT_PATH + mFileIndex;
                            out = ParcelFileDescriptor.open(new File(path),
                                    ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
                            mMediaRecorder.setNextOutputFile(out.getFileDescriptor());
                            out.close();
                            recordFileList.add(path);
                            mFileIndex++;
                        } catch (IOException e) {
                            fail("Fail to set next output file error: " + e);
                        }
                    } else if (mFileIndex < 6) {
                        try {
                            String path = OUTPUT_PATH + mFileIndex;
                            File nextFile = new File(path);
                            mMediaRecorder.setNextOutputFile(nextFile);
                            recordFileList.add(path);
                            mFileIndex++;
                        } catch (IOException e) {
                            fail("Fail to set next output file error: " + e);
                        }
                    }
                } else if (what ==
                    MediaRecorder.MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED) {
                    Log.v(TAG, "Next output file started");
                    mNextOutputFileStartedCond.open();
                }
            }
        });
        mExpectMaxFileCond = false;
        mMediaRecorder.setOutputFile(OUTPUT_PATH + mFileIndex);
        recordFileList.add(OUTPUT_PATH + mFileIndex);
        mFileIndex++;
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
        mMediaRecorder.setVideoEncodingBitRate(256000);
        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        mMediaRecorder.setMaxFileSize(fileSize);
        mMediaRecorder.prepare();
        mMediaRecorder.start();

        // Record total 5 files including previous one.
        int fileCount = 0;
        while (fileCount < 5) {
            if (!mMaxFileSizeApproachingCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
                fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING");
            }
            if (!mNextOutputFileStartedCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
                fail("timed out waiting for MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED");
            }
            fileCount++;
            mMaxFileSizeApproachingCond.close();
            mNextOutputFileStartedCond.close();
        }

        mExpectMaxFileCond = true;
        if (!mMaxFileSizeCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
        }
        mMediaRecorder.stop();

        for (String filePath : recordFileList) {
            checkOutputFileSize(filePath, fileSize, tolerance);
        }
    }

    private void checkOutputFileSize(final String fileName, long fileSize, long tolerance) {
        File file = new File(fileName);
        assertTrue(file.exists());
        assertEquals(fileSize, file.length(), tolerance);
        assertTrue(file.delete());
    }

    public void testOnErrorListener() throws Exception {
        if (!hasMicrophone() || !hasAac()) {
            MediaUtils.skipTest("no audio codecs or microphone");
            return;
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

        recordMedia(MAX_FILE_SIZE, mOutFile);
        // TODO: how can we trigger a recording error?
        assertFalse(mOnErrorCalled);
    }

    private void setupRecorder(String filename, boolean useSurface, boolean hasAudio)
            throws Exception {
        int codec = MediaRecorder.VideoEncoder.H264;
        int frameRate = getMaxFrameRateForCodec(codec);
        if (mMediaRecorder == null) {
            mMediaRecorder = new MediaRecorder();
        }

        if (!useSurface) {
            mCamera = Camera.open(0);
            Camera.Parameters params = mCamera.getParameters();
            frameRate = params.getPreviewFrameRate();
            mCamera.unlock();
            mMediaRecorder.setCamera(mCamera);
            mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
        }

        mMediaRecorder.setVideoSource(useSurface ?
                MediaRecorder.VideoSource.SURFACE : MediaRecorder.VideoSource.CAMERA);

        if (hasAudio) {
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        }

        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setOutputFile(filename);

        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setVideoFrameRate(frameRate);
        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);

        if (hasAudio) {
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        }
    }

    private Surface tryGetSurface(boolean shouldThrow) throws Exception {
        Surface surface = null;
        try {
            surface = mMediaRecorder.getSurface();
            assertFalse("failed to throw IllegalStateException", shouldThrow);
        } catch (IllegalStateException e) {
            assertTrue("threw unexpected exception: " + e, shouldThrow);
        }
        return surface;
    }

    private boolean validateGetSurface(boolean useSurface) {
        Log.v(TAG,"validateGetSurface, useSurface=" + useSurface);
        if (!useSurface && !hasCamera()) {
            // pass if testing camera source but no hardware
            return true;
        }
        Surface surface = null;
        boolean success = true;
        try {
            setupRecorder(OUTPUT_PATH, useSurface, false /* hasAudio */);

            /* Test: getSurface() before prepare()
             * should throw IllegalStateException
             */
            surface = tryGetSurface(true /* shouldThow */);

            mMediaRecorder.prepare();

            /* Test: getSurface() after prepare()
             * should succeed for surface source
             * should fail for camera source
             */
            surface = tryGetSurface(!useSurface);

            mMediaRecorder.start();

            /* Test: getSurface() after start()
             * should succeed for surface source
             * should fail for camera source
             */
            surface = tryGetSurface(!useSurface);

            try {
                mMediaRecorder.stop();
            } catch (Exception e) {
                // stop() could fail if the recording is empty, as we didn't render anything.
                // ignore any failure in stop, we just want it stopped.
            }

            /* Test: getSurface() after stop()
             * should throw IllegalStateException
             */
            surface = tryGetSurface(true /* shouldThow */);
        } catch (Exception e) {
            Log.d(TAG, e.toString());
            success = false;
        } finally {
            // reset to clear states, as stop() might have failed
            mMediaRecorder.reset();

            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
            if (surface != null) {
                surface.release();
                surface = null;
            }
        }

        return success;
    }

    private void trySetInputSurface(Surface surface) throws Exception {
        boolean testBadArgument = (surface == null);
        try {
            mMediaRecorder.setInputSurface(testBadArgument ? new Surface() : surface);
            fail("failed to throw exception");
        } catch (IllegalArgumentException e) {
            // OK only if testing bad arg
            assertTrue("threw unexpected exception: " + e, testBadArgument);
        } catch (IllegalStateException e) {
            // OK only if testing error case other than bad arg
            assertFalse("threw unexpected exception: " + e, testBadArgument);
        }
    }

    private boolean validatePersistentSurface(boolean errorCase) {
        Log.v(TAG, "validatePersistentSurface, errorCase=" + errorCase);

        Surface surface = MediaCodec.createPersistentInputSurface();
        if (surface == null) {
            return false;
        }
        Surface dummy = null;

        boolean success = true;
        try {
            setupRecorder(OUTPUT_PATH, true /* useSurface */, false /* hasAudio */);

            if (errorCase) {
                /*
                 * Test: should throw if called with non-persistent surface
                 */
                trySetInputSurface(null);
            } else {
                /*
                 * Test: should succeed if called with a persistent surface before prepare()
                 */
                mMediaRecorder.setInputSurface(surface);
            }

            /*
             * Test: getSurface() should fail before prepare
             */
            dummy = tryGetSurface(true /* shouldThow */);

            mMediaRecorder.prepare();

            /*
             * Test: setInputSurface() should fail after prepare
             */
            trySetInputSurface(surface);

            /*
             * Test: getSurface() should fail if setInputSurface() succeeded
             */
            dummy = tryGetSurface(!errorCase /* shouldThow */);

            mMediaRecorder.start();

            /*
             * Test: setInputSurface() should fail after start
             */
            trySetInputSurface(surface);

            /*
             * Test: getSurface() should fail if setInputSurface() succeeded
             */
            dummy = tryGetSurface(!errorCase /* shouldThow */);

            try {
                mMediaRecorder.stop();
            } catch (Exception e) {
                // stop() could fail if the recording is empty, as we didn't render anything.
                // ignore any failure in stop, we just want it stopped.
            }

            /*
             * Test: getSurface() should fail after stop
             */
            dummy = tryGetSurface(true /* shouldThow */);
        } catch (Exception e) {
            Log.d(TAG, e.toString());
            success = false;
        } finally {
            // reset to clear states, as stop() might have failed
            mMediaRecorder.reset();

            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
            if (surface != null) {
                surface.release();
                surface = null;
            }
            if (dummy != null) {
                dummy.release();
                dummy = null;
            }
        }

        return success;
    }

    public void testGetSurfaceApi() {
        if (!hasH264()) {
            MediaUtils.skipTest("no codecs");
            return;
        }

        if (hasCamera()) {
            // validate getSurface() with CAMERA source
            assertTrue(validateGetSurface(false /* useSurface */));
        }

        // validate getSurface() with SURFACE source
        assertTrue(validateGetSurface(true /* useSurface */));
    }

    public void testPersistentSurfaceApi() {
        if (!hasH264()) {
            MediaUtils.skipTest("no codecs");
            return;
        }

        // test valid use case
        assertTrue(validatePersistentSurface(false /* errorCase */));

        // test invalid use case
        assertTrue(validatePersistentSurface(true /* errorCase */));
    }

    private static int getMaxFrameRateForCodec(int codec) {
        for (VideoEncoderCap cap : mVideoEncoders) {
            if (cap.mCodec == codec) {
                return cap.mMaxFrameRate < NORMAL_FPS ? cap.mMaxFrameRate : NORMAL_FPS;
            }
        }
        fail("didn't find max FPS for codec");
        return -1;
    }

    private boolean recordFromSurface(
            String filename,
            int captureRate,
            boolean hasAudio,
            Surface persistentSurface) {
        Log.v(TAG, "recordFromSurface");
        Surface surface = null;
        try {
            setupRecorder(filename, true /* useSurface */, hasAudio);

            int sleepTimeMs;
            if (captureRate > 0) {
                mMediaRecorder.setCaptureRate(captureRate);
                sleepTimeMs = 1000 / captureRate;
            } else {
                sleepTimeMs = 1000 / getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H264);
            }

            if (persistentSurface != null) {
                Log.v(TAG, "using persistent surface");
                surface = persistentSurface;
                mMediaRecorder.setInputSurface(surface);
            }

            mMediaRecorder.prepare();

            if (persistentSurface == null) {
                surface = mMediaRecorder.getSurface();
            }

            Paint paint = new Paint();
            paint.setTextSize(16);
            paint.setColor(Color.RED);
            int i;

            /* Test: draw 10 frames at 30fps before start
             * these should be dropped and not causing malformed stream.
             */
            for(i = 0; i < 10; i++) {
                Canvas canvas = surface.lockCanvas(null);
                int background = (i * 255 / 99);
                canvas.drawARGB(255, background, background, background);
                String text = "Frame #" + i;
                canvas.drawText(text, 50, 50, paint);
                surface.unlockCanvasAndPost(canvas);
                Thread.sleep(sleepTimeMs);
            }

            Log.v(TAG, "start");
            mMediaRecorder.start();

            /* Test: draw another 90 frames at 30fps after start */
            for(i = 10; i < 100; i++) {
                Canvas canvas = surface.lockCanvas(null);
                int background = (i * 255 / 99);
                canvas.drawARGB(255, background, background, background);
                String text = "Frame #" + i;
                canvas.drawText(text, 50, 50, paint);
                surface.unlockCanvasAndPost(canvas);
                Thread.sleep(sleepTimeMs);
            }

            Log.v(TAG, "stop");
            mMediaRecorder.stop();
        } catch (Exception e) {
            Log.v(TAG, "record video failed: " + e.toString());
            return false;
        } finally {
            // We need to test persistent surface across multiple MediaRecorder
            // instances, so must destroy mMediaRecorder here.
            if (mMediaRecorder != null) {
                mMediaRecorder.release();
                mMediaRecorder = null;
            }

            // release surface if not using persistent surface
            if (persistentSurface == null && surface != null) {
                surface.release();
                surface = null;
            }
        }
        return true;
    }

    private boolean checkCaptureFps(String filename, int captureRate) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();

        retriever.setDataSource(filename);

        // verify capture rate meta key is present and correct
        String captureFps = retriever.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE);

        if (captureFps == null) {
            Log.d(TAG, "METADATA_KEY_CAPTURE_FRAMERATE is missing");
            return false;
        }

        if (Math.abs(Float.parseFloat(captureFps) - captureRate) > 0.001) {
            Log.d(TAG, "METADATA_KEY_CAPTURE_FRAMERATE is incorrect: "
                    + captureFps + "vs. " + captureRate);
            return false;
        }

        // verify other meta keys here if necessary
        return true;
    }

    private boolean testRecordFromSurface(boolean persistent, boolean timelapse) {
        Log.v(TAG, "testRecordFromSurface: " +
                   "persistent=" + persistent + ", timelapse=" + timelapse);
        boolean success = false;
        Surface surface = null;
        int noOfFailure = 0;

        if (!hasH264()) {
            MediaUtils.skipTest("no codecs");
            return true;
        }

        final float frameRate = getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H264);

        try {
            if (persistent) {
                surface = MediaCodec.createPersistentInputSurface();
            }

            for (int k = 0; k < 2; k++) {
                String filename = (k == 0) ? OUTPUT_PATH : OUTPUT_PATH2;
                boolean hasAudio = false;
                int captureRate = 0;

                if (timelapse) {
                    // if timelapse/slow-mo, k chooses between low/high capture fps
                    captureRate = (k == 0) ? TIME_LAPSE_FPS : SLOW_MOTION_FPS;
                } else {
                    // otherwise k chooses between no-audio and audio
                    hasAudio = (k == 0) ? false : true;
                }

                if (hasAudio && (!hasMicrophone() || !hasAmrNb())) {
                    // audio test waived if no audio support
                    continue;
                }

                Log.v(TAG, "testRecordFromSurface - round " + k);
                success = recordFromSurface(filename, captureRate, hasAudio, surface);
                if (success) {
                    checkTracksAndDuration(0, true /* hasVideo */, hasAudio, filename, frameRate);

                    // verify capture fps meta key
                    if (timelapse && !checkCaptureFps(filename, captureRate)) {
                        noOfFailure++;
                    }
                }
                if (!success) {
                    noOfFailure++;
                }
            }
        } catch (Exception e) {
            Log.v(TAG, e.toString());
            noOfFailure++;
        } finally {
            if (surface != null) {
                Log.v(TAG, "releasing persistent surface");
                surface.release();
                surface = null;
            }
        }
        return (noOfFailure == 0);
    }

    // Test recording from surface source with/without audio)
    public void testSurfaceRecording() {
        assertTrue(testRecordFromSurface(false /* persistent */, false /* timelapse */));
    }

    // Test recording from persistent surface source with/without audio
    public void testPersistentSurfaceRecording() {
        assertTrue(testRecordFromSurface(true /* persistent */, false /* timelapse */));
    }

    // Test timelapse recording from surface without audio
    public void testSurfaceRecordingTimeLapse() {
        assertTrue(testRecordFromSurface(false /* persistent */, true /* timelapse */));
    }

    // Test timelapse recording from persisent surface without audio
    public void testPersistentSurfaceRecordingTimeLapse() {
        assertTrue(testRecordFromSurface(true /* persistent */, true /* timelapse */));
    }

    private void recordMedia(long maxFileSize, File outFile) throws Exception {
        mMediaRecorder.setMaxFileSize(maxFileSize);
        mMediaRecorder.prepare();
        mMediaRecorder.start();
        Thread.sleep(RECORD_TIME_MS);
        mMediaRecorder.stop();

        assertTrue(outFile.exists());

        // The max file size is always guaranteed.
        // We just make sure that the margin is not too big
        assertTrue(outFile.length() < 1.1 * maxFileSize);
        assertTrue(outFile.length() > 0);
    }

    private boolean hasCamera() {
        return mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    private boolean hasMicrophone() {
        return mActivity.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_MICROPHONE);
    }

    private static boolean hasAmrNb() {
        return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
    }

    private static boolean hasAmrWb() {
        return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_WB);
    }

    private static boolean hasAac() {
        return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC);
    }

    private static boolean hasH264() {
        return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_VIDEO_AVC);
    }

    public void testSetCaptureRate() throws Exception {
        // No exception expected for 30fps
        mMediaRecorder.setCaptureRate(30.0);
        try {
            mMediaRecorder.setCaptureRate(-1.0);
            fail("Should fail setting negative fps");
        } catch (Exception ex) {
            // expected
        }
        // No exception expected for 1/24hr
        mMediaRecorder.setCaptureRate(1.0 / 86400.0);
        try {
            mMediaRecorder.setCaptureRate(1.0 / 90000.0);
            fail("Should fail setting smaller fps than one frame per day");
        } catch (Exception ex) {
            // expected
        }
        try {
            mMediaRecorder.setCaptureRate(0);
            fail("Should fail setting zero fps");
        } catch (Exception ex) {
            // expected
        }
    }
}
