Add Media Player Streaming Tests

Change-Id: I4bb78b0487d158f4ea57349b591f66eda6b325d2
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 38d7e3e..86c23c7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -25,6 +25,9 @@
 public class MediaNames {
     // A directory to hold all kinds of media files
     public static final String MEDIA_SAMPLE_POOL = "/sdcard/media_api/samples/";
+    // A file to hold all streaming URLs
+    public static final String MEDIA_STREAMING_SRC = "/sdcard/media_api/streaming.txt";
+
     // Audio files
     public static final String MP3CBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3";
     public static final String MP3VBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index e84f762..66ed933 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -42,13 +42,13 @@
 import java.util.Random;
 /**
  * Junit / Instrumentation test case for the media player api
- 
- */  
-public class CodecTest {    
+
+ */
+public class CodecTest {
     private static String TAG = "CodecTest";
     private static MediaPlayer mMediaPlayer;
     private MediaPlayer.OnPreparedListener mOnPreparedListener;
-    
+
     private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
     private static boolean mInitialized = false;
     private static boolean mPrepareReset = false;
@@ -66,18 +66,18 @@
     public static int mMediaInfoNotSeekableCount = 0;
     public static int mMediaInfoMetdataUpdateCount = 0;
 
-    public static String printCpuInfo(){      
+    public static String printCpuInfo(){
         String cm = "dumpsys cpuinfo";
         String cpuinfo =null;
         int ch;
         try{
             Process  p = Runtime.getRuntime().exec(cm);
-            InputStream in = p.getInputStream();        
+            InputStream in = p.getInputStream();
             StringBuffer sb = new StringBuffer(512);
-            while ( ( ch = in.read() ) != -1 ){  
-                sb.append((char) ch); 
+            while ( ( ch = in.read() ) != -1 ){
+                sb.append((char) ch);
             }
-            cpuinfo = sb.toString();      
+            cpuinfo = sb.toString();
         }catch (IOException e){
             Log.v(TAG, e.toString());
         }
@@ -90,14 +90,14 @@
         MediaPlayer mp = new MediaPlayer();
         try{
             mp.setDataSource(filePath);
-            mp.prepare(); 
+            mp.prepare();
         }catch (Exception e){
             Log.v(TAG, e.toString());
         }
         int duration = mp.getDuration();
         Log.v(TAG, "Duration " + duration);
         mp.release();
-        Log.v(TAG, "release");      
+        Log.v(TAG, "release");
         return duration;
     }
 
@@ -122,7 +122,7 @@
         }
         currentPosition = mp.getCurrentPosition();
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
         //The currentposition should be within 10% of the sleep time
         //For the very short mp3, it should return the length instead of 10 seconds
@@ -130,11 +130,11 @@
             if (currentPosition < 1000 )
                 return true;
         }
-        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0)) 
+        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0))
             return true;
         else
             return false;
-    }  
+    }
 
     public static boolean seekTo(String filePath){
         Log.v(TAG, "seekTo " + filePath);
@@ -149,12 +149,12 @@
             currentPosition = mp.getCurrentPosition();
         }catch (Exception e){
             Log.v(TAG, e.getMessage());
-        }      
+        }
         mp.stop();
         mp.release();
         Log.v(TAG, "CurrentPosition = " + currentPosition);
         //The currentposition should be at least greater than the 80% of seek time
-        if ((currentPosition > MediaNames.SEEK_TIME *0.8)) 
+        if ((currentPosition > MediaNames.SEEK_TIME *0.8))
             return true;
         else
             return false;
@@ -170,7 +170,7 @@
         try{
             mp.setDataSource(filePath);
             mp.prepare();
-            duration = mp.getDuration(); 
+            duration = mp.getDuration();
             Log.v(TAG, "setLooping duration " + duration);
             mp.setLooping(true);
             mp.start();
@@ -180,14 +180,14 @@
             Thread.sleep(20000);
             t2=SystemClock.uptimeMillis();
             Log.v(TAG, "pause");
-            //Bug# 1106852 - IllegalStateException will be thrown if pause is called 
+            //Bug# 1106852 - IllegalStateException will be thrown if pause is called
             //in here
             //mp.pause();
             currentPosition = mp.getCurrentPosition();
             Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
         }catch (Exception e){
             Log.v(TAG, "Exception : " + e.toString());
-        }      
+        }
         mp.stop();
         mp.release();
         //The current position should be within 20% of the sleep time
