Additional refactoring of MediaPlayer tests.

Rename MediaPlayerTestHelpers to MediaPlayerTestBase, a base class that can
be extended to easily create new MediaPlayer tests.  MediaPlayerTest now
consists of tests of local files, and MediaPlayerStreamingTest consists of
tests of streams (such as the local HTTP streams that were previously in
MediaPlayerTest).

Change-Id: I9aac07e8fdbc79bcd763e0a5e0c16254c42b39b0
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
index 36ed264..7d2bc81 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
@@ -15,46 +15,91 @@
  */
 package android.media.cts;
 
-import android.content.Context;
-import android.content.res.Resources;
 import android.media.MediaPlayer;
-import android.test.ActivityInstrumentationTestCase2;
+import android.webkit.cts.CtsTestServer;
+
 
 /**
  * Tests of MediaPlayer streaming capabilities.
  */
-public class MediaPlayerStreamingTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+public class MediaPlayerStreamingTest extends MediaPlayerTestBase {
+    private CtsTestServer mServer;
 
-    private static String TAG = "CtsMediaPlayerStreamingTest";
-
-    private Context mContext;
-    private Resources mResources;
-
-    /*
-     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
-     * for the current thread. However, since we don't actually call loop() in the test,
-     * any messages queued with that looper will never be consumed. We instantiate the player
-     * in the constructor, before setUp(), so that its constructor does not see the
-     * nonfunctional Looper.
-     */
-    private MediaPlayer mMediaPlayer = new MediaPlayer();
-
-    public MediaPlayerStreamingTest() {
-        super(MediaStubActivity.class);
+    // Streaming audio from local HTTP server
+    public void testPlayMp3Stream1() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3Stream2() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3StreamRedirect() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", true, false);
+    }
+    public void testPlayMp3StreamNoLength() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.mp3", false, true);
+    }
+    public void testPlayOggStream() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, false);
+    }
+    public void testPlayOggStreamRedirect() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", true, false);
+    }
+    public void testPlayOggStreamNoLength() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, true);
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mContext = getInstrumentation().getTargetContext();
-        mResources = mContext.getResources();
-    }
+    private void localHttpAudioStreamTest(final String name, boolean redirect, boolean nolength)
+            throws Throwable {
+        mServer = new CtsTestServer(mContext);
+        try {
+            String stream_url = null;
+            if (redirect) {
+                // Stagefright doesn't have a limit, but we can't test support of infinite redirects
+                // Up to 4 redirects seems reasonable though.
+                stream_url = mServer.getRedirectingAssetUrl(name, 4);
+            } else {
+                stream_url = mServer.getAssetUrl(name);
+            }
+            if (nolength) {
+                stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
+            }
 
-    @Override
-    protected void tearDown() throws Exception {
-        if (mMediaPlayer != null) {
-            mMediaPlayer.release();
+            mMediaPlayer.setDataSource(stream_url);
+
+            mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mMediaPlayer.setScreenOnWhilePlaying(true);
+
+            mOnBufferingUpdateCalled.reset();
+            mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
+                @Override
+                public void onBufferingUpdate(MediaPlayer mp, int percent) {
+                    mOnBufferingUpdateCalled.signal();
+                }
+            });
+            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer mp, int what, int extra) {
+                    fail("Media player had error " + what + " playing " + name);
+                    return true;
+                }
+            });
+
+            assertFalse(mOnBufferingUpdateCalled.isSignalled());
+            mMediaPlayer.prepare();
+
+            if (nolength) {
+                mMediaPlayer.start();
+                Thread.sleep(LONG_SLEEP_TIME);
+                assertFalse(mMediaPlayer.isPlaying());
+            } else {
+                mOnBufferingUpdateCalled.waitForSignal();
+                mMediaPlayer.start();
+                Thread.sleep(SLEEP_TIME);
+            }
+            mMediaPlayer.stop();
+            mMediaPlayer.reset();
+        } finally {
+            mServer.shutdown();
         }
-        super.tearDown();
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 470cf76..f688fea 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -17,96 +17,21 @@
 
 import com.android.cts.stub.R;
 
-import android.content.Context;
 import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
-import android.media.cts.MediaPlayerTestHelpers.Monitor;
 import android.net.Uri;
 import android.os.Environment;
-import android.os.Looper;
 import android.os.PowerManager;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-import android.webkit.cts.CtsTestServer;
 
 import java.io.File;
 
 /**
  * Tests for the MediaPlayer API and local video/audio playback.
  */
