Add CTS for closed captions

Bug: 26971555
Change-Id: I0eb75445884c4ebd9c41ce5e8f194299f912243e
diff --git a/tests/tests/media/res/raw/testvideo_with_2_subtitle_tracks.mp4 b/tests/tests/media/res/raw/testvideo_with_2_subtitle_tracks.mp4
new file mode 100755
index 0000000..b8dce17
--- /dev/null
+++ b/tests/tests/media/res/raw/testvideo_with_2_subtitle_tracks.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/testvideo_with_2_subtitles.3gp b/tests/tests/media/res/raw/testvideo_with_2_timedtext_tracks.3gp
similarity index 100%
rename from tests/tests/media/res/raw/testvideo_with_2_subtitles.3gp
rename to tests/tests/media/res/raw/testvideo_with_2_timedtext_tracks.3gp
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index bcc1e8d..1d0ab26 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -33,11 +33,11 @@
 import android.media.MediaRecorder;
 import android.media.MediaTimestamp;
 import android.media.PlaybackParams;
+import android.media.SubtitleData;
 import android.media.SyncParams;
 import android.media.TimedText;
 import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Visualizer;
-import android.media.cts.MediaPlayerTestBase.Monitor;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.IBinder;
@@ -74,9 +74,13 @@
     private static final long RECORDED_DURATION_MS  = 3000;
     private static final float FLOAT_TOLERANCE = .0001f;
 
-    private Vector<Integer> mTimedTextTrackIndex = new Vector<Integer>();
+    private final Vector<Integer> mTimedTextTrackIndex = new Vector<>();
+    private final Monitor mOnTimedTextCalled = new Monitor();
     private int mSelectedTimedTextIndex;
-    private Monitor mOnTimedTextCalled = new Monitor();
+
+    private final Vector<Integer> mSubtitleTrackIndex = new Vector<>();
+    private final Monitor mOnSubtitleDataCalled = new Monitor();
+    private int mSelectedSubtitleIndex;
 
     private File mOutFile;
 
@@ -919,7 +923,7 @@
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setDataSource(file);
         String rotation = retriever.extractMetadata(
-                    MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
+                MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
         retriever.release();
         retriever = null;
         assertNotNull(rotation);
@@ -1206,6 +1210,194 @@
                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_22050hz, 176, 144);
     }
 
+    private void readSubtitleTracks() throws Exception {
+        mSubtitleTrackIndex.clear();
+        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
+        if (trackInfos == null || trackInfos.length == 0) {
+            return;
+        }
+
+        Vector<Integer> subtitleTrackIndex = new Vector<>();
+        for (int i = 0; i < trackInfos.length; ++i) {
+            assertTrue(trackInfos[i] != null);
+            if (trackInfos[i].getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+                subtitleTrackIndex.add(i);
+            }
+        }
+
+        mSubtitleTrackIndex.addAll(subtitleTrackIndex);
+    }
+
+    private void selectSubtitleTrack(int index) throws Exception {
+        int trackIndex = mSubtitleTrackIndex.get(index);
+        mMediaPlayer.selectTrack(trackIndex);
+        mSelectedSubtitleIndex = index;
+    }
+
+    private void deselectSubtitleTrack(int index) throws Exception {
+        int trackIndex = mSubtitleTrackIndex.get(index);
+        mMediaPlayer.deselectTrack(trackIndex);
+        if (mSelectedSubtitleIndex == index) {
+            mSelectedSubtitleIndex = -1;
+        }
+    }
+
+    public void testDeselectTrackForSubtitleTracks() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        getInstrumentation().waitForIdleSync();
+
+        mMediaPlayer.setOnSubtitleDataListener(new MediaPlayer.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+        mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mp, int what, int extra) {
+                if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+                return false;
+            }
+        });
+
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mMediaPlayer.prepare();
+        mMediaPlayer.start();
+        assertTrue(mMediaPlayer.isPlaying());
+
+        // Closed caption tracks are in-band.
+        // So, those tracks will be found after processing a number of frames.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+
+        // Run twice to check if repeated selection-deselection on the same track works well.
+        for (int i = 0; i < 2; i++) {
+            // Waits until at least one subtitle is fired. Timeout is 1.5 sec.
+            selectSubtitleTrack(i);
+            mOnSubtitleDataCalled.reset();
+            assertTrue(mOnSubtitleDataCalled.waitForSignal(1500));
+
+            // Try deselecting track.
+            deselectSubtitleTrack(i);
+            mOnSubtitleDataCalled.reset();
+            assertFalse(mOnSubtitleDataCalled.waitForSignal(1500));
+        }
+
+        try {
+            deselectSubtitleTrack(0);
+            fail("Deselecting unselected track: expected RuntimeException, " +
+                 "but no exception has been triggered.");
+        } catch (RuntimeException e) {
+            // expected
+        }
+
+        mMediaPlayer.stop();
+    }
+
+    public void testChangeSubtitleTrack() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        mMediaPlayer.setOnSubtitleDataListener(new MediaPlayer.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+        mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mp, int what, int extra) {
+                if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+                return false;
+            }
+        });
+
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mMediaPlayer.prepare();
+        mMediaPlayer.start();
+        assertTrue(mMediaPlayer.isPlaying());
+
+        // Closed caption tracks are in-band.
+        // So, those tracks will be found after processing a number of frames.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+
+        // Waits until at least two captions are fired. Timeout is 2.5 sec.
+        selectSubtitleTrack(0);
+        assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
+
+        mOnSubtitleDataCalled.reset();
+        selectSubtitleTrack(1);
+        assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
+
+        mMediaPlayer.stop();
+    }
+
+    public void testGetTrackInfoForVideoWithSubtitleTracks() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        getInstrumentation().waitForIdleSync();
+
+        mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mp, int what, int extra) {
+                if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+                return false;
+            }
+        });
+
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mMediaPlayer.prepare();
+        mMediaPlayer.start();
+        assertTrue(mMediaPlayer.isPlaying());
+
+        // The media metadata will be changed while playing since closed caption tracks are in-band
+        // and those tracks will be found after processing a number of frames. These tracks will be
+        // found within one second.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+        assertEquals(2, mSubtitleTrackIndex.size());
+
+        mMediaPlayer.stop();
+    }
+
     private void readTimedTextTracks() throws Exception {
         mTimedTextTrackIndex.clear();
         MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
@@ -1234,13 +1426,13 @@
         return mTimedTextTrackIndex.size();
     }
 
