OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / tests / MediaFrameworkTest / src / com / android / mediaframeworktest / unit / MediaPlayerStateUnitTestTemplate.java
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.mediaframeworktest.unit;
18
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;
26
27 /**
28  * A template class for running a method under test in all possible
29  * states of a MediaPlayer object.
30  * 
31  * @see com.android.mediaframeworktest.unit.MediaPlayerSeekToStateUnitTest
32  * for an example of using this class.
33  * 
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
37  * tests.
38  * 
39  */
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.
45     
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;
54     
55     // An Handler object is absolutely necessary for receiving callback 
56     // messages from MediaPlayer objects.
57     private Handler mHandler = new Handler() {
58         @Override
59         public void handleMessage(Message msg) {
60             /*
61             switch(msg.what) {
62                 case MediaPlayerStateErrors.MEDIA_PLAYER_ERROR:
63                     Log.v(TAG, "handleMessage: received MEDIA_PLAYER_ERROR message");
64                     break;
65                 default:
66                     Log.v(TAG, "handleMessage: received unknown message");
67                 break;
68             }
69             */
70         }
71     };
72     
73     /**
74      * Runs the given method under test in all possible states of a MediaPlayer
75      * object.
76      * 
77      * @param testMethod the method under test.
78      */
79     public void runTestOnMethod(MediaPlayerMethodUnderTest testMethod) {
80         mMethodUnderTest = testMethod;
81         if (mMethodUnderTest != null) {  // Method under test has been set?
82             initializeMessageLooper();
83             synchronized(lock) {
84                 try {
85                     lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
86                 } catch(Exception e) {
87                     Log.v(TAG, "runTestOnMethod: wait was interrupted.");
88                 }
89             }
90             assertTrue(mInitialized);  // mMediaPlayer has been initialized?
91             checkMethodUnderTestInAllPossibleStates();
92             terminateMessageLooper();   // Release message looper thread.
93             assertTrue(mOnCompletionHasBeenCalled);
94             mMethodUnderTest.checkStateErrors(mStateErrors);
95             cleanUp();
96         }
97     }
98     
99     /*
100      * Initializes the message looper so that the MediaPlayer object can 
101      * receive the callback messages.
102      */
103     private void initializeMessageLooper() {
104         new Thread() {
105             @Override
106             public void run() {
107                 // Set up a looper to be used by mMediaPlayer.
108                 Looper.prepare();
109
110                 // Save the looper so that we can terminate this thread 
111                 // after we are done with it.
112                 mLooper = Looper.myLooper();
113                 
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.");
118                         synchronized(lock) {
119                             Log.v(TAG, "notify lock.");
120                             setStateError(mMediaPlayerState, true);
121                             if (mMediaPlayerState != MediaPlayerStateErrors.MediaPlayerState.ERROR) {
122                                 notifyStateError();
123                             }
124                             lock.notify();
125                         }
126                         return true;
127                     }
128                 });
129                 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
130                     public void onCompletion(MediaPlayer player) {
131                         Log.v(TAG, "onCompletion has been called.");
132                         synchronized(lock) {
133                             if (mMediaPlayerState == MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED) {
134                                 mOnCompletionHasBeenCalled = true;
135                             }
136                             lock.notify();
137                         }
138                     }
139                 });
140                 synchronized(lock) {
141                     mInitialized = true;
142                     lock.notify();
143                 }
144                 Looper.loop();  // Blocks forever until Looper.quit() is called.
145                 Log.v(TAG, "initializeMessageLooper: quit.");
146             }
147         }.start();
148     }
149     
150     /*
151      * Calls method under test in the given state of the MediaPlayer object.
152      * 
153      * @param state the MediaPlayer state in which the method under test is called.
154      */
155     private void callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState state) {
156         Log.v(TAG, "call " + mMethodUnderTest + ": started in state " + state);
157         setMediaPlayerToState(state);
158         mMethodUnderTest.invokeMethodUnderTest(mMediaPlayer);
159         synchronized(lock) {
160             try {
161                 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
162            } catch(Exception e) {
163                Log.v(TAG, "callMediaPlayerMethodUnderTestInState: wait is interrupted in state " + state);
164            }
165         }
166         Log.v(TAG, "call " + mMethodUnderTest + ": ended in state " + state);
167     }
168
169     /*
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. 
173      */
174     private void setMediaPlayerToIdleStateAfterReset() {
175         try {
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.");
182             assertTrue(false);
183         }
184     }
185     
186     private void setMediaPlayerToInitializedState() {
187         try {
188             mMediaPlayer.reset();
189             mMediaPlayer.setDataSource(TEST_PATH);
190         } catch(Exception e) {
191             Log.v(TAG, "setMediaPlayerToInitializedState: Exception " + e.getClass().getName() + " was thrown.");
192             assertTrue(false);
193         }
194     }
195     
196     private void setMediaPlayerToPreparedState() {
197         try {
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.");
203             assertTrue(false);
204         }
205     }
206     
207     private void setMediaPlayerToPreparedStateAfterStop() {
208         try {
209             mMediaPlayer.reset();
210             mMediaPlayer.setDataSource(TEST_PATH);
211             mMediaPlayer.prepare();
212             mMediaPlayer.start();
213             mMediaPlayer.stop();
214             mMediaPlayer.prepare();
215         } catch(Exception e) {
216             Log.v(TAG, "setMediaPlayerToPreparedStateAfterStop: Exception " + e.getClass().getName() + " was thrown.");
217             assertTrue(false);
218         }
219     }
220     
221     private void setMediaPlayerToStartedState() {
222         try {
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.");
229             assertTrue(false);
230         }
231     }
232     
233     private void setMediaPlayerToStartedStateAfterPause() {
234         try {
235             mMediaPlayer.reset();
236             mMediaPlayer.setDataSource(TEST_PATH);
237             mMediaPlayer.prepare();
238             mMediaPlayer.start();
239             mMediaPlayer.pause();
240
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.
245             try {
246                 Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
247             } catch(Exception ie) {
248                 Log.v(TAG, "sleep was interrupted and terminated prematurely");
249             }
250
251             mMediaPlayer.start();
252         } catch(Exception e) {
253             Log.v(TAG, "setMediaPlayerToStartedStateAfterPause: Exception " + e.getClass().getName() + " was thrown.");
254             assertTrue(false);
255         }
256     }
257     
258     private void setMediaPlayerToPausedState() {
259         try {
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.");
267             assertTrue(false);
268         }
269     }
270     
271     private void setMediaPlayerToStoppedState() {
272         try {
273             mMediaPlayer.reset();
274             mMediaPlayer.setDataSource(TEST_PATH);
275             mMediaPlayer.prepare();
276             mMediaPlayer.start();
277             mMediaPlayer.stop();
278         } catch(Exception e) {
279             Log.v(TAG, "setMediaPlayerToStoppedState: Exception " + e.getClass().getName() + " was thrown.");
280             assertTrue(false);
281         }
282     }
283     
284     private void setMediaPlayerToPlaybackCompletedState() {
285         try {
286             mMediaPlayer.reset();
287             mMediaPlayer.setDataSource(TEST_PATH);
288             mMediaPlayer.prepare();
289             mMediaPlayer.seekTo(SEEK_TO_END);
290             mMediaPlayer.start();
291             synchronized(lock) {
292                 try {
293                     lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
294                 } catch(Exception e) {
295                     Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: wait was interrupted.");
296                 }
297             }
298         } catch(Exception e) {
299             Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: Exception " + e.getClass().getName() + " was thrown.");
300             assertTrue(false);
301         }
302         Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: done.");
303     }
304     
305     /*
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.
309      */
310     private void setMediaPlayerToErrorState() {
311         try {
312             mMediaPlayer.reset();
313             mMediaPlayer.setDataSource(TEST_PATH);
314             mMediaPlayer.start();
315             synchronized(lock) {
316                 try {
317                     lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
318                 } catch(Exception e) {
319                     Log.v(TAG, "setMediaPlayerToErrorState: wait was interrupted.");
320                 }
321             }
322         } catch(Exception e) {
323             Log.v(TAG, "setMediaPlayerToErrorState: Exception " + e.getClass().getName() + " was thrown.");
324             assertTrue(e instanceof IllegalStateException);
325         }
326         Log.v(TAG, "setMediaPlayerToErrorState: done.");
327     }
328     
329     /*
330      * Sets the state of the MediaPlayer object to the specified one.
331      * 
332      * @param state the state of the MediaPlayer object.
333      */
334     private void setMediaPlayerToState(MediaPlayerStateErrors.MediaPlayerState state) {
335         mMediaPlayerState = state;
336         switch(state) {
337             case IDLE:
338                 // Does nothing.
339                 break;
340             case IDLE_AFTER_RESET:
341                 setMediaPlayerToIdleStateAfterReset();
342                 break;
343             case INITIALIZED:
344                 setMediaPlayerToInitializedState();
345                 break;
346             case PREPARED:
347                 setMediaPlayerToPreparedState();
348                 break;
349             case PREPARED_AFTER_STOP:
350                 setMediaPlayerToPreparedStateAfterStop();
351                 break;
352             case STARTED:
353                 setMediaPlayerToStartedState();
354                 break;
355             case STARTED_AFTER_PAUSE:
356                 setMediaPlayerToStartedStateAfterPause();
357                 break;
358             case PAUSED:
359                 setMediaPlayerToPausedState();
360                 break;
361             case STOPPED:
362                 setMediaPlayerToStoppedState();
363                 break;
364             case PLAYBACK_COMPLETED:
365                 setMediaPlayerToPlaybackCompletedState();
366                 break;
367             case ERROR:
368                 setMediaPlayerToErrorState();
369                 break;
370         }
371     }
372     
373     /*
374      * Sets the error value of the corresponding state to the given error.
375      * 
376      * @param state the state of the MediaPlayer object.
377      * @param error the value of the state error to be set.
378      */
379     private void setStateError(MediaPlayerStateErrors.MediaPlayerState state, boolean error) {
380         switch(state) {
381             case IDLE:
382                 mStateErrors.errorInIdleState = error;
383                 break;
384             case IDLE_AFTER_RESET:
385                 mStateErrors.errorInIdleStateAfterReset = error;
386                 break;
387             case INITIALIZED:
388                 mStateErrors.errorInInitializedState = error;
389                 break;
390             case PREPARED:
391                 mStateErrors.errorInPreparedState = error;
392                 break;
393             case PREPARED_AFTER_STOP:
394                 mStateErrors.errorInPreparedStateAfterStop = error;
395                 break;
396             case STARTED:
397                 mStateErrors.errorInStartedState = error;
398                 break;
399             case STARTED_AFTER_PAUSE:
400                 mStateErrors.errorInStartedStateAfterPause = error;
401                 break;
402             case PAUSED:
403                 mStateErrors.errorInPausedState = error;
404                 break;
405             case STOPPED:
406                 mStateErrors.errorInStoppedState = error;
407                 break;
408             case PLAYBACK_COMPLETED:
409                 mStateErrors.errorInPlaybackCompletedState = error;
410                 break;
411             case ERROR:
412                 mStateErrors.errorInErrorState = error;
413                 break;
414         }
415     }
416     
417     private void notifyStateError() {
418         mHandler.sendMessage(mHandler.obtainMessage(MediaPlayerStateErrors.MEDIA_PLAYER_ERROR));
419     }
420
421     private void checkIdleState() {
422         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE);
423     }
424     
425     private void checkIdleStateAfterReset() {
426         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE_AFTER_RESET);
427     }
428     
429     private void checkInitializedState() {
430         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.INITIALIZED);
431     }
432     
433     private void checkPreparedState() {
434         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED);
435     }
436     
437     private void checkPreparedStateAfterStop() {
438         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED_AFTER_STOP);
439     }
440     
441     private void checkStartedState() {
442         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED);
443     }
444     
445     private void checkPausedState() {
446         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PAUSED);
447     }
448     
449     private void checkStartedStateAfterPause() {
450         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED_AFTER_PAUSE);
451     }
452     
453     private void checkStoppedState() {
454         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STOPPED);
455     }
456     
457     private void checkPlaybackCompletedState() {
458         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED);
459     }
460     
461     private void checkErrorState() {
462         callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.ERROR);
463     }
464
465     /*
466      * Checks the given method under test in all possible states of the MediaPlayer object.
467      */
468     private void checkMethodUnderTestInAllPossibleStates() {
469         // Must be called first.
470         checkIdleState(); 
471         
472         // The sequence of the following method calls should not 
473         // affect the test results.
474         checkErrorState();
475         checkIdleStateAfterReset();
476         checkInitializedState();
477         checkStartedState();
478         checkStartedStateAfterPause();
479         checkPausedState();
480         checkPreparedState();
481         
482         checkPreparedStateAfterStop();
483         
484         checkPlaybackCompletedState();
485         checkStoppedState();
486     }
487     
488     /*
489      * Terminates the message looper thread.
490      */
491     private void terminateMessageLooper() {
492         mLooper.quit();
493         mMediaPlayer.release();
494     }
495     
496     /*
497      * Cleans up all the internal object references.
498      */
499     private void cleanUp() {
500         mMediaPlayer = null;
501         mMediaPlayerState = null;
502         mLooper = null;
503         mStateErrors = null;
504         mMethodUnderTest = null;
505     }
506 }