-public class MediaPlayerTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
-
-    private static String TAG = "CtsMediaPlayerTest";
-    private static final int SLEEP_TIME = 1000;
-    private static final int LONG_SLEEP_TIME = 6000;
-    private final String mSourceMediaOnSdcard;
-    private Monitor mOnVideoSizeChangedCalled = new Monitor();
-    private Monitor mOnBufferingUpdateCalled = new Monitor();
-    private Monitor mOnPrepareCalled = new Monitor();
-    private Monitor mOnSeekCompleteCalled = new Monitor();
-    private Monitor mOnCompletionCalled = new Monitor();
-    private Monitor mOnInfoCalled = new Monitor();
-    private Monitor mOnErrorCalled = new Monitor();
-    private Context mContext;
-    private Resources mResources;
-    private CtsTestServer mServer;
-    private static Object sVideoSizeChanged;
-    private static Object sLock;
-    private static Looper sLooper = null;
-    private static final int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
-
-    /*
-     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
-     * for the current thread. However, since we don't actually call loop() in the test,
-     * any messages queued with that looper will never be consumed. We instantiate the player
-     * in the constructor, before setUp(), so that its constructor does not see the
-     * nonfunctional Looper.
-     */
-    private MediaPlayer mMediaPlayer = new MediaPlayer();
-
-    static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
-        new MediaPlayer.OnVideoSizeChangedListener() {
-            @Override
-            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
-                synchronized (sVideoSizeChanged) {
-                    Log.v(TAG, "sizechanged notification received ...");
-                    sVideoSizeChanged.notify();
-                }
-            }
-        };
-
-    public MediaPlayerTest() {
-        super(MediaStubActivity.class);
-        mSourceMediaOnSdcard = new File(Environment.getExternalStorageDirectory(),
-                                        "record_and_play.3gp").getAbsolutePath();
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mContext = getInstrumentation().getTargetContext();
-        mResources = mContext.getResources();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mMediaPlayer != null) {
-            mMediaPlayer.release();
-        }
-        File file = new File(mSourceMediaOnSdcard);
-        if (file.exists()) {
-            file.delete();
-        }
-        if (mServer != null) {
-            mServer.shutdown();
-        }
-        super.tearDown();
-    }
-
-    public void testStreamNullSource() throws Exception {
+public class MediaPlayerTest extends MediaPlayerTestBase {
+    public void testPlayNullSource() throws Exception {
         try {
             mMediaPlayer.setDataSource((String) null);
             fail("Null URI was accepted");
@@ -122,213 +47,61 @@
         final int resid = R.raw.testmp3_2;
 
         MediaPlayer mp = MediaPlayer.create(mContext, resid);
-        mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+        try {
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
 
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-        assertFalse(mp.isLooping());
-        mp.setLooping(true);
-        assertTrue(mp.isLooping());
+            assertFalse(mp.isLooping());
+            mp.setLooping(true);
+            assertTrue(mp.isLooping());
 
-        assertEquals(mp3Duration, mp.getDuration(), tolerance);
-        int pos = mp.getCurrentPosition();
-        assertTrue(pos >= 0);
-        assertTrue(pos < mp3Duration - seekDuration);
+            assertEquals(mp3Duration, mp.getDuration(), tolerance);
+            int pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < mp3Duration - seekDuration);
 
-        mp.seekTo(pos + seekDuration);
-        assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+            mp.seekTo(pos + seekDuration);
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
 
-        // test pause and restart
-        mp.pause();
-        Thread.sleep(SLEEP_TIME);
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
-
-        // test stop and restart
-        mp.stop();
-        mp.reset();
-        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
-        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        afd.close();
-        mp.prepare();
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
-
-        // waiting to complete
-        while(mp.isPlaying()) {
+            // test pause and restart
+            mp.pause();
             Thread.sleep(SLEEP_TIME);
-        }
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-        mp.release();
-    }
+            // test stop and restart
+            mp.stop();
+            mp.reset();
+            AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+            afd.close();
+            mp.prepare();
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-    /*
-     * Initializes the message looper so that the mediaPlayer object can
-     * receive the callback messages.
-     */
-    private static void initializeMessageLooper() {
-        new Thread() {
-            @Override
-            public void run() {
-                // Set up a looper to be used by camera.
-                Looper.prepare();
-                // Save the looper so that we can terminate this thread
-                // after we are done with it.
-                sLooper = Looper.myLooper();
-                synchronized (sLock) {
-                    sLock.notify();
-                }
-                Looper.loop();  // Blocks forever until Looper.quit() is called.
-                Log.v(TAG, "initializeMessageLooper: quit.");
+            // waiting to complete
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
             }
-        }.start();
-    }
-
-    /*
-     * Terminates the message looper thread.
-     */
-    private static void terminateMessageLooper() {
-        sLooper.quit();
+        } finally {
+            mp.release();
+        }
     }
 
     public void testPlayVideo() throws Exception {
-        final int expectedVideoWidth = 352; // width of R.raw.testvideo
-        final int expectedVideoHeight = 288; // height of R.raw.testvideo
-        final float leftVolume = 0.5f;
-        final float rightVolume = 0.5f;
-        final int resid = R.raw.testvideo;
-
-        sLock = new Object();
-        sVideoSizeChanged = new Object();
-        MediaPlayer mp = new MediaPlayer();
-        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
-        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        afd.close();
-        mp.setDisplay(getActivity().getSurfaceHolder());
-        mp.setScreenOnWhilePlaying(true);
-        mp.prepare();
-
-        int videoWidth = 0;
-        int videoHeight = 0;
-        synchronized (sLock) {
-            initializeMessageLooper();
-            try {
-                sLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-            } catch(Exception e) {
-                Log.v(TAG, "looper was interrupted.");
-                return;
-            }
-        }
-        try {
-             mp.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
-             synchronized (sVideoSizeChanged) {
-                 try {
-                     sVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                 } catch (Exception e) {
-                     Log.v(TAG, "wait was interrupted");
-                 }
-             }
-             videoWidth = mp.getVideoWidth();
-             videoHeight = mp.getVideoHeight();
-             terminateMessageLooper();
-        } catch (Exception e) {
-             Log.e(TAG, e.getMessage());
-        }
-        assertEquals(expectedVideoWidth, videoWidth);
-        assertEquals(expectedVideoHeight, videoHeight);
-
-        mp.start();
-        mp.setVolume(leftVolume, rightVolume);
-
-        // waiting to complete
-        while (mp.isPlaying()) {
-            Thread.sleep(SLEEP_TIME);
-        }
-
-        mp.release();
-    }
-
-    public void testPlayMp3Stream1() throws Throwable {
-        streamTest("ringer.mp3", false, false);
-    }
-    public void testPlayMp3Stream2() throws Throwable {
-        streamTest("ringer.mp3", false, false);
-    }
-    public void testPlayMp3StreamRedirect() throws Throwable {
-        streamTest("ringer.mp3", true, false);
-    }
-    public void testPlayMp3StreamNoLength() throws Throwable {
-        streamTest("noiseandchirps.mp3", false, true);
-    }
-    public void testPlayOggStream() throws Throwable {
-        streamTest("noiseandchirps.ogg", false, false);
-    }
-    public void testPlayOggStreamRedirect() throws Throwable {
-        streamTest("noiseandchirps.ogg", true, false);
-    }
-    public void testPlayOggStreamNoLength() throws Throwable {
-        streamTest("noiseandchirps.ogg", false, true);
-    }
-
-    private void streamTest(String name, boolean redirect, boolean nolength) throws Throwable {
-        mServer = new CtsTestServer(mContext);
-        String stream_url = null;
-        if (redirect) {
-            // Stagefright doesn't have a limit, but we can't test support of infinite redirects
-            // Up to 4 redirects seems reasonable though.
-            stream_url = mServer.getRedirectingAssetUrl(name, 4);
-        } else {
-            stream_url = mServer.getAssetUrl(name);
-        }
-        if (nolength) {
-            stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
-        }
-
-        mMediaPlayer.setDataSource(stream_url);
-
-        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
-        mMediaPlayer.setScreenOnWhilePlaying(true);
-
-        mOnBufferingUpdateCalled.reset();
-        mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
-            @Override
-            public void onBufferingUpdate(MediaPlayer mp, int percent) {
-                mOnBufferingUpdateCalled.signal();
-            }
-        });
-
-        assertFalse(mOnBufferingUpdateCalled.isSignalled());
-        mMediaPlayer.prepare();
-
-        if (nolength) {
-            mMediaPlayer.start();
-            Thread.sleep(LONG_SLEEP_TIME);
-            assertFalse(mMediaPlayer.isPlaying());
-        } else {
-            mOnBufferingUpdateCalled.waitForSignal();
-            mMediaPlayer.start();
-            Thread.sleep(SLEEP_TIME);
-        }
-        mMediaPlayer.stop();
-        mMediaPlayer.reset();
+        playVideoTest(R.raw.testvideo, 352, 288);
     }
 
     public void testCallback() throws Throwable {
         final int mp4Duration = 8484;
 
-        AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.testvideo);
-        try {
-            mMediaPlayer.setDataSource(
-                    afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        } finally {
-            afd.close();
-        }
-
+        loadResource(R.raw.testvideo);
         mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
         mMediaPlayer.setScreenOnWhilePlaying(true);
 
@@ -399,28 +172,52 @@
     }
 
     public void testRecordAndPlay() throws Exception {
-        recordMedia();
-        MediaPlayer mp = new MediaPlayer();
-        mp.setDataSource(mSourceMediaOnSdcard);
-        mp.prepareAsync();
-        Thread.sleep(SLEEP_TIME);
-        playAndStop(mp);
-        mp.reset();
-        Uri uri = Uri.parse(mSourceMediaOnSdcard);
-        mp = new MediaPlayer();
-        mp.setDataSource(mContext, uri);
-        mp.prepareAsync();
-        Thread.sleep(SLEEP_TIME);
-        playAndStop(mp);
-        mp.release();
+        File outputFile = new File(Environment.getExternalStorageDirectory(),
+                "record_and_play.3gp");
+        String outputFileLocation = outputFile.getAbsolutePath();
+        try {
+            recordMedia(outputFileLocation);
+            MediaPlayer mp = new MediaPlayer();
+            try {
+                mp.setDataSource(outputFileLocation);
+                mp.prepareAsync();
+                Thread.sleep(SLEEP_TIME);
+                playAndStop(mp);
+            } finally {
+                mp.release();
+            }
 
-        mp = MediaPlayer.create(mContext, uri);
-        playAndStop(mp);
-        mp.release();
+            Uri uri = Uri.parse(outputFileLocation);
+            mp = new MediaPlayer();
+            try {
+                mp.setDataSource(mContext, uri);
+                mp.prepareAsync();
+                Thread.sleep(SLEEP_TIME);
+                playAndStop(mp);
+            } finally {
+                mp.release();
+            }
 
-        mp = MediaPlayer.create(mContext, uri, getActivity().getSurfaceHolder());
-        playAndStop(mp);
-        mp.release();
+            try {
+                mp = MediaPlayer.create(mContext, uri);
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.release();
+                }
+            }
+
+            try {
+                mp = MediaPlayer.create(mContext, uri, getActivity().getSurfaceHolder());
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.release();
+                }
+            }
+        } finally {
+            outputFile.delete();
+        }
     }
 
     private void playAndStop(MediaPlayer mp) throws Exception {
@@ -429,18 +226,20 @@
         mp.stop();
     }
 
