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