Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f358cecb authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 79a3981e: Fix Looper leaks in MediaRecorderStressTest.

Merge commit '79a3981e' into gingerbread-plus-aosp

* commit '79a3981e':
  Fix Looper leaks in MediaRecorderStressTest.
parents ff04e97f 79a3981e
Loading
Loading
Loading
Loading
+89 −111
Original line number Original line Diff line number Diff line
@@ -23,10 +23,13 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.File;
import java.io.FileWriter;
import java.io.FileWriter;
import java.io.Writer;
import java.io.Writer;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;


import android.hardware.Camera;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Looper;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.LargeTest;
@@ -51,105 +54,90 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
    private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 200;
    private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 200;
    private static final long WAIT_TIME_CAMERA_TEST = 3000;  // 3 second
    private static final long WAIT_TIME_CAMERA_TEST = 3000;  // 3 second
    private static final long WAIT_TIME_RECORDER_TEST = 6000;  // 6 second
    private static final long WAIT_TIME_RECORDER_TEST = 6000;  // 6 second
    private static final long WAIT_TIME_RECORD = 10000;  // 10 seconds
    private static final long WAIT_TIME_PLAYBACK = 6000;  // 6 second
    private static final String OUTPUT_FILE = "/sdcard/temp";
    private static final String OUTPUT_FILE = "/sdcard/temp";
    private static final String OUTPUT_FILE_EXT = ".3gp";
    private static final String OUTPUT_FILE_EXT = ".3gp";
    private static final String MEDIA_STRESS_OUTPUT =
    private static final String MEDIA_STRESS_OUTPUT =
        "/sdcard/mediaStressOutput.txt";
        "/sdcard/mediaStressOutput.txt";
    private Looper mCameraLooper = null;
    private Looper mRecorderLooper = null;
    private final Object lock = new Object();
    private final Object recorderlock = new Object();
    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000;  // Milliseconds.
    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();


    private final static int WAIT_TIMEOUT = 10000;
    private Thread mLooperThread;
    private Handler mHandler;

    public MediaRecorderStressTest() {
    public MediaRecorderStressTest() {
        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
    }
    }


    protected void setUp() throws Exception {
    protected void setUp() throws Exception {
        final Semaphore sem = new Semaphore(0);
        mLooperThread = new Thread() {
            @Override
            public void run() {
                Log.v(TAG, "starting looper");
                Looper.prepare();
                mHandler = new Handler();
                sem.release();
                Looper.loop();
                Log.v(TAG, "quit looper");
            }
        };
        mLooperThread.start();
        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
            fail("Failed to start the looper.");
        }

        getActivity();
        getActivity();
        super.setUp();
        super.setUp();
    }
    }


    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
    @Override
        public void onError(int error, android.hardware.Camera camera) {
    protected void tearDown() throws Exception {
            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
        if (mHandler != null) {
                assertTrue("Camera test mediaserver died", false);
            mHandler.getLooper().quit();
            mHandler = null;
        }
        }
        if (mLooperThread != null) {
            mLooperThread.join(WAIT_TIMEOUT);
            if (mLooperThread.isAlive()) {
                fail("Failed to stop the looper.");
            }
            }
            mLooperThread = null;
        }
        }


    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
        super.tearDown();
        public void onError(MediaRecorder mr, int what, int extra) {
            // fail the test case no matter what error come up
            assertTrue("mediaRecorder error", false);
        }
    }
    }


    private void initializeCameraMessageLooper() {
    private void runOnLooper(final Runnable command) throws InterruptedException {
        Log.v(TAG, "start looper");
        final Semaphore sem = new Semaphore(0);
        new Thread() {
        mHandler.post(new Runnable() {
            @Override
            @Override
            public void run() {
            public void run() {
                // Set up a looper to be used by camera.
                try {
                Looper.prepare();
                    command.run();
                Log.v(TAG, "start loopRun");
                } finally {
                mCameraLooper = Looper.myLooper();
                    sem.release();
                mCamera = Camera.open();
                synchronized (lock) {
                    lock.notify();
                }
                Looper.loop();
                Log.v(TAG, "initializeMessageLooper: quit.");
                }
                }
        }.start();
            }
            }

        });
    private void initializeRecorderMessageLooper() {
        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
        Log.v(TAG, "start looper");
            fail("Failed to run the command on the looper.");
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Log.v(TAG, "start loopRun");
                mRecorderLooper = Looper.myLooper();
                mRecorder = new MediaRecorder();
                synchronized (recorderlock) {
                    recorderlock.notify();
        }
        }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
                Log.v(TAG, "initializeMessageLooper: quit.");
            }
        }.start();
    }
    }


    /*
    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
     * Terminates the message looper thread.
        public void onError(int error, android.hardware.Camera camera) {
     */
            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
    private void terminateCameraMessageLooper() {
                assertTrue("Camera test mediaserver died", false);
        mCameraLooper.quit();
            }
        try {
            Thread.sleep(1000);
        } catch (Exception e){
            Log.v(TAG, e.toString());
        }
        }
        mCamera.release();
    }
    }


    /*
    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
     * Terminates the message looper thread.
        public void onError(MediaRecorder mr, int what, int extra) {
     */
            // fail the test case no matter what error come up
    private void terminateRecorderMessageLooper() {
            assertTrue("mediaRecorder error", false);
        mRecorderLooper.quit();
        try {
            Thread.sleep(1000);
        } catch (Exception e){
            Log.v(TAG, e.toString());
        }
        }
        mRecorder.release();
    }
    }


    //Test case for stressing the camera preview.
    //Test case for stressing the camera preview.