-    private void selectSubtitleTrack(int index) throws Exception {
+    private void selectTimedTextTrack(int index) throws Exception {
         int trackIndex = mTimedTextTrackIndex.get(index);
         mMediaPlayer.selectTrack(trackIndex);
         mSelectedTimedTextIndex = index;
     }
 
-    private void deselectSubtitleTrack(int index) throws Exception {
+    private void deselectTimedTextTrack(int index) throws Exception {
         int trackIndex = mTimedTextTrackIndex.get(index);
         mMediaPlayer.deselectTrack(trackIndex);
         if (mSelectedTimedTextIndex == index) {
@@ -1248,8 +1440,8 @@
         }
     }
 
-    public void testDeselectTrack() throws Throwable {
-        if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+    public void testDeselectTrackForTimedTextTrack() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_timedtext_tracks)) {
             return; // skip;
         }
         runTestOnUiThread(new Runnable() {
@@ -1287,31 +1479,31 @@
 
         // Run twice to check if repeated selection-deselection on the same track works well.
         for (int i = 0; i < 2; i++) {
-            // Waits until at least one subtitle is fired. Timeout is 1 sec.
-            selectSubtitleTrack(0);
+            // Waits until at least one subtitle is fired. Timeout is 1.5 sec.
+            selectTimedTextTrack(0);
             mOnTimedTextCalled.reset();
             assertTrue(mOnTimedTextCalled.waitForSignal(1500));
 
             // Try deselecting track.
-            deselectSubtitleTrack(0);
+            deselectTimedTextTrack(0);
             mOnTimedTextCalled.reset();
             assertFalse(mOnTimedTextCalled.waitForSignal(1500));
         }
 
         // Run the same test for external subtitle track.
         for (int i = 0; i < 2; i++) {
-            selectSubtitleTrack(2);
+            selectTimedTextTrack(2);
             mOnTimedTextCalled.reset();
             assertTrue(mOnTimedTextCalled.waitForSignal(1500));
 
             // Try deselecting track.
-            deselectSubtitleTrack(2);
+            deselectTimedTextTrack(2);
             mOnTimedTextCalled.reset();
             assertFalse(mOnTimedTextCalled.waitForSignal(1500));
         }
 
         try {
-            deselectSubtitleTrack(0);
+            deselectTimedTextTrack(0);
             fail("Deselecting unselected track: expected RuntimeException, " +
                  "but no exception has been triggered.");
         } catch (RuntimeException e) {
@@ -1321,8 +1513,8 @@
         mMediaPlayer.stop();
     }
 
-    public void testChangeSubtitleTrack() throws Throwable {
-        if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+    public void testChangeTimedTextTrack() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_timedtext_tracks)) {
             return; // skip;
         }
 
@@ -1394,26 +1586,26 @@
         getInstrumentation().waitForIdleSync();
         assertEquals(getTimedTextTrackCount(), 4);
 
-        selectSubtitleTrack(0);
+        selectTimedTextTrack(0);
         mOnTimedTextCalled.reset();
 
         mMediaPlayer.start();
         assertTrue(mMediaPlayer.isPlaying());
 
-        // Waits until at least two subtitles are fired. Timeout is 2 sec.
+        // Waits until at least two subtitles are fired. Timeout is 2.5 sec.
         // Please refer the test srt files:
         // test_subtitle1_srt.3gp and test_subtitle2_srt.3gp
         assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
-        selectSubtitleTrack(1);
+        selectTimedTextTrack(1);
         mOnTimedTextCalled.reset();
         assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
-        selectSubtitleTrack(2);
+        selectTimedTextTrack(2);
         mOnTimedTextCalled.reset();
         assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
-        selectSubtitleTrack(3);
+        selectTimedTextTrack(3);
         mOnTimedTextCalled.reset();
         assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
         mMediaPlayer.stop();
@@ -1421,8 +1613,8 @@
         assertEquals("Wrong bounds count", 2, mBoundsCount);
     }
 
-    public void testGetTrackInfo() throws Throwable {
-        if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+    public void testGetTrackInfoForVideoWithTimedText() throws Throwable {
+        if (!checkLoadResource(R.raw.testvideo_with_2_timedtext_tracks)) {
             return; // skip;
         }
         runTestOnUiThread(new Runnable() {
@@ -1440,7 +1632,7 @@
         mMediaPlayer.start();
 
         readTimedTextTracks();
-        selectSubtitleTrack(2);
+        selectTimedTextTrack(2);
 
         int count = 0;
         MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();