@@ -196,7 +196,7 @@
             return true;
         else
             return false;
-    }  
+    }
 
     public static boolean pause(String filePath) throws Exception {
         Log.v(TAG, "pause - " + filePath);
@@ -206,7 +206,7 @@
         long t2=0;
         MediaPlayer mp = new MediaPlayer();
         mp.setDataSource(filePath);
-        mp.prepare();    
+        mp.prepare();
         int duration = mp.getDuration();
         mp.start();
         t1=SystemClock.uptimeMillis();
@@ -244,7 +244,7 @@
         mp.pause();
         mp.release();
     }
-    
+
     static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
         new MediaPlayer.OnVideoSizeChangedListener() {
             public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
@@ -258,7 +258,7 @@
     //Register the videoSizeChanged listener
     public static int videoHeight(String filePath) throws Exception {
         Log.v(TAG, "videoHeight - " + filePath);
-        int videoHeight = 0;    
+        int videoHeight = 0;
         synchronized (lock) {
             initializeMessageLooper();
             try {
@@ -286,7 +286,7 @@
         } catch (Exception e) {
             Log.e(TAG, e.getMessage());
         }
-        
+
         return videoHeight;
     }
 
@@ -321,12 +321,12 @@
             terminateMessageLooper();
         } catch (Exception e) {
             Log.e(TAG, e.getMessage());
-        }        
+        }
         return videoWidth;
     }
 
     //This also test the streaming video which may take a long
-    //time to start the playback. 
+    //time to start the playback.
     public static boolean videoSeekTo(String filePath) throws Exception {
         Log.v(TAG, "videoSeekTo - " + filePath);
         int currentPosition = 0;
@@ -392,12 +392,12 @@
         currentPosition = mp.getCurrentPosition();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "duration = " + duration);
         if (currentPosition < 0.9 * duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean shortMediaStop(String filePath){
@@ -419,12 +419,12 @@
         currentPosition = mp.getCurrentPosition();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "duration = " + duration);
         if (currentPosition > duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean playToEnd(String filePath){
@@ -449,13 +449,13 @@
         //updateDuration = mp.getDuration();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         //Log.v(TAG, "duration = " + duration);
         //Log.v(TAG, "Update duration = " + updateDuration);
         if (currentPosition > duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean seektoBeforeStart(String filePath){
@@ -478,7 +478,7 @@
         if (currentPosition < duration/2)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean mediaRecorderRecord(String filePath){
@@ -499,7 +499,7 @@
             mRecorder.release();
         }catch (Exception e){
             Log.v(TAG, e.toString());
-        }  
+        }
 
         //Verify the recorded file
         MediaPlayer mp = new MediaPlayer();
@@ -540,7 +540,7 @@
             }
             Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1);
 
-            //Verify the thumbnail 
+            //Verify the thumbnail
             Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
             outputWidth = outThumbnail.getWidth();
             outputHeight = outThumbnail.getHeight();
@@ -586,8 +586,8 @@
             return false;
     }
 
-    public static boolean prepareAsyncReset(String filePath){    
-        //preparesAsync 
+    public static boolean prepareAsyncReset(String filePath){
+        //preparesAsync
         try{
             MediaPlayer mp = new MediaPlayer();
             mp.setDataSource(filePath);
@@ -602,9 +602,9 @@
     }
 
 
-    public static boolean isLooping(String filePath) {        
+    public static boolean isLooping(String filePath) {
         MediaPlayer mp = null;
-        
+
         try {
             mp = new MediaPlayer();
             if (mp.isLooping()) {
@@ -619,7 +619,7 @@
                 Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
                 return false;
             }
-            
+
             mp.setLooping(false);
             if (mp.isLooping()) {
                 Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
@@ -659,9 +659,9 @@
 
         return true;
     }
-    
+
     /*
-     * Initializes the message looper so that the mediaPlayer object can 
+     * Initializes the message looper so that the mediaPlayer object can
      * receive the callback messages.
      */
     private static void initializeMessageLooper() {
@@ -672,10 +672,10 @@
                 // Set up a looper to be used by camera.
                 Looper.prepare();
                 Log.v(TAG, "start loopRun");
-                // Save the looper so that we can terminate this thread 
+                // Save the looper so that we can terminate this thread
                 // after we are done with it.
-                mLooper = Looper.myLooper();                
-                mMediaPlayer = new MediaPlayer();                                
+                mLooper = Looper.myLooper();
+                mMediaPlayer = new MediaPlayer();
                 synchronized (lock) {
                     mInitialized = true;
                     lock.notify();
@@ -685,7 +685,7 @@
             }
         }.start();
     }
-    
+
     /*
      * Terminates the message looper thread.
      */
@@ -693,7 +693,7 @@
         mLooper.quit();
         mMediaPlayer.release();
     }
-    
+
     static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
         public void onPrepared(MediaPlayer mp) {
             synchronized (prepareDone) {
@@ -707,14 +707,14 @@
             }
         }
     };
-   
+
     public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception {
         //Added the PrepareReset flag which allow us to switch to different
         //test case.
         if (reset){
             mPrepareReset = true;
         }
-        
+
         synchronized (lock) {
             initializeMessageLooper();
             try {
@@ -728,18 +728,18 @@
             mMediaPlayer.setOnPreparedListener(mPreparedListener);
             mMediaPlayer.setDataSource(filePath);
             mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
-            mMediaPlayer.prepareAsync(); 
+            mMediaPlayer.prepareAsync();
             synchronized (prepareDone) {
                 try {
                     prepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                 } catch (Exception e) {
                     Log.v(TAG, "wait was interrupted.");
                 }
-            }         
+            }
             terminateMessageLooper();
         }catch (Exception e){
             Log.v(TAG,e.getMessage());
-        }      
+        }
        return onPrepareSuccess;
     }
 
@@ -784,8 +784,12 @@
         }
     };
 
