am f358cecb: am 79a3981e: Fix Looper leaks in MediaRecorderStressTest.

Merge commit 'f358cecb9cb2853ba0d6f54f350a92b1b5e247b2'

* commit 'f358cecb9cb2853ba0d6f54f350a92b1b5e247b2':
  Fix Looper leaks in MediaRecorderStressTest.
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index e442c85..3908d71 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -23,10 +23,13 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.Writer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
 
 import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.os.Handler;
 import android.os.Looper;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -51,27 +54,75 @@
     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_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_EXT = ".3gp";
     private static final String MEDIA_STRESS_OUTPUT =
         "/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 RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
 
+    private final static int WAIT_TIMEOUT = 10000;
+    private Thread mLooperThread;
+    private Handler mHandler;
+
     public MediaRecorderStressTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
     }
 
     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();
-        super.setUp();      
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHandler != null) {
+            mHandler.getLooper().quit();
+            mHandler = null;
+        }
+        if (mLooperThread != null) {
+            mLooperThread.join(WAIT_TIMEOUT);
+            if (mLooperThread.isAlive()) {
+                fail("Failed to stop the looper.");
+            }
+            mLooperThread = null;
+        }
+
+        super.tearDown();
+    }
+
+    private void runOnLooper(final Runnable command) throws InterruptedException {
+        final Semaphore sem = new Semaphore(0);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    command.run();
+                } finally {
+                    sem.release();
+                }
+            }
+        });
+        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to run the command on the looper.");
+        }
     }
 
     private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
@@ -89,69 +140,6 @@
         }
     }
 
-    private void initializeCameraMessageLooper() {
-        Log.v(TAG, "start looper");
-        new Thread() {
-            @Override
-            public void run() {
-                // Set up a looper to be used by camera.
-                Looper.prepare();
-                Log.v(TAG, "start loopRun");
-                mCameraLooper = Looper.myLooper();
-                mCamera = Camera.open();
-                synchronized (lock) {
-                    lock.notify();
-                }
-                Looper.loop();
-                Log.v(TAG, "initializeMessageLooper: quit.");
-            }
-        }.start();
-    }
-
-    private void initializeRecorderMessageLooper() {
-        Log.v(TAG, "start 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();
-    }
-
-    /*
-     * Terminates the message looper thread.
-     */
-    private void terminateCameraMessageLooper() {
-        mCameraLooper.quit();
-        try {
-            Thread.sleep(1000);
-        } catch (Exception e){
-            Log.v(TAG, e.toString());
-        }
-        mCamera.release();
-    }
-
-    /*
-     * Terminates the message looper thread.
-     */
-    private void terminateRecorderMessageLooper() {
-        mRecorderLooper.quit();
-        try {
-            Thread.sleep(1000);
-        } catch (Exception e){
-            Log.v(TAG, e.toString());
-        }
-        mRecorder.release();
-    }
-
     //Test case for stressing the camera preview.
     @LargeTest
     public void testStressCamera() throws Exception {
@@ -166,21 +154,19 @@
             Log.v(TAG, "Start preview");
             output.write("No of loop: ");
 
-            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++){
-                synchronized (lock) {
-                    initializeCameraMessageLooper();
-                    try {
-                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                    } catch(Exception e) {
-                        Log.v(TAG, "wait was interrupted.");
+            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCamera = Camera.open();
                     }
-                }
+                });
                 mCamera.setErrorCallback(mCameraErrorCallback);
                 mCamera.setPreviewDisplay(mSurfaceHolder);
                 mCamera.startPreview();
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
                 mCamera.stopPreview();
-                terminateCameraMessageLooper();
+                mCamera.release();
                 output.write(" ," + i);
             }
         } catch (Exception e) {
@@ -205,15 +191,13 @@
         try {
             output.write("No of loop: ");
             Log.v(TAG, "Start preview");
-            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++){
-                synchronized (recorderlock) {
-                    initializeRecorderMessageLooper();
-                    try {
-                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                    } catch(Exception e) {
-                        Log.v(TAG, "wait was interrupted.");
+            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mRecorder = new MediaRecorder();
                     }
-                }
+                });
                 Log.v(TAG, "counter = " + i);
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
@@ -233,7 +217,7 @@
                 Log.v(TAG, "before release");
                 Thread.sleep(WAIT_TIME_RECORDER_TEST);
                 mRecorder.reset();
-                terminateRecorderMessageLooper();
+                mRecorder.release();
                 output.write(", " + i);
             }
         } catch (Exception e) {
@@ -258,33 +242,29 @@
         try {
             Log.v(TAG, "Start preview");
             output.write("No of loop: ");
-            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++){
-                synchronized (lock) {
-                    initializeCameraMessageLooper();
-                    try {
-                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                    } catch(Exception e) {
-                        Log.v(TAG, "wait was interrupted.");
+            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCamera = Camera.open();
                     }
-                }
+                });
                 mCamera.setErrorCallback(mCameraErrorCallback);
                 mCamera.setPreviewDisplay(mSurfaceHolder);
                 mCamera.startPreview();
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
                 mCamera.stopPreview();
-                terminateCameraMessageLooper();
+                mCamera.release();
                 mCamera = null;
                 Log.v(TAG, "release camera");
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
-                synchronized (recorderlock) {
-                    initializeRecorderMessageLooper();
-                    try {
-                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                    } catch(Exception e) {
-                        Log.v(TAG, "wait was interrupted.");
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mRecorder = new MediaRecorder();
                     }
-                }
+                });
                 mRecorder.setOnErrorListener(mRecorderErrorCallback);
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
@@ -299,7 +279,7 @@
                 mRecorder.prepare();
                 Log.v(TAG, "before release");
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
-                terminateRecorderMessageLooper();
+                mRecorder.release();
                 Log.v(TAG, "release video recorder");
                 output.write(", " + i);
             }
@@ -358,14 +338,12 @@
             for (int i = 0; i < iterations; i++){
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
-                synchronized (recorderlock) {
-                    initializeRecorderMessageLooper();
-                    try {
-                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                    } catch(Exception e) {
-                        Log.v(TAG, "wait was interrupted.");
+                runOnLooper(new Runnable() {
+                    @Override
+                    public void run() {
+                        mRecorder = new MediaRecorder();
                     }
-                }
+                });
                 Log.v(TAG, "iterations : " + iterations);
                 Log.v(TAG, "video_encoder : " + video_encoder);
                 Log.v(TAG, "audio_encoder : " + audio_encoder);
@@ -391,7 +369,7 @@
                 Thread.sleep(record_duration);
                 Log.v(TAG, "Before stop");
                 mRecorder.stop();
-                terminateRecorderMessageLooper();
+                mRecorder.release();
                 //start the playback
                 MediaPlayer mp = new MediaPlayer();
                 mp.setDataSource(filename);