@@ -167,20 +155,18 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
            output.write("No of loop: ");
            output.write("No of loop: ");


            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
                synchronized (lock) {
                runOnLooper(new Runnable() {
                    initializeCameraMessageLooper();
                    @Override
                    try {
                    public void run() {
                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                        mCamera = Camera.open();
                    } catch(Exception e) {
                        Log.v(TAG, "wait was interrupted.");
                    }
                    }
                    }
                });
                mCamera.setErrorCallback(mCameraErrorCallback);
                mCamera.setErrorCallback(mCameraErrorCallback);
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();
                mCamera.startPreview();
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                mCamera.stopPreview();
                mCamera.stopPreview();
                terminateCameraMessageLooper();
                mCamera.release();
                output.write(" ," + i);
                output.write(" ," + i);
            }
            }
        } catch (Exception e) {
        } catch (Exception e) {
@@ -206,14 +192,12 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
            output.write("No of loop: ");
            output.write("No of loop: ");
            Log.v(TAG, "Start preview");
            Log.v(TAG, "Start preview");
            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
                synchronized (recorderlock) {
                runOnLooper(new Runnable() {
                    initializeRecorderMessageLooper();
                    @Override
                    try {
                    public void run() {
                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                        mRecorder = new MediaRecorder();
                    } catch(Exception e) {
                        Log.v(TAG, "wait was interrupted.");
                    }
                    }
                    }
                });
                Log.v(TAG, "counter = " + i);
                Log.v(TAG, "counter = " + i);
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                Log.v(TAG, filename);
                Log.v(TAG, filename);
@@ -233,7 +217,7 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
                Log.v(TAG, "before release");
                Log.v(TAG, "before release");
                Thread.sleep(WAIT_TIME_RECORDER_TEST);
                Thread.sleep(WAIT_TIME_RECORDER_TEST);
                mRecorder.reset();
                mRecorder.reset();
                terminateRecorderMessageLooper();
                mRecorder.release();
                output.write(", " + i);
                output.write(", " + i);
            }
            }
        } catch (Exception e) {
        } catch (Exception e) {
@@ -259,32 +243,28 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
            Log.v(TAG, "Start preview");
            Log.v(TAG, "Start preview");
            output.write("No of loop: ");
            output.write("No of loop: ");
            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
                synchronized (lock) {
                runOnLooper(new Runnable() {
                    initializeCameraMessageLooper();
                    @Override
                    try {
                    public void run() {
                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                        mCamera = Camera.open();
                    } catch(Exception e) {
                        Log.v(TAG, "wait was interrupted.");
                    }
                    }
                    }
                });
                mCamera.setErrorCallback(mCameraErrorCallback);
                mCamera.setErrorCallback(mCameraErrorCallback);
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();
                mCamera.startPreview();
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                mCamera.stopPreview();
                mCamera.stopPreview();
                terminateCameraMessageLooper();
                mCamera.release();
                mCamera = null;
                mCamera = null;
                Log.v(TAG, "release camera");
                Log.v(TAG, "release camera");
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                Log.v(TAG, filename);
                Log.v(TAG, filename);
                synchronized (recorderlock) {
                runOnLooper(new Runnable() {
                    initializeRecorderMessageLooper();
                    @Override
                    try {
                    public void run() {
                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                        mRecorder = new MediaRecorder();
                    } catch(Exception e) {
                        Log.v(TAG, "wait was interrupted.");
                    }
                    }
                    }
                });
                mRecorder.setOnErrorListener(mRecorderErrorCallback);
                mRecorder.setOnErrorListener(mRecorderErrorCallback);
                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
@@ -299,7 +279,7 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
                mRecorder.prepare();
                mRecorder.prepare();
                Log.v(TAG, "before release");
                Log.v(TAG, "before release");
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                Thread.sleep(WAIT_TIME_CAMERA_TEST);
                terminateRecorderMessageLooper();
                mRecorder.release();
                Log.v(TAG, "release video recorder");
                Log.v(TAG, "release video recorder");
                output.write(", " + i);
                output.write(", " + i);
            }
            }
@@ -358,14 +338,12 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
            for (int i = 0; i < iterations; i++){
            for (int i = 0; i < iterations; i++){
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                Log.v(TAG, filename);
                Log.v(TAG, filename);
                synchronized (recorderlock) {
                runOnLooper(new Runnable() {
                    initializeRecorderMessageLooper();
                    @Override
                    try {
                    public void run() {
                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                        mRecorder = new MediaRecorder();
                    } catch(Exception e) {
                        Log.v(TAG, "wait was interrupted.");
                    }
                    }
                    }
                });
                Log.v(TAG, "iterations : " + iterations);
                Log.v(TAG, "iterations : " + iterations);
                Log.v(TAG, "video_encoder : " + video_encoder);
                Log.v(TAG, "video_encoder : " + video_encoder);
                Log.v(TAG, "audio_encoder : " + audio_encoder);
                Log.v(TAG, "audio_encoder : " + audio_encoder);
@@ -391,7 +369,7 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
                Thread.sleep(record_duration);
                Thread.sleep(record_duration);
                Log.v(TAG, "Before stop");
                Log.v(TAG, "Before stop");
                mRecorder.stop();
                mRecorder.stop();
                terminateRecorderMessageLooper();
                mRecorder.release();
                //start the playback
                //start the playback
                MediaPlayer mp = new MediaPlayer();
                MediaPlayer mp = new MediaPlayer();
                mp.setDataSource(filename);
                mp.setDataSource(filename);