-    // For each media file, forward twice and backward once, then play to the end
     public static boolean playMediaSamples(String filePath) throws Exception {
+        return playMediaSamples(filePath, 2000);
+    }
+
+    // For each media file, forward twice and backward once, then play to the end
+    public static boolean playMediaSamples(String filePath, int buffertime) throws Exception {
         int duration = 0;
         int curPosition = 0;
         int nextPosition = 0;
@@ -822,14 +826,14 @@
             waittime = duration - mMediaPlayer.getCurrentPosition();
             synchronized(onCompletion){
                 try {
-                    onCompletion.wait(waittime + 2000);
+                    onCompletion.wait(waittime + buffertime);
                 }catch (Exception e) {
                     Log.v(TAG, "playMediaSamples are interrupted");
                     return false;
                 }
             }
             terminateMessageLooper();
-        }catch (Exception e) {
+        } catch (Exception e) {
             Log.v(TAG, "playMediaSamples:" + e.getMessage());
         }
         return onCompleteSuccess;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java
new file mode 100644
index 0000000..d92c857
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.stress;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaPlayerStressTestRunner;
+
+import android.os.Bundle;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaNames;
+import com.android.mediaframeworktest.functional.CodecTest;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Junit / Instrumentation test case for the media player
+ */
+public class MediaPlayerStreamingStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private String TAG = "MediaPlayerStreamingStressTest";
+    private String mStreamingSrc;
+
+    public MediaPlayerStreamingStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        //Insert a 2 second before launching the test activity. This is
+        //the workaround for the race condition of requesting the updated surface.
+        Thread.sleep(2000);
+        getActivity();
+        MediaPlayerStressTestRunner mRunner = (MediaPlayerStressTestRunner)getInstrumentation();
+        Bundle arguments = mRunner.getArguments();
+        mStreamingSrc = arguments.getString("streaming-source");
+        if (mStreamingSrc == null) {
+            mStreamingSrc = MediaNames.MEDIA_STREAMING_SRC;
+        }
+        super.setUp();
+    }
+
+    private int mTotalPlaybackError = 0;
+    private int mTotalComplete = 0;
+    private int mTotalInfoUnknown = 0;
+    private int mTotalVideoTrackLagging = 0;
+    private int mTotalBadInterleaving = 0;
+    private int mTotalNotSeekable = 0;
+    private int mTotalMetaDataUpdate = 0;
+
+    //Test result output file
+    private static final String PLAYBACK_RESULT = "StreamingTestResult.txt";
+
+    private void writeTestOutput(String filename, Writer output) throws Exception{
+        output.write("URL: " + filename);
+        output.write(" Complete: " + CodecTest.onCompleteSuccess);
+        output.write(" Error: " + CodecTest.mPlaybackError);
+        output.write(" Unknown Info: " + CodecTest.mMediaInfoUnknownCount);
+        output.write(" Track Lagging: " +  CodecTest.mMediaInfoVideoTrackLaggingCount);
+        output.write(" Bad Interleaving: " + CodecTest.mMediaInfoBadInterleavingCount);
+        output.write(" Not Seekable: " + CodecTest.mMediaInfoNotSeekableCount);
+        output.write(" Info Meta data update: " + CodecTest.mMediaInfoMetdataUpdateCount);
+        output.write("\n");
+    }
+
+    private void writeTestSummary(Writer output) throws Exception{
+        output.write("Total Result:\n");
+        output.write("Total Complete: " + mTotalComplete + "\n");
+        output.write("Total Error: " + mTotalPlaybackError + "\n");
+        output.write("Total Unknown Info: " + mTotalInfoUnknown + "\n");
+        output.write("Total Track Lagging: " + mTotalVideoTrackLagging + "\n" );
+        output.write("Total Bad Interleaving: " + mTotalBadInterleaving + "\n");
+        output.write("Total Not Seekable: " + mTotalNotSeekable + "\n");
+        output.write("Total Info Meta data update: " + mTotalMetaDataUpdate + "\n");
+        output.write("\n");
+    }
+
+    private void updateTestResult(){
+        if (CodecTest.onCompleteSuccess){
+            mTotalComplete++;
+        }
+        else if (CodecTest.mPlaybackError){
+            mTotalPlaybackError++;
+        }
+        mTotalInfoUnknown += CodecTest.mMediaInfoUnknownCount;
+        mTotalVideoTrackLagging += CodecTest.mMediaInfoVideoTrackLaggingCount;
+        mTotalBadInterleaving += CodecTest.mMediaInfoBadInterleavingCount;
+        mTotalNotSeekable += CodecTest.mMediaInfoNotSeekableCount;
+        mTotalMetaDataUpdate += CodecTest.mMediaInfoMetdataUpdateCount;
+    }
+
+    //Test that will start the playback for all the videos
+    //under the samples folder
+    @LargeTest
+    public void testVideoPlayback() throws Exception {
+        String fileWithError = "Filename:\n";
+        File playbackOutput = new File(Environment.getExternalStorageDirectory(), PLAYBACK_RESULT);
+        Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
+
+        boolean testResult = true;
+        // load directory files
+        boolean onCompleteSuccess = false;
+
+
+        Log.i(TAG, "Streaming src file: " + mStreamingSrc);
+        //TODO: add try catch
+
+        File f = new File(mStreamingSrc);
+        BufferedReader br = new BufferedReader(new FileReader(f));
+        List<String> urls = new ArrayList<String>();
+        String line;
+        while ((line = br.readLine()) != null) {
+           urls.add(line.trim());
+        }
+        br.close();
+        if (urls == null) {
+            Log.v("MediaPlayerStreamingTest:testVideoPlayback", "no url found");
+            return;
+        } else {
+            for (int i = 0; i < urls.size(); i++) {
+                //Get url
+                String filename = urls.get(i);
+                onCompleteSuccess =
+                    CodecTest.playMediaSamples(filename, 60000);
+                if (!onCompleteSuccess){
+                    //Don't fail the test right away, print out the failure file.
+                    fileWithError += filename + '\n';
+                    Log.v(TAG, "Failure File : " + fileWithError);
+                    testResult = false;
+                }
+                Thread.sleep(3000);
+                //Write test result to an output file
+                writeTestOutput(filename,output);
+                //Get the summary
+                updateTestResult();
+            }
+            writeTestSummary(output);
+            output.close();
+            assertTrue("testMediaSamples", testResult);
+       }
+    }
+}