-    private void recordMedia() throws Exception {
+    private void recordMedia(String outputFile) throws Exception {
         MediaRecorder mr = new MediaRecorder();
-        mr.setAudioSource(MediaRecorder.AudioSource.MIC);
-        mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
-        mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
-        mr.setOutputFile(mSourceMediaOnSdcard);
+        try {
+            mr.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            mr.setOutputFile(outputFile);
 
-        mr.prepare();
-        mr.start();
-        Thread.sleep(SLEEP_TIME);
-        mr.stop();
-        mr.release();
+            mr.prepare();
+            mr.start();
+            Thread.sleep(SLEEP_TIME);
+            mr.stop();
+        } finally {
+            mr.release();
+        }
     }
-
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
new file mode 100644
index 0000000..b79764e
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2011 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.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.media.MediaPlayer;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+/**
+ * Base class for tests which use MediaPlayer to play audio or video.
+ */
+public class MediaPlayerTestBase extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+    private static String TAG = "MediaPlayerTestBase";
+
+    protected static final int SLEEP_TIME = 1000;
+    protected static final int LONG_SLEEP_TIME = 6000;
+
+    public static class Monitor {
+        private boolean signalled;
+
+        public synchronized void reset() {
+            signalled = false;
+        }
+
+        public synchronized void signal() {
+            signalled = true;
+            notifyAll();
+        }
+
+        public synchronized void waitForSignal() throws InterruptedException {
+            while (!signalled) {
+                wait();
+            }
+        }
+
+        public synchronized boolean isSignalled() {
+            return signalled;
+        }
+    }
+
+    protected Monitor mOnVideoSizeChangedCalled = new Monitor();
+    protected Monitor mOnBufferingUpdateCalled = new Monitor();
+    protected Monitor mOnPrepareCalled = new Monitor();
+    protected Monitor mOnSeekCompleteCalled = new Monitor();
+    protected Monitor mOnCompletionCalled = new Monitor();
+    protected Monitor mOnInfoCalled = new Monitor();
+    protected Monitor mOnErrorCalled = new Monitor();
+
+    protected Context mContext;
+    protected Resources mResources;
+
+    // Video Playback
+    private static Object sVideoSizeChanged;
+    private static Object sLock;
+    private static Looper sLooper = null;
+    private static final int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
+
+    /*
+     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
+     * for the current thread. However, since we don't actually call loop() in the test,
+     * any messages queued with that looper will never be consumed. We instantiate the player
+     * in the constructor, before setUp(), so that its constructor does not see the
+     * nonfunctional Looper.
+     */
+    protected MediaPlayer mMediaPlayer = new MediaPlayer();
+
+    public MediaPlayerTestBase() {
+        super(MediaStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        mResources = mContext.getResources();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.release();
+        }
+        super.tearDown();
+    }
+
+    private static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
+        new MediaPlayer.OnVideoSizeChangedListener() {
+            @Override
+            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
+                synchronized (sVideoSizeChanged) {
+                    Log.v(TAG, "sizechanged notification received ...");
+                    sVideoSizeChanged.notify();
+                }
+            }
+        };
+
+    /*
+     * Initializes the message looper so that the mediaPlayer object can
+     * receive the callback messages.
+     */
+    private static void initializeMessageLooper() {
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by camera.
+                Looper.prepare();
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                sLooper = Looper.myLooper();
+                synchronized (sLock) {
+                    sLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+
+    /*
+     * Terminates the message looper thread.
+     */
+    private static void terminateMessageLooper() {
+        sLooper.quit();
+    }
+
+    protected void loadResource(int resid) throws Exception {
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                    afd.getLength());
+        } finally {
+            afd.close();
+        }
+    }
+
+    protected void playVideoTest(int resid, int width, int height) throws Exception {
+        final float leftVolume = 0.5f;
+        final float rightVolume = 0.5f;
+
+        sLock = new Object();
+        sVideoSizeChanged = new Object();
+        loadResource(resid);
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+            @Override
+            public boolean onError(MediaPlayer mp, int what, int extra) {
+                fail("Media player had error " + what + " playing video");
+                return true;
+            }
+        });
+        mMediaPlayer.prepare();
+
+        int videoWidth = 0;
+        int videoHeight = 0;
+        synchronized (sLock) {
+            initializeMessageLooper();
+            try {
+                sLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return;
+            }
+        }
+        try {
+            mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
+             synchronized (sVideoSizeChanged) {
+                 try {
+                     sVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                 } catch (Exception e) {
+                     Log.v(TAG, "wait was interrupted");
+                 }
+             }
+             videoWidth = mMediaPlayer.getVideoWidth();
+             videoHeight = mMediaPlayer.getVideoHeight();
+             terminateMessageLooper();
+        } catch (Exception e) {
+             Log.e(TAG, e.getMessage());
+        }
+        assertEquals(width, videoWidth);
+        assertEquals(height, videoHeight);
+
+        mMediaPlayer.start();
+        mMediaPlayer.setVolume(leftVolume, rightVolume);
+
+        // waiting to complete
+        while (mMediaPlayer.isPlaying()) {
+            Thread.sleep(SLEEP_TIME);
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestHelpers.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestHelpers.java
deleted file mode 100644
index a6e2bf7..0000000
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestHelpers.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-/**
- * Helper classes and methods for MediaPlayer tests.
- */
-public final class MediaPlayerTestHelpers {
-    private MediaPlayerTestHelpers() {}
-
-    public static class Monitor {
-        private boolean signalled;
-
-        public synchronized void reset() {
-            signalled = false;
-        }
-
-        public synchronized void signal() {
-            signalled = true;
-            notifyAll();
-        }
-
-        public synchronized void waitForSignal() throws InterruptedException {
-            while (!signalled) {
-                wait();
-            }
-        }
-
-        public synchronized boolean isSignalled() {
-            return signalled;
-        }
-    }
-}