1 /*
2  * Copyright (C) 2012 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 android.mediastress.cts;
18 
19 import android.content.res.AssetFileDescriptor;
20 import android.graphics.Bitmap;
21 import android.graphics.BitmapFactory;
22 import android.media.MediaMetadataRetriever;
23 import android.media.MediaPlayer;
24 import android.media.MediaRecorder;
25 import android.os.Looper;
26 import android.os.SystemClock;
27 import android.util.Log;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.TimeUnit;
33 
34 /**
35  * Junit / Instrumentation test case for the media player api
36  */
37 public class CodecTest {
38     private static String TAG = "CodecTest";
39     private static MediaPlayer mMediaPlayer;
40     private MediaPlayer.OnPreparedListener mOnPreparedListener;
41 
42     private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
43     private static boolean mInitialized = false;
44     private static boolean mPrepareReset = false;
45     private static Looper mLooper = null;
46     private static final Object mLock = new Object();
47     private static final Object mPrepareDone = new Object();
48     private static final Object mVideoSizeChanged = new Object();
49     private static boolean mOnPrepareSuccess = false;
50     private static final long PAUSE_WAIT_TIME = 3000;
51     private static final long WAIT_TIME = 2000;
52     private static final int SEEK_TIME = 10000;
53     private static final int PLAYBACK_SETTLE_TIME_MS = 5000;
54     private static final int SETUP_SETTLE_TIME_MS = 5000;
55 
56     public static CountDownLatch mFirstFrameLatch;
57     public static CountDownLatch mCompletionLatch;
58     public static boolean mOnCompleteSuccess = false;
59     public static boolean mPlaybackError = false;
60 
61     public static int mMediaInfoUnknownCount = 0;
62     public static int mMediaInfoVideoTrackLaggingCount = 0;
63     public static int mMediaInfoBadInterleavingCount = 0;
64     public static int mMediaInfoNotSeekableCount = 0;
65     public static int mMediaInfoMetdataUpdateCount = 0;
66 
printCpuInfo()67     public static String printCpuInfo() {
68         String cm = "dumpsys cpuinfo";
69         String cpuinfo = null;
70         int ch;
71         try {
72             Process  p = Runtime.getRuntime().exec(cm);
73             InputStream in = p.getInputStream();
74             StringBuffer sb = new StringBuffer(512);
75             while ( ( ch = in.read() ) != -1 ) {
76                 sb.append((char) ch);
77             }
78             cpuinfo = sb.toString();
79         } catch (IOException e) {
80             Log.v(TAG, e.toString());
81         }
82         return cpuinfo;
83     }
84 
85 
getDuration(String filePath)86     public static int getDuration(String filePath) {
87         Log.v(TAG, "getDuration - " + filePath);
88         MediaPlayer mp = new MediaPlayer();
89         try {
90             mp.setDataSource(filePath);
91             mp.prepare();
92         } catch (Exception e) {
93             Log.v(TAG, e.toString());
94         }
95         int duration = mp.getDuration();
96         Log.v(TAG, "Duration " + duration);
97         mp.release();
98         Log.v(TAG, "release");
99         return duration;
100     }
101 
getCurrentPosition(String filePath)102     public static boolean getCurrentPosition(String filePath) {
103         Log.v(TAG, "GetCurrentPosition - " + filePath);
104         int currentPosition = 0;
105         long t1=0;
106         long t2 =0;
107         MediaPlayer mp = new MediaPlayer();
108         try {
109             mp.setDataSource(filePath);
110             Log.v(TAG, "start playback");
111             mp.prepare();
112             mp.start();
113             t1=SystemClock.uptimeMillis();
114             Thread.sleep(10000);
115             mp.pause();
116             Thread.sleep(PAUSE_WAIT_TIME);
117             t2=SystemClock.uptimeMillis();
118         } catch (Exception e) {
119             Log.v(TAG, e.toString());
120         }
121         currentPosition = mp.getCurrentPosition();
122         mp.stop();
123         mp.release();
124         Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
125 
126         if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0))
127             return true;
128         else
129             return false;
130     }
131 
seekTo(String filePath)132     public static boolean seekTo(String filePath) {
133         Log.v(TAG, "seekTo " + filePath);
134         int currentPosition = 0;
135         MediaPlayer mp = new MediaPlayer();
136         try {
137             mp.setDataSource(filePath);
138             mp.prepare();
139             mp.start();
140             mp.seekTo(SEEK_TIME);
141             Thread.sleep(WAIT_TIME);
142             currentPosition = mp.getCurrentPosition();
143         } catch (Exception e) {
144             Log.v(TAG, e.getMessage());
145         }
146         mp.stop();
147         mp.release();
148         Log.v(TAG, "CurrentPosition = " + currentPosition);
149         //The currentposition should be at least greater than the 80% of seek time
150         if ((currentPosition > SEEK_TIME *0.8))
151             return true;
152         else
153             return false;
154     }
155 
setLooping(String filePath)156     public static boolean setLooping(String filePath) {
157         int currentPosition = 0;
158         int duration = 0;
159         long t1 =0;
160         long t2 =0;
161         Log.v (TAG, "SetLooping - " + filePath);
162         MediaPlayer mp = new MediaPlayer();
163         try {
164             mp.setDataSource(filePath);
165             mp.prepare();
166             duration = mp.getDuration();
167             Log.v(TAG, "setLooping duration " + duration);
168             mp.setLooping(true);
169             mp.start();
170             Thread.sleep(5000);
171             mp.seekTo(duration - 5000);
172             t1=SystemClock.uptimeMillis();
173             Thread.sleep(20000);
174             t2=SystemClock.uptimeMillis();
175             Log.v(TAG, "pause");
176             //Bug# 1106852 - IllegalStateException will be thrown if pause is called
177             //in here
178             //mp.pause();
179             currentPosition = mp.getCurrentPosition();
180             Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
181         } catch (Exception e) {
182             Log.v(TAG, "Exception : " + e.toString());
183         }
184         mp.stop();
185         mp.release();
186         //The current position should be within 20% of the sleep time
187         //and should be greater than zero.
188         if ((currentPosition < ((t2-t1-5000)*1.2)) && currentPosition > 0)
189             return true;
190         else
191             return false;
192     }
193 
pause(String filePath)194     public static boolean pause(String filePath) throws Exception {
195         Log.v(TAG, "pause - " + filePath);
196         boolean misPlaying = true;
197         boolean pauseResult = false;
198         long t1=0;
199         long t2=0;
200         MediaPlayer mp = new MediaPlayer();
201         mp.setDataSource(filePath);
202         mp.prepare();
203         int duration = mp.getDuration();
204         mp.start();
205         t1=SystemClock.uptimeMillis();
206         Thread.sleep(5000);
207         mp.pause();
208         Thread.sleep(PAUSE_WAIT_TIME);
209         t2=SystemClock.uptimeMillis();
210         misPlaying = mp.isPlaying();
211         int curPosition = mp.getCurrentPosition();
212         Log.v(TAG, filePath + " pause currentPositon " + curPosition);
213         Log.v(TAG, "isPlaying "+ misPlaying + " wait time " + (t2 - t1) );
214         String cpuinfo = printCpuInfo();
215         Log.v(TAG, cpuinfo);
216         if ((curPosition>0) && (curPosition < ((t2-t1) * 1.3)) && (misPlaying == false))
217             pauseResult = true;
218         mp.stop();
219         mp.release();
220         return pauseResult;
221     }
222 
prepareStopRelease(String filePath)223     public static void prepareStopRelease(String filePath) throws Exception {
224         Log.v(TAG, "prepareStopRelease" + filePath);
225         MediaPlayer mp = new MediaPlayer();
226         mp.setDataSource(filePath);
227         mp.prepare();
228         mp.stop();
229         mp.release();
230     }
231 
preparePauseRelease(String filePath)232     public static void preparePauseRelease(String filePath) throws Exception {
233         Log.v(TAG, "preparePauseRelease" + filePath);
234         MediaPlayer mp = new MediaPlayer();
235         mp.setDataSource(filePath);
236         mp.prepare();
237         mp.pause();
238         mp.release();
239     }
240 
241     static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
242         new MediaPlayer.OnVideoSizeChangedListener() {
243             public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
244                 synchronized (mVideoSizeChanged) {
245                     Log.v(TAG, "sizechanged notification received ...");
246                     mVideoSizeChanged.notify();
247                 }
248             }
249     };
250 
251     //Register the videoSizeChanged listener
videoHeight(String filePath)252     public static int videoHeight(String filePath) throws Exception {
253         Log.v(TAG, "videoHeight - " + filePath);
254         int videoHeight = 0;
255         synchronized (mLock) {
256             initializeMessageLooper();
257             try {
258                 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
259             } catch(Exception e) {
260                 Log.v(TAG, "looper was interrupted.");
261                 return 0;
262             }
263         }
264         try {
265             mMediaPlayer.setDataSource(filePath);
266             mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
267             mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
268             synchronized (mVideoSizeChanged) {
269                 try {
270                     mMediaPlayer.prepare();
271                     mMediaPlayer.start();
272                     mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
273                 } catch (Exception e) {
274                     Log.v(TAG, "wait was interrupted");
275                 }
276             }
277             videoHeight = mMediaPlayer.getVideoHeight();
278             terminateMessageLooper();
279         } catch (Exception e) {
280             Log.e(TAG, e.getMessage());
281         }
282 
283         return videoHeight;
284     }
285 
286     //Register the videoSizeChanged listener
videoWidth(String filePath)287     public static int videoWidth(String filePath) throws Exception {
288         Log.v(TAG, "videoWidth - " + filePath);
289         int videoWidth = 0;
290 
291         synchronized (mLock) {
292             initializeMessageLooper();
293             try {
294                 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
295             } catch(Exception e) {
296                 Log.v(TAG, "looper was interrupted.");
297                 return 0;
298             }
299         }
300         try {
301             mMediaPlayer.setDataSource(filePath);
302             mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
303             mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
304             synchronized (mVideoSizeChanged) {
305                 try {
306                     mMediaPlayer.prepare();
307                     mMediaPlayer.start();
308                     mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
309                 } catch (Exception e) {
310                     Log.v(TAG, "wait was interrupted");
311                 }
312             }
313             videoWidth = mMediaPlayer.getVideoWidth();
314             terminateMessageLooper();
315         } catch (Exception e) {
316             Log.e(TAG, e.getMessage());
317         }
318         return videoWidth;
319     }
320 
321     //This also test the streaming video which may take a long
322     //time to start the playback.
videoSeekTo(String filePath)323     public static boolean videoSeekTo(String filePath) throws Exception {
324         Log.v(TAG, "videoSeekTo - " + filePath);
325         int currentPosition = 0;
326         int duration = 0;
327         boolean videoResult = false;
328         MediaPlayer mp = new MediaPlayer();
329         mp.setDataSource(filePath);
330         mp.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
331         mp.prepare();
332         mp.start();
333 
334         Thread.sleep(5000);
335         duration = mp.getDuration();
336         Log.v(TAG, "video duration " + duration);
337         mp.pause();
338         Thread.sleep(PAUSE_WAIT_TIME);
339         mp.seekTo(duration - 20000 );
340         mp.start();
341         Thread.sleep(1000);
342         mp.pause();
343         Thread.sleep(PAUSE_WAIT_TIME);
344         mp.seekTo(duration/2);
345         mp.start();
346         Thread.sleep(10000);
347         currentPosition = mp.getCurrentPosition();
348         Log.v(TAG, "video currentPosition " + currentPosition);
349         mp.release();
350         if (currentPosition > (duration /2 )*0.9)
351             return true;
352         else
353             return false;
354 
355     }
356 
seekToEnd(String filePath)357     public static boolean seekToEnd(String filePath) {
358         Log.v(TAG, "seekToEnd - " + filePath);
359         int duration = 0;
360         int currentPosition = 0;
361         boolean isPlaying = false;
362         MediaPlayer mp = new MediaPlayer();
363         try {
364             mp.setDataSource(filePath);
365             Log.v(TAG, "start playback");
366             mp.prepare();
367             duration = mp.getDuration();
368             mp.seekTo(duration - 3000);
369             mp.start();
370             Thread.sleep(6000);
371         } catch (Exception e) {}
372         isPlaying = mp.isPlaying();
373         currentPosition = mp.getCurrentPosition();
374         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
375         mp.stop();
376         mp.release();
377         Log.v(TAG, "duration = " + duration);
378         if (currentPosition < 0.9 * duration || isPlaying)
379             return false;
380         else
381             return true;
382     }
383 
shortMediaStop(String filePath)384     public static boolean shortMediaStop(String filePath) {
385         Log.v(TAG, "shortMediaStop - " + filePath);
386         //This test is only for the short media file
387         int duration = 0;
388         int currentPosition = 0;
389         boolean isPlaying = false;
390         MediaPlayer mp = new MediaPlayer();
391         try {
392             mp.setDataSource(filePath);
393             Log.v(TAG, "start playback");
394             mp.prepare();
395             duration = mp.getDuration();
396             mp.start();
397             Thread.sleep(10000);
398         } catch (Exception e) {}
399         isPlaying = mp.isPlaying();
400         currentPosition = mp.getCurrentPosition();
401         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
402         mp.stop();
403         mp.release();
404         Log.v(TAG, "duration = " + duration);
405         if (currentPosition > duration || isPlaying)
406             return false;
407         else
408             return true;
409     }
410 
playToEnd(String filePath)411     public static boolean playToEnd(String filePath) {
412         Log.v(TAG, "shortMediaStop - " + filePath);
413         //This test is only for the short media file
414         int duration = 200000;
415         int updateDuration = 0;
416         int currentPosition = 0;
417         boolean isPlaying = false;
418         MediaPlayer mp = new MediaPlayer();
419         try {
420             Thread.sleep(5000);
421             mp.setDataSource(filePath);
422             Log.v(TAG, "start playback");
423             mp.prepare();
424             //duration = mp.getDuration();
425             mp.start();
426             Thread.sleep(50000);
427         } catch (Exception e){}
428         isPlaying = mp.isPlaying();
429         currentPosition = mp.getCurrentPosition();
430         //updateDuration = mp.getDuration();
431         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
432         mp.stop();
433         mp.release();
434         //Log.v(TAG, "duration = " + duration);
435         //Log.v(TAG, "Update duration = " + updateDuration);
436         if (currentPosition > duration || isPlaying)
437             return false;
438         else
439             return true;
440     }
441 
seektoBeforeStart(String filePath)442     public static boolean seektoBeforeStart(String filePath){
443         Log.v(TAG, "seektoBeforeStart - " + filePath);
444         //This test is only for the short media file
445         int duration = 0;
446         int currentPosition = 0;
447 
448         MediaPlayer mp = new MediaPlayer();
449         try {
450             mp.setDataSource(filePath);
451             mp.prepare();
452             duration = mp.getDuration();
453             mp.seekTo(duration - 10000);
454             mp.start();
455             currentPosition=mp.getCurrentPosition();
456             mp.stop();
457             mp.release();
458         } catch (Exception e) {}
459         if (currentPosition < duration/2)
460             return false;
461         else
462             return true;
463     }
464 
mediaRecorderRecord(String filePath)465     public static boolean mediaRecorderRecord(String filePath){
466         Log.v(TAG, "SoundRecording - " + filePath);
467         //This test is only for the short media file
468         int duration = 0;
469         try {
470             MediaRecorder mRecorder = new MediaRecorder();
471             mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
472             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
473             mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
474             mRecorder.setOutputFile(filePath);
475             mRecorder.prepare();
476             mRecorder.start();
477             Thread.sleep(500);
478             mRecorder.stop();
479             Log.v(TAG, "sound recorded");
480             mRecorder.release();
481         } catch (Exception e) {
482             Log.v(TAG, e.toString());
483         }
484 
485         //Verify the recorded file
486         MediaPlayer mp = new MediaPlayer();
487         try {
488             mp.setDataSource(filePath);
489             mp.prepare();
490             duration = mp.getDuration();
491             Log.v(TAG,"Duration " + duration);
492             mp.release();
493         } catch (Exception e) {}
494         //Check the record media file length is greate than zero
495         if (duration > 0)
496             return true;
497         else
498             return false;
499 
500     }
501 
502     //Test for mediaMeta Data Thumbnail
getThumbnail(String filePath, String goldenPath)503     public static boolean getThumbnail(String filePath, String goldenPath) {
504         Log.v(TAG, "getThumbnail - " + filePath);
505 
506         int goldenHeight = 0;
507         int goldenWidth = 0;
508         int outputWidth = 0;
509         int outputHeight = 0;
510 
511         //This test is only for the short media file
512         try {
513             BitmapFactory mBitmapFactory = new BitmapFactory();
514 
515             Bitmap outThumbnail;
516             try (MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever()) {
517                 try {
518                     mediaMetadataRetriever.setDataSource(filePath);
519                 } catch (Exception e) {
520                     e.printStackTrace();
521                     return false;
522                 }
523                 outThumbnail = mediaMetadataRetriever.getFrameAtTime(-1);
524             }
525 
526             //Verify the thumbnail
527             Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
528             outputWidth = outThumbnail.getWidth();
529             outputHeight = outThumbnail.getHeight();
530             goldenHeight = goldenBitmap.getHeight();
531             goldenWidth = goldenBitmap.getWidth();
532 
533             //check the image dimension
534             if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight))
535                 return false;
536 
537             // Check half line of pixel
538             int x = goldenHeight / 2;
539             for (int j = 1; j < goldenWidth / 2; j++) {
540                 if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)) {
541                     Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j));
542                     return false;
543                 }
544            }
545         } catch (Exception e) {
546             Log.v(TAG, e.toString());
547             return false;
548         }
549         return true;
550     }
551 
552     //Load midi file from resources
resourcesPlayback(AssetFileDescriptor afd, int expectedDuration)553     public static boolean resourcesPlayback(AssetFileDescriptor afd, int expectedDuration) {
554         int duration = 0;
555         try {
556             MediaPlayer mp = new MediaPlayer();
557             mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
558             mp.prepare();
559             mp.start();
560             duration = mp.getDuration();
561             Thread.sleep(5000);
562             mp.release();
563         } catch (Exception e) {
564             Log.v(TAG,e.getMessage());
565         }
566         if (duration > expectedDuration)
567             return true;
568         else
569             return false;
570     }
571 
prepareAsyncReset(String filePath)572     public static boolean prepareAsyncReset(String filePath) {
573         //preparesAsync
574         try {
575             MediaPlayer mp = new MediaPlayer();
576             mp.setDataSource(filePath);
577             mp.prepareAsync();
578             mp.reset();
579             mp.release();
580         } catch (Exception e) {
581             Log.v(TAG,e.getMessage());
582             return false;
583         }
584         return true;
585     }
586 
587 
isLooping(String filePath)588     public static boolean isLooping(String filePath) {
589         MediaPlayer mp = null;
590 
591         try {
592             mp = new MediaPlayer();
593             if (mp.isLooping()) {
594                 Log.v(TAG, "MediaPlayer.isLooping() returned true after ctor");
595                 return false;
596             }
597             mp.setDataSource(filePath);
598             mp.prepare();
599 
600             mp.setLooping(true);
601             if (!mp.isLooping()) {
602                 Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
603                 return false;
604             }
605 
606             mp.setLooping(false);
607             if (mp.isLooping()) {
608                 Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
609                 return false;
610             }
611         } catch (Exception e) {
612             Log.v(TAG, "Exception : " + e.toString());
613             return false;
614         } finally {
615             if (mp != null)
616                 mp.release();
617         }
618 
619         return true;
620     }
621 
isLoopingAfterReset(String filePath)622     public static boolean isLoopingAfterReset(String filePath) {
623         MediaPlayer mp = null;
624         try {
625             mp = new MediaPlayer();
626             mp.setDataSource(filePath);
627             mp.prepare();
628 
629             mp.setLooping(true);
630             mp.reset();
631             if (mp.isLooping()) {
632                 Log.v(TAG, "MediaPlayer.isLooping() returned true after reset()");
633                 return false;
634             }
635         } catch (Exception e){
636             Log.v(TAG, "Exception : " + e.toString());
637             return false;
638         } finally {
639             if (mp != null)
640                 mp.release();
641         }
642 
643         return true;
644     }
645 
646     /*
647      * Initializes the message looper so that the mediaPlayer object can
648      * receive the callback messages.
649      */
initializeMessageLooper()650     private static void initializeMessageLooper() {
651         Log.v(TAG, "start looper");
652         new Thread() {
653             @Override
654             public void run() {
655                 // Set up a looper to be used by camera.
656                 Looper.prepare();
657                 Log.v(TAG, "start loopRun");
658                 // Save the looper so that we can terminate this thread
659                 // after we are done with it.
660                 mLooper = Looper.myLooper();
661                 mMediaPlayer = new MediaPlayer();
662                 synchronized (mLock) {
663                     mInitialized = true;
664                     mLock.notify();
665                 }
666                 Looper.loop();  // Blocks forever until Looper.quit() is called.
667                 Log.v(TAG, "initializeMessageLooper: quit.");
668             }
669         }.start();
670     }
671 
672     /*
673      * Terminates the message looper thread.
674      */
terminateMessageLooper()675     private static void terminateMessageLooper() {
676         if (mLooper != null) {
677             mLooper.quit();
678         }
679         if (mMediaPlayer != null) {
680             mMediaPlayer.release();
681         }
682     }
683 
684     static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
685         public void onPrepared(MediaPlayer mp) {
686             synchronized (mPrepareDone) {
687                 if(mPrepareReset) {
688                     Log.v(TAG, "call Reset");
689                     mMediaPlayer.reset();
690                 }
691                 Log.v(TAG, "notify the prepare callback");
692                 mPrepareDone.notify();
693                 mOnPrepareSuccess = true;
694             }
695         }
696     };
697 
prepareAsyncCallback(String filePath, boolean reset)698     public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception {
699         //Added the PrepareReset flag which allow us to switch to different
700         //test case.
701         if (reset) {
702             mPrepareReset = true;
703         }
704 
705         synchronized (mLock) {
706             initializeMessageLooper();
707             try {
708                 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
709             } catch(Exception e) {
710                 Log.v(TAG, "looper was interrupted.");
711                 return false;
712             }
713         }
714         try{
715             mMediaPlayer.setOnPreparedListener(mPreparedListener);
716             mMediaPlayer.setDataSource(filePath);
717             mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
718             mMediaPlayer.prepareAsync();
719             synchronized (mPrepareDone) {
720                 try {
721                     mPrepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
722                 } catch (Exception e) {
723                     Log.v(TAG, "wait was interrupted.");
724                 }
725             }
726             terminateMessageLooper();
727         }catch (Exception e) {
728             Log.v(TAG,e.getMessage());
729         }
730        return mOnPrepareSuccess;
731     }
732 
733     static MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
734         public void onCompletion(MediaPlayer mp) {
735                 Log.v(TAG, "notify the completion callback");
736                 mOnCompleteSuccess = true;
737                 mCompletionLatch.countDown();
738         }
739     };
740 
741     static MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
742         public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
743             Log.v(TAG, "playback error");
744             mPlaybackError = true;
745             mp.reset();
746             mOnCompleteSuccess = false;
747             mCompletionLatch.countDown();
748             return true;
749         }
750     };
751 
752     static MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
753         public boolean onInfo(MediaPlayer mp, int what, int extra) {
754             switch (what) {
755                 case MediaPlayer.MEDIA_INFO_UNKNOWN:
756                     mMediaInfoUnknownCount++;
757                     break;
758                 case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
759                     mMediaInfoVideoTrackLaggingCount++;
760                     break;
761                 case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
762                     mMediaInfoBadInterleavingCount++;
763                     break;
764                 case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
765                     mMediaInfoNotSeekableCount++;
766                     break;
767                 case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
768                     mMediaInfoMetdataUpdateCount++;
769                     break;
770                 case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
771                     mFirstFrameLatch.countDown();
772                     break;
773             }
774             return true;
775         }
776     };
777 
setupPlaybackMarkers()778     private static void setupPlaybackMarkers() {
779         // we only ever worry about these firing 1 time
780         mFirstFrameLatch = new CountDownLatch(1);
781         mCompletionLatch = new CountDownLatch(1);
782 
783         mOnCompleteSuccess = false;
784         mPlaybackError = false;
785 
786         mMediaInfoUnknownCount = 0;
787         mMediaInfoVideoTrackLaggingCount = 0;
788         mMediaInfoBadInterleavingCount = 0;
789         mMediaInfoNotSeekableCount = 0;
790         mMediaInfoMetdataUpdateCount = 0;
791     }
792 
793     // null == success, !null == reason why it failed
playMediaSample(String fileName)794     public static String playMediaSample(String fileName) throws Exception {
795         int duration = 0;
796         int curPosition = 0;
797         int nextPosition = 0;
798 
799         setupPlaybackMarkers();
800 
801         initializeMessageLooper();
802         synchronized (mLock) {
803             try {
804                 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
805             } catch(Exception e) {
806                 Log.v(TAG, "looper was interrupted.");
807                 return "Looper was interrupted";
808             }
809         }
810         try {
811             mMediaPlayer.setOnCompletionListener(mCompletionListener);
812             mMediaPlayer.setOnErrorListener(mOnErrorListener);
813             mMediaPlayer.setOnInfoListener(mInfoListener);
814             Log.v(TAG, "playMediaSample: sample file name " + fileName);
815             mMediaPlayer.setDataSource(fileName);
816             mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
817             mMediaPlayer.prepare();
818             duration = mMediaPlayer.getDuration();
819             Log.v(TAG, "duration of media " + duration);
820 
821             // start to play
822             long time_started = SystemClock.uptimeMillis();
823             long time_firstFrame = time_started - 1;
824             long time_completed = time_started - 1;
825             mMediaPlayer.start();
826 
827             boolean happyStart = mFirstFrameLatch.await(SETUP_SETTLE_TIME_MS,
828                             TimeUnit.MILLISECONDS);
829             time_firstFrame = SystemClock.uptimeMillis();
830             if (happyStart == false) {
831                 String msg = "playMediaSamples playback did not start within "
832                                 + SETUP_SETTLE_TIME_MS + " ms";
833                 Log.i(TAG, msg);
834                 return msg;
835             }
836 
837             // now that we know playback has started, calculate when it should
838             // finish and wait that long that. Account for what has already
839             // played (should be very close to 0 as we get here shortly after playback
840             // starts)
841             int startingPosition = mMediaPlayer.getCurrentPosition();
842             int remainingDuration = duration - startingPosition;
843 
844             boolean happyFinish = mCompletionLatch.await(remainingDuration + PLAYBACK_SETTLE_TIME_MS,
845                             TimeUnit.MILLISECONDS);
846             time_completed = SystemClock.uptimeMillis();
847 
848             // really helps diagnose the class of failures we've seen.
849             if (true) {
850                 Log.i(TAG, "duration of video sample:             " + duration + " ms");
851                 Log.i(TAG, "full start+playback+completionsignal: "
852                                 + (time_completed - time_started) + " ms");
853                 Log.i(TAG, "total overhead:                       "
854                                 + (time_completed - time_started - duration) + " ms");
855                 Log.i(TAG, "time until 1st frame rendered:        "
856                                 + (time_firstFrame - time_started) + " ms");
857                 Log.i(TAG, "video position when started timer:    " + startingPosition + " ms");
858                 long preOverhead = (time_firstFrame - time_started) - (startingPosition);
859                 Log.i(TAG, "start() startup overhead:             " + preOverhead + " ms");
860                 long postOverhead = (time_completed - time_started) - duration - preOverhead;
861                 Log.i(TAG, "trailing costs overhead:              " + postOverhead + " ms");
862             }
863 
864             // did we succeed?
865             if (happyFinish == false) {
866                 // the test failed
867 
868                 // wait a little more, to help who is trying to figure out why it's bad.
869                 boolean happyExtra = mCompletionLatch.await(10000, TimeUnit.MILLISECONDS);
870                 long time_extension = SystemClock.uptimeMillis();
871 
872                 String extraTime = "";
873                 if (happyExtra) {
874                     extraTime = " BUT complete after an additional "
875                                     + (time_extension - time_completed) + " ms";
876                 } else {
877                     extraTime = " AND still not complete after an additional "
878                                     + (time_extension - time_completed) + " ms";
879                 }
880 
881                 // it's still a failure, even if we did finish in extra time
882                 Log.e(TAG, "wait timed-out without onCompletion notification" + extraTime);
883                 return "wait timed-out without onCompletion notification" + extraTime;
884             }
885         } catch (Exception e) {
886             Log.v(TAG, "playMediaSample Exception:" + e.getMessage());
887         } finally {
888             // we need to clean up, even if we tripped an early return above
889             terminateMessageLooper();
890         }
891         return mOnCompleteSuccess ? null : "unknown failure reason";
892     }
893 }
894