2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.mediaframeworktest.unit;
19 import android.util.Log;
20 import android.os.Looper;
21 import android.os.Handler;
22 import android.os.Message;
23 import android.media.MediaPlayer;
24 import android.test.AndroidTestCase;
25 import com.android.mediaframeworktest.MediaNames;
28 * A template class for running a method under test in all possible
29 * states of a MediaPlayer object.
31 * @see com.android.mediaframeworktest.unit.MediaPlayerSeekToStateUnitTest
32 * for an example of using this class.
34 * A typical concrete unit test class would implement the
35 * MediaPlayerMethodUnderTest interface and have a reference to an object of
36 * this class. Then it calls runTestOnMethod() to actually perform the unit
40 class MediaPlayerStateUnitTestTemplate extends AndroidTestCase {
41 private static final String TEST_PATH = MediaNames.TEST_PATH_1;
42 private static final String TAG = "MediaPlayerSeekToStateUnitTest";
43 private static final int SEEK_TO_END = 135110; // Milliseconds.
44 private static int WAIT_FOR_COMMAND_TO_COMPLETE = 1000; // Milliseconds.
46 private MediaPlayerStateErrors mStateErrors = new MediaPlayerStateErrors();
47 private MediaPlayer mMediaPlayer = null;
48 private boolean mInitialized = false;
49 private boolean mOnCompletionHasBeenCalled = false;
50 private MediaPlayerStateErrors.MediaPlayerState mMediaPlayerState = null;
51 private Looper mLooper = null;
52 private final Object lock = new Object();
53 private MediaPlayerMethodUnderTest mMethodUnderTest = null;
55 // An Handler object is absolutely necessary for receiving callback
56 // messages from MediaPlayer objects.
57 private Handler mHandler = new Handler() {
59 public void handleMessage(Message msg) {
62 case MediaPlayerStateErrors.MEDIA_PLAYER_ERROR:
63 Log.v(TAG, "handleMessage: received MEDIA_PLAYER_ERROR message");
66 Log.v(TAG, "handleMessage: received unknown message");
74 * Runs the given method under test in all possible states of a MediaPlayer
77 * @param testMethod the method under test.
79 public void runTestOnMethod(MediaPlayerMethodUnderTest testMethod) {
80 mMethodUnderTest = testMethod;
81 if (mMethodUnderTest != null) { // Method under test has been set?
82 initializeMessageLooper();
85 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
86 } catch(Exception e) {
87 Log.v(TAG, "runTestOnMethod: wait was interrupted.");
90 assertTrue(mInitialized); // mMediaPlayer has been initialized?
91 checkMethodUnderTestInAllPossibleStates();
92 terminateMessageLooper(); // Release message looper thread.
93 assertTrue(mOnCompletionHasBeenCalled);
94 mMethodUnderTest.checkStateErrors(mStateErrors);
100 * Initializes the message looper so that the MediaPlayer object can
101 * receive the callback messages.
103 private void initializeMessageLooper() {
107 // Set up a looper to be used by mMediaPlayer.
110 // Save the looper so that we can terminate this thread
111 // after we are done with it.
112 mLooper = Looper.myLooper();
114 mMediaPlayer = new MediaPlayer();
115 mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
116 public boolean onError(MediaPlayer player, int what, int extra) {
117 Log.v(TAG, "onError has been called.");
119 Log.v(TAG, "notify lock.");
120 setStateError(mMediaPlayerState, true);
121 if (mMediaPlayerState != MediaPlayerStateErrors.MediaPlayerState.ERROR) {
129 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
130 public void onCompletion(MediaPlayer player) {
131 Log.v(TAG, "onCompletion has been called.");
133 if (mMediaPlayerState == MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED) {
134 mOnCompletionHasBeenCalled = true;
144 Looper.loop(); // Blocks forever until Looper.quit() is called.
145 Log.v(TAG, "initializeMessageLooper: quit.");
151 * Calls method under test in the given state of the MediaPlayer object.
153 * @param state the MediaPlayer state in which the method under test is called.
155 private void callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState state) {
156 Log.v(TAG, "call " + mMethodUnderTest + ": started in state " + state);
157 setMediaPlayerToState(state);
158 mMethodUnderTest.invokeMethodUnderTest(mMediaPlayer);
161 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
162 } catch(Exception e) {
163 Log.v(TAG, "callMediaPlayerMethodUnderTestInState: wait is interrupted in state " + state);
166 Log.v(TAG, "call " + mMethodUnderTest + ": ended in state " + state);
170 * The following setMediaPlayerToXXXStateXXX methods sets the MediaPlayer
171 * object to the corresponding state, given the assumption that reset()
172 * always resets the MediaPlayer object to Idle (after reset) state.
174 private void setMediaPlayerToIdleStateAfterReset() {
176 mMediaPlayer.reset();
177 mMediaPlayer.setDataSource(TEST_PATH);
178 mMediaPlayer.prepare();
179 mMediaPlayer.reset();
180 } catch(Exception e) {
181 Log.v(TAG, "setMediaPlayerToIdleStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
186 private void setMediaPlayerToInitializedState() {
188 mMediaPlayer.reset();
189 mMediaPlayer.setDataSource(TEST_PATH);
190 } catch(Exception e) {
191 Log.v(TAG, "setMediaPlayerToInitializedState: Exception " + e.getClass().getName() + " was thrown.");
196 private void setMediaPlayerToPreparedState() {
198 mMediaPlayer.reset();
199 mMediaPlayer.setDataSource(TEST_PATH);
200 mMediaPlayer.prepare();
201 } catch(Exception e) {
202 Log.v(TAG, "setMediaPlayerToPreparedState: Exception " + e.getClass().getName() + " was thrown.");
207 private void setMediaPlayerToPreparedStateAfterStop() {
209 mMediaPlayer.reset();
210 mMediaPlayer.setDataSource(TEST_PATH);
211 mMediaPlayer.prepare();
212 mMediaPlayer.start();
214 mMediaPlayer.prepare();
215 } catch(Exception e) {
216 Log.v(TAG, "setMediaPlayerToPreparedStateAfterStop: Exception " + e.getClass().getName() + " was thrown.");
221 private void setMediaPlayerToStartedState() {
223 mMediaPlayer.reset();
224 mMediaPlayer.setDataSource(TEST_PATH);
225 mMediaPlayer.prepare();
226 mMediaPlayer.start();
227 } catch(Exception e) {
228 Log.v(TAG, "setMediaPlayerToStartedState: Exception " + e.getClass().getName() + " was thrown.");
233 private void setMediaPlayerToStartedStateAfterPause() {
235 mMediaPlayer.reset();
236 mMediaPlayer.setDataSource(TEST_PATH);
237 mMediaPlayer.prepare();
238 mMediaPlayer.start();
239 mMediaPlayer.pause();
241 // pause() is an asynchronous call and returns immediately, but
242 // PV player engine may take quite a while to actually set the
243 // player state to Paused; if we call start() right after pause()
244 // without waiting, start() may fail.
246 Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
247 } catch(Exception ie) {
248 Log.v(TAG, "sleep was interrupted and terminated prematurely");
251 mMediaPlayer.start();
252 } catch(Exception e) {
253 Log.v(TAG, "setMediaPlayerToStartedStateAfterPause: Exception " + e.getClass().getName() + " was thrown.");
258 private void setMediaPlayerToPausedState() {
260 mMediaPlayer.reset();
261 mMediaPlayer.setDataSource(TEST_PATH);
262 mMediaPlayer.prepare();
263 mMediaPlayer.start();
264 mMediaPlayer.pause();
265 } catch(Exception e) {
266 Log.v(TAG, "setMediaPlayerToPausedState: Exception " + e.getClass().getName() + " was thrown.");
271 private void setMediaPlayerToStoppedState() {
273 mMediaPlayer.reset();
274 mMediaPlayer.setDataSource(TEST_PATH);
275 mMediaPlayer.prepare();
276 mMediaPlayer.start();
278 } catch(Exception e) {
279 Log.v(TAG, "setMediaPlayerToStoppedState: Exception " + e.getClass().getName() + " was thrown.");
284 private void setMediaPlayerToPlaybackCompletedState() {
286 mMediaPlayer.reset();
287 mMediaPlayer.setDataSource(TEST_PATH);
288 mMediaPlayer.prepare();
289 mMediaPlayer.seekTo(SEEK_TO_END);
290 mMediaPlayer.start();
293 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
294 } catch(Exception e) {
295 Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: wait was interrupted.");
298 } catch(Exception e) {
299 Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: Exception " + e.getClass().getName() + " was thrown.");
302 Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: done.");
306 * There are a lot of ways to force the MediaPlayer object to enter
307 * the Error state. The impact (such as onError is called or not) highly
308 * depends on how the Error state is entered.
310 private void setMediaPlayerToErrorState() {
312 mMediaPlayer.reset();
313 mMediaPlayer.setDataSource(TEST_PATH);
314 mMediaPlayer.start();
317 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
318 } catch(Exception e) {
319 Log.v(TAG, "setMediaPlayerToErrorState: wait was interrupted.");
322 } catch(Exception e) {
323 Log.v(TAG, "setMediaPlayerToErrorState: Exception " + e.getClass().getName() + " was thrown.");
324 assertTrue(e instanceof IllegalStateException);
326 Log.v(TAG, "setMediaPlayerToErrorState: done.");
330 * Sets the state of the MediaPlayer object to the specified one.
332 * @param state the state of the MediaPlayer object.
334 private void setMediaPlayerToState(MediaPlayerStateErrors.MediaPlayerState state) {
335 mMediaPlayerState = state;
340 case IDLE_AFTER_RESET:
341 setMediaPlayerToIdleStateAfterReset();
344 setMediaPlayerToInitializedState();
347 setMediaPlayerToPreparedState();
349 case PREPARED_AFTER_STOP:
350 setMediaPlayerToPreparedStateAfterStop();
353 setMediaPlayerToStartedState();
355 case STARTED_AFTER_PAUSE:
356 setMediaPlayerToStartedStateAfterPause();
359 setMediaPlayerToPausedState();
362 setMediaPlayerToStoppedState();
364 case PLAYBACK_COMPLETED:
365 setMediaPlayerToPlaybackCompletedState();
368 setMediaPlayerToErrorState();
374 * Sets the error value of the corresponding state to the given error.
376 * @param state the state of the MediaPlayer object.
377 * @param error the value of the state error to be set.
379 private void setStateError(MediaPlayerStateErrors.MediaPlayerState state, boolean error) {
382 mStateErrors.errorInIdleState = error;
384 case IDLE_AFTER_RESET:
385 mStateErrors.errorInIdleStateAfterReset = error;
388 mStateErrors.errorInInitializedState = error;
391 mStateErrors.errorInPreparedState = error;
393 case PREPARED_AFTER_STOP:
394 mStateErrors.errorInPreparedStateAfterStop = error;
397 mStateErrors.errorInStartedState = error;
399 case STARTED_AFTER_PAUSE:
400 mStateErrors.errorInStartedStateAfterPause = error;
403 mStateErrors.errorInPausedState = error;
406 mStateErrors.errorInStoppedState = error;
408 case PLAYBACK_COMPLETED:
409 mStateErrors.errorInPlaybackCompletedState = error;
412 mStateErrors.errorInErrorState = error;
417 private void notifyStateError() {
418 mHandler.sendMessage(mHandler.obtainMessage(MediaPlayerStateErrors.MEDIA_PLAYER_ERROR));
421 private void checkIdleState() {
422 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE);
425 private void checkIdleStateAfterReset() {
426 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE_AFTER_RESET);
429 private void checkInitializedState() {
430 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.INITIALIZED);
433 private void checkPreparedState() {
434 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED);
437 private void checkPreparedStateAfterStop() {
438 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED_AFTER_STOP);
441 private void checkStartedState() {
442 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED);
445 private void checkPausedState() {
446 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PAUSED);
449 private void checkStartedStateAfterPause() {
450 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED_AFTER_PAUSE);
453 private void checkStoppedState() {
454 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STOPPED);
457 private void checkPlaybackCompletedState() {
458 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED);
461 private void checkErrorState() {
462 callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.ERROR);
466 * Checks the given method under test in all possible states of the MediaPlayer object.
468 private void checkMethodUnderTestInAllPossibleStates() {
469 // Must be called first.
472 // The sequence of the following method calls should not
473 // affect the test results.
475 checkIdleStateAfterReset();
476 checkInitializedState();
478 checkStartedStateAfterPause();
480 checkPreparedState();
482 checkPreparedStateAfterStop();
484 checkPlaybackCompletedState();
489 * Terminates the message looper thread.
491 private void terminateMessageLooper() {
493 mMediaPlayer.release();
497 * Cleans up all the internal object references.
499 private void cleanUp() {
501 mMediaPlayerState = null;
504 mMethodUnderTest = null;