Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright 2018 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 package android.media.cts;
     17 
     18 import android.media.cts.R;
     19 
     20 import android.content.Context;
     21 import android.content.pm.PackageManager;
     22 import android.content.res.AssetFileDescriptor;
     23 import android.graphics.Rect;
     24 import android.hardware.Camera;
     25 import android.media.AudioAttributes;
     26 import android.media.AudioManager;
     27 import android.media.DataSourceDesc;
     28 import android.media.MediaCodec;
     29 import android.media.Media2DataSource;
     30 import android.media.MediaExtractor;
     31 import android.media.MediaFormat;
     32 import android.media.MediaMetadataRetriever;
     33 import android.media.MediaPlayer2;
     34 import android.media.MediaRecorder;
     35 import android.media.MediaTimestamp;
     36 import android.media.PlaybackParams;
     37 import android.media.SubtitleData;
     38 import android.media.SyncParams;
     39 import android.media.TimedText;
     40 import android.media.audiofx.AudioEffect;
     41 import android.media.audiofx.Visualizer;
     42 import android.media.cts.TestUtils.Monitor;
     43 import android.net.Uri;
     44 import android.os.Bundle;
     45 import android.os.Environment;
     46 import android.os.IBinder;
     47 import android.os.PowerManager;
     48 import android.os.ServiceManager;
     49 import android.os.SystemClock;
     50 import android.platform.test.annotations.AppModeFull;
     51 import android.support.test.InstrumentationRegistry;
     52 import android.support.test.filters.SmallTest;
     53 import android.platform.test.annotations.RequiresDevice;
     54 import android.util.Log;
     55 
     56 import com.android.compatibility.common.util.MediaUtils;
     57 
     58 import java.io.BufferedReader;
     59 import java.io.File;
     60 import java.io.InputStream;
     61 import java.io.InputStreamReader;
     62 import java.util.ArrayList;
     63 import java.util.List;
     64 import java.util.StringTokenizer;
     65 import java.util.UUID;
     66 import java.util.Vector;
     67 import java.util.concurrent.Callable;
     68 import java.util.concurrent.CountDownLatch;
     69 import java.util.concurrent.ExecutorService;
     70 import java.util.concurrent.Executors;
     71 import java.util.concurrent.atomic.AtomicInteger;
     72 import java.util.stream.Collectors;
     73 import java.util.stream.Stream;
     74 import junit.framework.AssertionFailedError;
     75 
     76 /**
     77  * Tests for the MediaPlayer2 API and local video/audio playback.
     78  *
     79  * The files in res/raw used by testLocalVideo* are (c) copyright 2008,
     80  * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
     81  * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
     82  */
     83 @SmallTest
     84 @RequiresDevice
     85 @AppModeFull(reason = "TODO: evaluate and port to instant")
     86 public class MediaPlayer2Test extends MediaPlayer2TestBase {
     87     // TODO: remove this flag to enable tests.
     88     private static final boolean IGNORE_TESTS = true;
     89 
     90     private String RECORDED_FILE;
     91     private static final String LOG_TAG = "MediaPlayer2Test";
     92 
     93     private static final int  RECORDED_VIDEO_WIDTH  = 176;
     94     private static final int  RECORDED_VIDEO_HEIGHT = 144;
     95     private static final long RECORDED_DURATION_MS  = 3000;
     96     private static final float FLOAT_TOLERANCE = .0001f;
     97 
     98     private final Vector<Integer> mTimedTextTrackIndex = new Vector<>();
     99     private final Monitor mOnTimedTextCalled = new Monitor();
    100     private int mSelectedTimedTextIndex;
    101 
    102     private final Vector<Integer> mSubtitleTrackIndex = new Vector<>();
    103     private final Monitor mOnSubtitleDataCalled = new Monitor();
    104     private int mSelectedSubtitleIndex;
    105 
    106     private File mOutFile;
    107 
    108     private int mBoundsCount;
    109 
    110     @Override
    111     protected void setUp() throws Exception {
    112         super.setUp();
    113         RECORDED_FILE = new File(Environment.getExternalStorageDirectory(),
    114                 "mediaplayer_record.out").getAbsolutePath();
    115         mOutFile = new File(RECORDED_FILE);
    116     }
    117 
    118     @Override
    119     protected void tearDown() throws Exception {
    120         super.tearDown();
    121         if (mOutFile != null && mOutFile.exists()) {
    122             mOutFile.delete();
    123         }
    124     }
    125 
    126     // Bug 13652927
    127     public void testVorbisCrash() throws Exception {
    128         if (IGNORE_TESTS) {
    129             return;
    130         }
    131         MediaPlayer2 mp = mPlayer;
    132         MediaPlayer2 mp2 = mPlayer2;
    133         AssetFileDescriptor afd2 = mResources.openRawResourceFd(R.raw.testmp3_2);
    134         mp2.setDataSource(new DataSourceDesc.Builder()
    135                 .setDataSource(afd2.getFileDescriptor(), afd2.getStartOffset(), afd2.getLength())
    136                 .build());
    137         Monitor onPrepareCalled = new Monitor();
    138         Monitor onErrorCalled = new Monitor();
    139         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    140             @Override
    141             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    142                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    143                     onPrepareCalled.signal();
    144                 }
    145             }
    146 
    147             @Override
    148             public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    149                 onErrorCalled.signal();
    150             }
    151         };
    152         mp2.setMediaPlayer2EventCallback(mExecutor, ecb);
    153         mp2.prepare();
    154         onPrepareCalled.waitForSignal();
    155         afd2.close();
    156         mp2.clearMediaPlayer2EventCallback();
    157 
    158         mp2.loopCurrent(true);
    159         mp2.play();
    160 
    161         for (int i = 0; i < 20; i++) {
    162             try {
    163                 AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.bug13652927);
    164                 mp.setDataSource(new DataSourceDesc.Builder()
    165                         .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
    166                             afd.getLength())
    167                         .build());
    168                 mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    169                 onPrepareCalled.reset();
    170                 mp.prepare();
    171                 onErrorCalled.waitForSignal();
    172                 afd.close();
    173             } catch (Exception e) {
    174                 // expected to fail
    175                 Log.i("@@@", "failed: " + e);
    176             }
    177             Thread.sleep(500);
    178             assertTrue("media player died", mp2.isPlaying());
    179             mp.reset();
    180         }
    181     }
    182 
    183     public void testPlayNullSourcePath() throws Exception {
    184         if (IGNORE_TESTS) {
    185             return;
    186         }
    187         Monitor onSetDataSourceCalled = new Monitor();
    188         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    189             @Override
    190             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
    191                 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
    192                     assertTrue(status != MediaPlayer2.CALL_STATUS_NO_ERROR);
    193                     onSetDataSourceCalled.signal();
    194                 }
    195             }
    196         };
    197         synchronized (mEventCbLock) {
    198             mEventCallbacks.add(ecb);
    199         }
    200 
    201         onSetDataSourceCalled.reset();
    202         mPlayer.setDataSource((DataSourceDesc)null);
    203         onSetDataSourceCalled.waitForSignal();
    204     }
    205 
    206     public void testPlayAudioFromDataURI() throws Exception {
    207         if (IGNORE_TESTS) {
    208             return;
    209         }
    210         final int mp3Duration = 34909;
    211         final int tolerance = 70;
    212         final int seekDuration = 100;
    213 
    214         // This is "R.raw.testmp3_2", base64-encoded.
    215         final int resid = R.raw.testmp3_3;
    216 
    217         InputStream is = mContext.getResources().openRawResource(resid);
    218         BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    219 
    220         StringBuilder builder = new StringBuilder();
    221         builder.append("data:;base64,");
    222         builder.append(reader.readLine());
    223         Uri uri = Uri.parse(builder.toString());
    224 
    225         MediaPlayer2 mp = createMediaPlayer2(mContext, uri);
    226 
    227         Monitor onPrepareCalled = new Monitor();
    228         Monitor onPlayCalled = new Monitor();
    229         Monitor onSeekToCalled = new Monitor();
    230         Monitor onLoopCurrentCalled = new Monitor();
    231         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    232             @Override
    233             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    234                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    235                     onPrepareCalled.signal();
    236                 }
    237             }
    238 
    239             @Override
    240             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
    241                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
    242                     onPlayCalled.signal();
    243                 } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
    244                     onLoopCurrentCalled.signal();
    245                 } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
    246                     onSeekToCalled.signal();
    247                 }
    248             }
    249         };
    250         mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    251 
    252         try {
    253             AudioAttributes attributes = new AudioAttributes.Builder()
    254                     .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    255                     .build();
    256             mp.setAudioAttributes(attributes);
    257             mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    258 
    259             assertFalse(mp.isPlaying());
    260             onPlayCalled.reset();
    261             mp.play();
    262             onPlayCalled.waitForSignal();
    263             assertTrue(mp.isPlaying());
    264 
    265             assertFalse(mp.isLooping());
    266             onLoopCurrentCalled.reset();
    267             mp.loopCurrent(true);
    268             onLoopCurrentCalled.waitForSignal();
    269             assertTrue(mp.isLooping());
    270 
    271             assertEquals(mp3Duration, mp.getDuration(), tolerance);
    272             long pos = mp.getCurrentPosition();
    273             assertTrue(pos >= 0);
    274             assertTrue(pos < mp3Duration - seekDuration);
    275 
    276             onSeekToCalled.reset();
    277             mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
    278             onSeekToCalled.waitForSignal();
    279             assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
    280 
    281             // test pause and restart
    282             mp.pause();
    283             Thread.sleep(SLEEP_TIME);
    284             assertFalse(mp.isPlaying());
    285             onPlayCalled.reset();
    286             mp.play();
    287             onPlayCalled.waitForSignal();
    288             assertTrue(mp.isPlaying());
    289 
    290             // test stop and restart
    291             mp.reset();
    292             mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    293             mp.setDataSource(new DataSourceDesc.Builder()
    294                     .setDataSource(mContext, uri)
    295                     .build());
    296             onPrepareCalled.reset();
    297             mp.prepare();
    298             onPrepareCalled.waitForSignal();
    299 
    300             assertFalse(mp.isPlaying());
    301             onPlayCalled.reset();
    302             mp.play();
    303             onPlayCalled.waitForSignal();
    304             assertTrue(mp.isPlaying());
    305 
    306             // waiting to complete
    307             while(mp.isPlaying()) {
    308                 Thread.sleep(SLEEP_TIME);
    309             }
    310         } finally {
    311             mp.close();
    312         }
    313     }
    314 
    315     public void testPlayAudio() throws Exception {
    316         if (IGNORE_TESTS) {
    317             return;
    318         }
    319         final int resid = R.raw.testmp3_2;
    320         final int mp3Duration = 34909;
    321         final int tolerance = 70;
    322         final int seekDuration = 100;
    323 
    324         MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
    325 
    326         Monitor onPrepareCalled = new Monitor();
    327         Monitor onPlayCalled = new Monitor();
    328         Monitor onSeekToCalled = new Monitor();
    329         Monitor onLoopCurrentCalled = new Monitor();
    330         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    331             @Override
    332             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    333                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    334                     onPrepareCalled.signal();
    335                 }
    336             }
    337 
    338             @Override
    339             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
    340                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
    341                     onPlayCalled.signal();
    342                 } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
    343                     onLoopCurrentCalled.signal();
    344                 } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
    345                     onSeekToCalled.signal();
    346                 }
    347             }
    348         };
    349         mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    350 
    351         try {
    352             AudioAttributes attributes = new AudioAttributes.Builder()
    353                     .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    354                     .build();
    355             mp.setAudioAttributes(attributes);
    356             mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    357 
    358             assertFalse(mp.isPlaying());
    359             onPlayCalled.reset();
    360             mp.play();
    361             onPlayCalled.waitForSignal();
    362             assertTrue(mp.isPlaying());
    363 
    364             assertFalse(mp.isLooping());
    365             onLoopCurrentCalled.reset();
    366             mp.loopCurrent(true);
    367             onLoopCurrentCalled.waitForSignal();
    368             assertTrue(mp.isLooping());
    369 
    370             assertEquals(mp3Duration, mp.getDuration(), tolerance);
    371             long pos = mp.getCurrentPosition();
    372             assertTrue(pos >= 0);
    373             assertTrue(pos < mp3Duration - seekDuration);
    374 
    375             onSeekToCalled.reset();
    376             mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
    377             onSeekToCalled.waitForSignal();
    378             assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
    379 
    380             // test pause and restart
    381             mp.pause();
    382             Thread.sleep(SLEEP_TIME);
    383             assertFalse(mp.isPlaying());
    384             onPlayCalled.reset();
    385             mp.play();
    386             onPlayCalled.waitForSignal();
    387             assertTrue(mp.isPlaying());
    388 
    389             // test stop and restart
    390             mp.reset();
    391             AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
    392             mp.setDataSource(new DataSourceDesc.Builder()
    393                     .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
    394                     .build());
    395 
    396             mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    397             onPrepareCalled.reset();
    398             mp.prepare();
    399             onPrepareCalled.waitForSignal();
    400             afd.close();
    401 
    402             assertFalse(mp.isPlaying());
    403             onPlayCalled.reset();
    404             mp.play();
    405             onPlayCalled.waitForSignal();
    406             assertTrue(mp.isPlaying());
    407 
    408             // waiting to complete
    409             while(mp.isPlaying()) {
    410                 Thread.sleep(SLEEP_TIME);
    411             }
    412         } finally {
    413             mp.close();
    414         }
    415     }
    416 
    417     public void testConcurentPlayAudio() throws Exception {
    418         if (IGNORE_TESTS) {
    419             return;
    420         }
    421         final int resid = R.raw.test1m1s; // MP3 longer than 1m are usualy offloaded
    422         final int tolerance = 70;
    423 
    424         List<MediaPlayer2> mps = Stream.generate(() -> createMediaPlayer2(mContext, resid))
    425                                       .limit(5).collect(Collectors.toList());
    426 
    427         try {
    428             for (MediaPlayer2 mp : mps) {
    429                 Monitor onPlayCalled = new Monitor();
    430                 Monitor onLoopCurrentCalled = new Monitor();
    431                 MediaPlayer2.MediaPlayer2EventCallback ecb =
    432                     new MediaPlayer2.MediaPlayer2EventCallback() {
    433                         @Override
    434                         public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
    435                                 int what, int status) {
    436                             if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
    437                                 onPlayCalled.signal();
    438                             } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
    439                                 onLoopCurrentCalled.signal();
    440                             }
    441                         }
    442                     };
    443                 mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    444 
    445                 AudioAttributes attributes = new AudioAttributes.Builder()
    446                         .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    447                         .build();
    448                 mp.setAudioAttributes(attributes);
    449                 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    450 
    451                 assertFalse(mp.isPlaying());
    452                 onPlayCalled.reset();
    453                 mp.play();
    454                 onPlayCalled.waitForSignal();
    455                 assertTrue(mp.isPlaying());
    456 
    457                 assertFalse(mp.isLooping());
    458                 onLoopCurrentCalled.reset();
    459                 mp.loopCurrent(true);
    460                 onLoopCurrentCalled.waitForSignal();
    461                 assertTrue(mp.isLooping());
    462 
    463                 long pos = mp.getCurrentPosition();
    464                 assertTrue(pos >= 0);
    465 
    466                 Thread.sleep(SLEEP_TIME); // Delay each track to be able to ear them
    467             }
    468             // Check that all mp3 are playing concurrently here
    469             for (MediaPlayer2 mp : mps) {
    470                 long pos = mp.getCurrentPosition();
    471                 Thread.sleep(SLEEP_TIME);
    472                 assertEquals(pos + SLEEP_TIME, mp.getCurrentPosition(), tolerance);
    473             }
    474         } finally {
    475             mps.forEach(MediaPlayer2::close);
    476         }
    477     }
    478 
    479     public void testPlayAudioLooping() throws Exception {
    480         if (IGNORE_TESTS) {
    481             return;
    482         }
    483         final int resid = R.raw.testmp3;
    484 
    485         MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
    486         try {
    487             AudioAttributes attributes = new AudioAttributes.Builder()
    488                     .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    489                     .build();
    490             mp.setAudioAttributes(attributes);
    491             mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    492             mp.loopCurrent(true);
    493             Monitor onCompletionCalled = new Monitor();
    494             Monitor onPlayCalled = new Monitor();
    495             MediaPlayer2.MediaPlayer2EventCallback ecb =
    496                 new MediaPlayer2.MediaPlayer2EventCallback() {
    497                     @Override
    498                     public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd,
    499                             int what, int extra) {
    500                         Log.i("@@@", "got oncompletion");
    501                         onCompletionCalled.signal();
    502                     }
    503 
    504                     @Override
    505                     public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
    506                             int what, int status) {
    507                         if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
    508                             onPlayCalled.signal();
    509                         }
    510                     }
    511                 };
    512             mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    513 
    514             assertFalse(mp.isPlaying());
    515             onPlayCalled.reset();
    516             mp.play();
    517             onPlayCalled.waitForSignal();
    518             assertTrue(mp.isPlaying());
    519 
    520             long duration = mp.getDuration();
    521             Thread.sleep(duration * 4); // allow for several loops
    522             assertTrue(mp.isPlaying());
    523             assertEquals("wrong number of completion signals", 0,
    524                     onCompletionCalled.getNumSignal());
    525             mp.loopCurrent(false);
    526 
    527             // wait for playback to finish
    528             while(mp.isPlaying()) {
    529                 Thread.sleep(SLEEP_TIME);
    530             }
    531             assertEquals("wrong number of completion signals", 1,
    532                     onCompletionCalled.getNumSignal());
    533         } finally {
    534             mp.close();
    535         }
    536     }
    537 
    538     public void testPlayMidi() throws Exception {
    539         if (IGNORE_TESTS) {
    540             return;
    541         }
    542         final int resid = R.raw.midi8sec;
    543         final int midiDuration = 8000;
    544         final int tolerance = 70;
    545         final int seekDuration = 1000;
    546 
    547         MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
    548 
    549         Monitor onPrepareCalled = new Monitor();
    550         Monitor onSeekToCalled = new Monitor();
    551         Monitor onLoopCurrentCalled = new Monitor();
    552         MediaPlayer2.MediaPlayer2EventCallback ecb =
    553             new MediaPlayer2.MediaPlayer2EventCallback() {
    554                 @Override
    555                 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    556                     if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    557                         onPrepareCalled.signal();
    558                     }
    559                 }
    560 
    561                 @Override
    562                 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
    563                         int what, int status) {
    564                     if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
    565                         onLoopCurrentCalled.signal();
    566                     } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
    567                         onSeekToCalled.signal();
    568                     }
    569                 }
    570             };
    571         mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    572 
    573         try {
    574             AudioAttributes attributes = new AudioAttributes.Builder()
    575                     .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    576                     .build();
    577             mp.setAudioAttributes(attributes);
    578             mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    579 
    580             mp.play();
    581 
    582             assertFalse(mp.isLooping());
    583             onLoopCurrentCalled.reset();
    584             mp.loopCurrent(true);
    585             onLoopCurrentCalled.waitForSignal();
    586             assertTrue(mp.isLooping());
    587 
    588             assertEquals(midiDuration, mp.getDuration(), tolerance);
    589             long pos = mp.getCurrentPosition();
    590             assertTrue(pos >= 0);
    591             assertTrue(pos < midiDuration - seekDuration);
    592 
    593             onSeekToCalled.reset();
    594             mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
    595             onSeekToCalled.waitForSignal();
    596             assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
    597 
    598             // test stop and restart
    599             mp.reset();
    600             AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
    601             mp.setDataSource(new DataSourceDesc.Builder()
    602                     .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
    603                     .build());
    604 
    605             mp.setMediaPlayer2EventCallback(mExecutor, ecb);
    606             onPrepareCalled.reset();
    607             mp.prepare();
    608             onPrepareCalled.waitForSignal();
    609             afd.close();
    610 
    611             mp.play();
    612 
    613             Thread.sleep(SLEEP_TIME);
    614         } finally {
    615             mp.close();
    616         }
    617     }
    618 
    619     static class OutputListener {
    620         int mSession;
    621         AudioEffect mVc;
    622         Visualizer mVis;
    623         byte [] mVisData;
    624         boolean mSoundDetected;
    625         OutputListener(int session) {
    626             mSession = session;
    627             // creating a volume controller on output mix ensures that ro.audio.silent mutes
    628             // audio after the effects and not before
    629             mVc = new AudioEffect(
    630                     AudioEffect.EFFECT_TYPE_NULL,
    631                     UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
    632                     0,
    633                     session);
    634             mVc.setEnabled(true);
    635             mVis = new Visualizer(session);
    636             int size = 256;
    637             int[] range = Visualizer.getCaptureSizeRange();
    638             if (size < range[0]) {
    639                 size = range[0];
    640             }
    641             if (size > range[1]) {
    642                 size = range[1];
    643             }
    644             assertTrue(mVis.setCaptureSize(size) == Visualizer.SUCCESS);
    645 
    646             mVis.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
    647                 @Override
    648                 public void onWaveFormDataCapture(Visualizer visualizer,
    649                         byte[] waveform, int samplingRate) {
    650                     if (!mSoundDetected) {
    651                         for (int i = 0; i < waveform.length; i++) {
    652                             // 8 bit unsigned PCM, zero level is at 128, which is -128 when
    653                             // seen as a signed byte
    654                             if (waveform[i] != -128) {
    655                                 mSoundDetected = true;
    656                                 break;
    657                             }
    658                         }
    659                     }
    660                 }
    661 
    662                 @Override
    663                 public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
    664                 }
    665             }, 10000 /* milliHertz */, true /* PCM */, false /* FFT */);
    666             assertTrue(mVis.setEnabled(true) == Visualizer.SUCCESS);
    667         }
    668 
    669         void reset() {
    670             mSoundDetected = false;
    671         }
    672 
    673         boolean heardSound() {
    674             return mSoundDetected;
    675         }
    676 
    677         void release() {
    678             mVis.release();
    679             mVc.release();
    680         }
    681     }
    682 
    683     public void testPlayAudioTwice() throws Exception {
    684         if (IGNORE_TESTS) {
    685             return;
    686         }
    687         final int resid = R.raw.camera_click;
    688 
    689         MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
    690         try {
    691             AudioAttributes attributes = new AudioAttributes.Builder()
    692                     .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
    693                     .build();
    694             mp.setAudioAttributes(attributes);
    695             mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
    696 
    697             OutputListener listener = new OutputListener(mp.getAudioSessionId());
    698 
    699             Thread.sleep(SLEEP_TIME);
    700             assertFalse("noise heard before test started", listener.heardSound());
    701 
    702             mp.play();
    703             Thread.sleep(SLEEP_TIME);
    704             assertFalse("player was still playing after " + SLEEP_TIME + " ms", mp.isPlaying());
    705             assertTrue("nothing heard while test ran", listener.heardSound());
    706             listener.reset();
    707             mp.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
    708             mp.play();
    709             Thread.sleep(SLEEP_TIME);
    710             assertTrue("nothing heard when sound was replayed", listener.heardSound());
    711             listener.release();
    712         } finally {
    713             mp.close();
    714         }
    715     }
    716 
    717     public void testPlayVideo() throws Exception {
    718         if (IGNORE_TESTS) {
    719             return;
    720         }
    721         playVideoTest(R.raw.testvideo, 352, 288);
    722     }
    723 
    724     /**
    725      * Test for reseting a surface during video playback
    726      * After reseting, the video should continue playing
    727      * from the time setDisplay() was called
    728      */
    729     public void testVideoSurfaceResetting() throws Exception {
    730         if (IGNORE_TESTS) {
    731             return;
    732         }
    733         final int tolerance = 150;
    734         final int audioLatencyTolerance = 1000;  /* covers audio path latency variability */
    735         final int seekPos = 4760;  // This is the I-frame position
    736 
    737         final CountDownLatch seekDone = new CountDownLatch(1);
    738 
    739         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    740             @Override
    741             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
    742                 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
    743                     seekDone.countDown();
    744                 }
    745             }
    746         };
    747         synchronized (mEventCbLock) {
    748             mEventCallbacks.add(ecb);
    749         }
    750 
    751         if (!checkLoadResource(R.raw.testvideo)) {
    752             return; // skip;
    753         }
    754         playLoadedVideo(352, 288, -1);
    755 
    756         Thread.sleep(SLEEP_TIME);
    757 
    758         long posBefore = mPlayer.getCurrentPosition();
    759         mPlayer.setDisplay(getActivity().getSurfaceHolder2());
    760         long posAfter = mPlayer.getCurrentPosition();
    761 
    762         /* temporarily disable timestamp checking because MediaPlayer2 now seeks to I-frame
    763          * position, instead of requested position. setDisplay invovles a seek operation
    764          * internally.
    765          */
    766         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
    767         // assertEquals(posAfter, posBefore, tolerance);
    768         assertTrue(mPlayer.isPlaying());
    769 
    770         Thread.sleep(SLEEP_TIME);
    771 
    772         mPlayer.seekTo(seekPos, MediaPlayer2.SEEK_PREVIOUS_SYNC);
    773         seekDone.await();
    774         posAfter = mPlayer.getCurrentPosition();
    775         assertEquals(seekPos, posAfter, tolerance + audioLatencyTolerance);
    776 
    777         Thread.sleep(SLEEP_TIME / 2);
    778         posBefore = mPlayer.getCurrentPosition();
    779         mPlayer.setDisplay(null);
    780         posAfter = mPlayer.getCurrentPosition();
    781         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
    782         // assertEquals(posAfter, posBefore, tolerance);
    783         assertTrue(mPlayer.isPlaying());
    784 
    785         Thread.sleep(SLEEP_TIME);
    786 
    787         posBefore = mPlayer.getCurrentPosition();
    788         mPlayer.setDisplay(getActivity().getSurfaceHolder());
    789         posAfter = mPlayer.getCurrentPosition();
    790 
    791         // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
    792         // assertEquals(posAfter, posBefore, tolerance);
    793         assertTrue(mPlayer.isPlaying());
    794 
    795         Thread.sleep(SLEEP_TIME);
    796     }
    797 
    798     public void testRecordedVideoPlayback0() throws Exception {
    799         if (IGNORE_TESTS) {
    800             return;
    801         }
    802         testRecordedVideoPlaybackWithAngle(0);
    803     }
    804 
    805     public void testRecordedVideoPlayback90() throws Exception {
    806         if (IGNORE_TESTS) {
    807             return;
    808         }
    809         testRecordedVideoPlaybackWithAngle(90);
    810     }
    811 
    812     public void testRecordedVideoPlayback180() throws Exception {
    813         if (IGNORE_TESTS) {
    814             return;
    815         }
    816         testRecordedVideoPlaybackWithAngle(180);
    817     }
    818 
    819     public void testRecordedVideoPlayback270() throws Exception {
    820         if (IGNORE_TESTS) {
    821             return;
    822         }
    823         testRecordedVideoPlaybackWithAngle(270);
    824     }
    825 
    826     private boolean hasCamera() {
    827         return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    828     }
    829 
    830     private Camera mCamera;
    831     private void testRecordedVideoPlaybackWithAngle(int angle) throws Exception {
    832         int width = RECORDED_VIDEO_WIDTH;
    833         int height = RECORDED_VIDEO_HEIGHT;
    834         final String file = RECORDED_FILE;
    835         final long durationMs = RECORDED_DURATION_MS;
    836 
    837         if (!hasCamera()) {
    838             return;
    839         }
    840 
    841         boolean isSupported = false;
    842         mCamera = Camera.open(0);
    843         Camera.Parameters parameters = mCamera.getParameters();
    844         List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes();
    845         // getSupportedVideoSizes returns null when separate video/preview size
    846         // is not supported.
    847         if (videoSizes == null) {
    848             videoSizes = parameters.getSupportedPreviewSizes();
    849         }
    850         for (Camera.Size size : videoSizes)
    851         {
    852             if (size.width == width && size.height == height) {
    853                 isSupported = true;
    854                 break;
    855             }
    856         }
    857         mCamera.release();
    858         mCamera = null;
    859         if (!isSupported) {
    860             width = videoSizes.get(0).width;
    861             height = videoSizes.get(0).height;
    862         }
    863         checkOrientation(angle);
    864         recordVideo(width, height, angle, file, durationMs);
    865         checkDisplayedVideoSize(width, height, angle, file);
    866         checkVideoRotationAngle(angle, file);
    867     }
    868 
    869     private void checkOrientation(int angle) throws Exception {
    870         assertTrue(angle >= 0);
    871         assertTrue(angle < 360);
    872         assertTrue((angle % 90) == 0);
    873     }
    874 
    875     private void recordVideo(
    876             int w, int h, int angle, String file, long durationMs) throws Exception {
    877 
    878         MediaRecorder recorder = new MediaRecorder();
    879         recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    880         recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    881         recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
    882         recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
    883         recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    884         recorder.setOutputFile(file);
    885         recorder.setOrientationHint(angle);
    886         recorder.setVideoSize(w, h);
    887         recorder.setPreviewDisplay(getActivity().getSurfaceHolder2().getSurface());
    888         recorder.prepare();
    889         recorder.start();
    890         Thread.sleep(durationMs);
    891         recorder.stop();
    892         recorder.release();
    893         recorder = null;
    894     }
    895 
    896     private void checkDisplayedVideoSize(
    897             int w, int h, int angle, String file) throws Exception {
    898 
    899         int displayWidth  = w;
    900         int displayHeight = h;
    901         if ((angle % 180) != 0) {
    902             displayWidth  = h;
    903             displayHeight = w;
    904         }
    905         playVideoTest(file, displayWidth, displayHeight);
    906     }
    907 
    908     private void checkVideoRotationAngle(int angle, String file) {
    909         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    910         retriever.setDataSource(file);
    911         String rotation = retriever.extractMetadata(
    912                 MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
    913         retriever.release();
    914         retriever = null;
    915         assertNotNull(rotation);
    916         assertEquals(Integer.parseInt(rotation), angle);
    917     }
    918 
    919     public void testPlaylist() throws Exception {
    920         if (IGNORE_TESTS) {
    921             return;
    922         }
    923         if (!checkLoadResource(
    924                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
    925             return; // skip
    926         }
    927         DataSourceDesc dsd1 = createDataSourceDesc(
    928                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz);
    929         DataSourceDesc dsd2 = createDataSourceDesc(
    930                 R.raw.testvideo);
    931         ArrayList<DataSourceDesc> nextDSDs = new ArrayList<DataSourceDesc>(2);
    932         nextDSDs.add(dsd2);
    933         nextDSDs.add(dsd1);
    934 
    935         mPlayer.setNextDataSources(nextDSDs);
    936 
    937         Monitor onCompletion1Called = new Monitor();
    938         Monitor onCompletion2Called = new Monitor();
    939         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    940             @Override
    941             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    942                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    943                     Log.i(LOG_TAG, "testPlaylist: prepared dsd MediaId=" + dsd.getMediaId());
    944                     mOnPrepareCalled.signal();
    945                 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
    946                     if (dsd == dsd1) {
    947                         onCompletion1Called.signal();
    948                     } else if (dsd == dsd2) {
    949                         onCompletion2Called.signal();
    950                     } else {
    951                         mOnCompletionCalled.signal();
    952                     }
    953                 }
    954             }
    955         };
    956         synchronized (mEventCbLock) {
    957             mEventCallbacks.add(ecb);
    958         }
    959 
    960         mOnCompletionCalled.reset();
    961         onCompletion1Called.reset();
    962         onCompletion2Called.reset();
    963 
    964         mPlayer.setDisplay(mActivity.getSurfaceHolder());
    965 
    966         mPlayer.prepare();
    967 
    968         mPlayer.play();
    969 
    970         mOnCompletionCalled.waitForSignal();
    971         onCompletion2Called.waitForSignal();
    972         onCompletion1Called.waitForSignal();
    973 
    974         mPlayer.reset();
    975     }
    976 
    977     // setPlaybackParams() with non-zero speed should NOT start playback.
    978     // TODO: enable this test when MediaPlayer2.setPlaybackParams() is fixed
    979     /*
    980     public void testSetPlaybackParamsPositiveSpeed() throws Exception {
    981         if (IGNORE_TESTS) {
    982             return;
    983         }
    984         if (!checkLoadResource(
    985                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
    986             return; // skip
    987         }
    988 
    989         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
    990             @Override
    991             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
    992                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
    993                     mOnPrepareCalled.signal();
    994                 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
    995                     mOnCompletionCalled.signal();
    996                 }
    997             }
    998 
    999             @Override
   1000             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1001                 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
   1002                     mOnSeekCompleteCalled.signal();
   1003                 }
   1004             }
   1005         };
   1006         synchronized (mEventCbLock) {
   1007             mEventCallbacks.add(ecb);
   1008         }
   1009 
   1010         mOnCompletionCalled.reset();
   1011         mPlayer.setDisplay(mActivity.getSurfaceHolder());
   1012 
   1013         mOnPrepareCalled.reset();
   1014         mPlayer.prepare();
   1015         mOnPrepareCalled.waitForSignal();
   1016 
   1017         mOnSeekCompleteCalled.reset();
   1018         mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1019         mOnSeekCompleteCalled.waitForSignal();
   1020 
   1021         final float playbackRate = 1.0f;
   1022 
   1023         int playTime = 2000;  // The testing clip is about 10 second long.
   1024         mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
   1025         assertTrue("MediaPlayer2 should be playing", mPlayer.isPlaying());
   1026         Thread.sleep(playTime);
   1027         assertTrue("MediaPlayer2 should still be playing",
   1028                 mPlayer.getCurrentPosition() > 0);
   1029 
   1030         long duration = mPlayer.getDuration();
   1031         mOnSeekCompleteCalled.reset();
   1032         mPlayer.seekTo(duration - 1000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1033         mOnSeekCompleteCalled.waitForSignal();
   1034 
   1035         mOnCompletionCalled.waitForSignal();
   1036         assertFalse("MediaPlayer2 should not be playing", mPlayer.isPlaying());
   1037         long eosPosition = mPlayer.getCurrentPosition();
   1038 
   1039         mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
   1040         assertTrue("MediaPlayer2 should be playing after EOS", mPlayer.isPlaying());
   1041         Thread.sleep(playTime);
   1042         long position = mPlayer.getCurrentPosition();
   1043         assertTrue("MediaPlayer2 should still be playing after EOS",
   1044                 position > 0 && position < eosPosition);
   1045 
   1046         mPlayer.reset();
   1047     }
   1048     */
   1049 
   1050     public void testPlaybackRate() throws Exception {
   1051         if (IGNORE_TESTS) {
   1052             return;
   1053         }
   1054         final int toleranceMs = 1000;
   1055         if (!checkLoadResource(
   1056                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
   1057             return; // skip
   1058         }
   1059 
   1060         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1061             @Override
   1062             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1063                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1064                     mOnPrepareCalled.signal();
   1065                 }
   1066             }
   1067         };
   1068         synchronized (mEventCbLock) {
   1069             mEventCallbacks.add(ecb);
   1070         }
   1071         mPlayer.setDisplay(mActivity.getSurfaceHolder());
   1072 
   1073         mOnPrepareCalled.reset();
   1074         mPlayer.prepare();
   1075         mOnPrepareCalled.waitForSignal();
   1076 
   1077         SyncParams sync = new SyncParams().allowDefaults();
   1078         mPlayer.setSyncParams(sync);
   1079         sync = mPlayer.getSyncParams();
   1080 
   1081         float[] rates = { 0.25f, 0.5f, 1.0f, 2.0f };
   1082         for (float playbackRate : rates) {
   1083             mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1084             Thread.sleep(1000);
   1085             int playTime = 4000;  // The testing clip is about 10 second long.
   1086             mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
   1087             mPlayer.play();
   1088             Thread.sleep(playTime);
   1089             PlaybackParams pbp = mPlayer.getPlaybackParams();
   1090             assertEquals(
   1091                     playbackRate, pbp.getSpeed(),
   1092                     FLOAT_TOLERANCE + playbackRate * sync.getTolerance());
   1093             assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying());
   1094 
   1095             long playedMediaDurationMs = mPlayer.getCurrentPosition();
   1096             int diff = Math.abs((int)(playedMediaDurationMs / playbackRate) - playTime);
   1097             if (diff > toleranceMs) {
   1098                 fail("Media player had error in playback rate " + playbackRate
   1099                      + ", play time is " + playTime + " vs expected " + playedMediaDurationMs);
   1100             }
   1101             mPlayer.pause();
   1102             pbp = mPlayer.getPlaybackParams();
   1103             // TODO: pause() should NOT change PlaybackParams.
   1104             // assertEquals(0.f, pbp.getSpeed(), FLOAT_TOLERANCE);
   1105         }
   1106         mPlayer.reset();
   1107     }
   1108 
   1109     public void testSeekModes() throws Exception {
   1110         if (IGNORE_TESTS) {
   1111             return;
   1112         }
   1113         // This clip has 2 I frames at 66687us and 4299687us.
   1114         if (!checkLoadResource(
   1115                 R.raw.bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz)) {
   1116             return; // skip
   1117         }
   1118 
   1119         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1120             @Override
   1121             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1122                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1123                     mOnPrepareCalled.signal();
   1124                 }
   1125             }
   1126 
   1127             @Override
   1128             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1129                 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
   1130                     mOnSeekCompleteCalled.signal();
   1131                 }
   1132             }
   1133         };
   1134         synchronized (mEventCbLock) {
   1135             mEventCallbacks.add(ecb);
   1136         }
   1137 
   1138         mPlayer.setDisplay(mActivity.getSurfaceHolder());
   1139 
   1140         mOnPrepareCalled.reset();
   1141         mPlayer.prepare();
   1142         mOnPrepareCalled.waitForSignal();
   1143 
   1144         mOnSeekCompleteCalled.reset();
   1145         mPlayer.play();
   1146 
   1147         final long seekPosMs = 3000;
   1148         final long timeToleranceMs = 100;
   1149         final long syncTime1Ms = 67;
   1150         final long syncTime2Ms = 4300;
   1151 
   1152         // TODO: tighten checking range. For now, ensure mediaplayer doesn't
   1153         // seek to previous sync or next sync.
   1154         long cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST, seekPosMs);
   1155         assertTrue("MediaPlayer2 did not seek to closest position",
   1156                 cp > seekPosMs && cp < syncTime2Ms);
   1157 
   1158         // TODO: tighten checking range. For now, ensure mediaplayer doesn't
   1159         // seek to closest position or next sync.
   1160         cp = runSeekMode(MediaPlayer2.SEEK_PREVIOUS_SYNC, seekPosMs);
   1161         assertTrue("MediaPlayer2 did not seek to preivous sync position",
   1162                 cp < seekPosMs - timeToleranceMs);
   1163 
   1164         // TODO: tighten checking range. For now, ensure mediaplayer doesn't
   1165         // seek to closest position or previous sync.
   1166         cp = runSeekMode(MediaPlayer2.SEEK_NEXT_SYNC, seekPosMs);
   1167         assertTrue("MediaPlayer2 did not seek to next sync position",
   1168                 cp > syncTime2Ms - timeToleranceMs);
   1169 
   1170         // TODO: tighten checking range. For now, ensure mediaplayer doesn't
   1171         // seek to closest position or previous sync.
   1172         cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST_SYNC, seekPosMs);
   1173         assertTrue("MediaPlayer2 did not seek to closest sync position",
   1174                 cp > syncTime2Ms - timeToleranceMs);
   1175 
   1176         mPlayer.reset();
   1177     }
   1178 
   1179     private long runSeekMode(int seekMode, long seekPosMs) throws Exception {
   1180         final int sleepIntervalMs = 100;
   1181         int timeRemainedMs = 10000;  // total time for testing
   1182         final int timeToleranceMs = 100;
   1183 
   1184         mPlayer.seekTo(seekPosMs, seekMode);
   1185         mOnSeekCompleteCalled.waitForSignal();
   1186         mOnSeekCompleteCalled.reset();
   1187         long cp = -seekPosMs;
   1188         while (timeRemainedMs > 0) {
   1189             cp = mPlayer.getCurrentPosition();
   1190             // Wait till MediaPlayer2 starts rendering since MediaPlayer2 caches
   1191             // seek position as current position.
   1192             if (cp < seekPosMs - timeToleranceMs || cp > seekPosMs + timeToleranceMs) {
   1193                 break;
   1194             }
   1195             timeRemainedMs -= sleepIntervalMs;
   1196             Thread.sleep(sleepIntervalMs);
   1197         }
   1198         assertTrue("MediaPlayer2 did not finish seeking in time for mode " + seekMode,
   1199                 timeRemainedMs > 0);
   1200         return cp;
   1201     }
   1202 
   1203     public void testGetTimestamp() throws Exception {
   1204         if (IGNORE_TESTS) {
   1205             return;
   1206         }
   1207         final int toleranceUs = 100000;
   1208         final float playbackRate = 1.0f;
   1209         if (!checkLoadResource(
   1210                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
   1211             return; // skip
   1212         }
   1213 
   1214         Monitor onPauseCalled = new Monitor();
   1215         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1216             @Override
   1217             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1218                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1219                     mOnPrepareCalled.signal();
   1220                 }
   1221             }
   1222 
   1223             @Override
   1224             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1225                 if (what == MediaPlayer2.CALL_COMPLETED_PAUSE) {
   1226                     onPauseCalled.signal();
   1227                 }
   1228             }
   1229         };
   1230         synchronized (mEventCbLock) {
   1231             mEventCallbacks.add(ecb);
   1232         }
   1233 
   1234         mPlayer.setDisplay(mActivity.getSurfaceHolder());
   1235 
   1236         mOnPrepareCalled.reset();
   1237         mPlayer.prepare();
   1238         mOnPrepareCalled.waitForSignal();
   1239 
   1240         mPlayer.play();
   1241         mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
   1242         Thread.sleep(SLEEP_TIME);  // let player get into stable state.
   1243         long nt1 = System.nanoTime();
   1244         MediaTimestamp ts1 = mPlayer.getTimestamp();
   1245         long nt2 = System.nanoTime();
   1246         assertTrue("Media player should return a valid time stamp", ts1 != null);
   1247         assertEquals("MediaPlayer2 had error in clockRate " + ts1.getMediaClockRate(),
   1248                 playbackRate, ts1.getMediaClockRate(), 0.001f);
   1249         assertTrue("The nanoTime of Media timestamp should be taken when getTimestamp is called.",
   1250                 nt1 <= ts1.getAnchorSytemNanoTime() && ts1.getAnchorSytemNanoTime() <= nt2);
   1251 
   1252         onPauseCalled.reset();
   1253         mPlayer.pause();
   1254         onPauseCalled.waitForSignal();
   1255         ts1 = mPlayer.getTimestamp();
   1256         assertTrue("Media player should return a valid time stamp", ts1 != null);
   1257         assertTrue("Media player should have play rate of 0.0f when paused",
   1258                 ts1.getMediaClockRate() == 0.0f);
   1259 
   1260         mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1261         mPlayer.play();
   1262         Thread.sleep(SLEEP_TIME);  // let player get into stable state.
   1263         int playTime = 4000;  // The testing clip is about 10 second long.
   1264         ts1 = mPlayer.getTimestamp();
   1265         assertTrue("Media player should return a valid time stamp", ts1 != null);
   1266         Thread.sleep(playTime);
   1267         MediaTimestamp ts2 = mPlayer.getTimestamp();
   1268         assertTrue("Media player should return a valid time stamp", ts2 != null);
   1269         assertTrue("The clockRate should not be changed.",
   1270                 ts1.getMediaClockRate() == ts2.getMediaClockRate());
   1271         assertEquals("MediaPlayer2 had error in timestamp.",
   1272                 ts1.getAnchorMediaTimeUs() + (long)(playTime * ts1.getMediaClockRate() * 1000),
   1273                 ts2.getAnchorMediaTimeUs(), toleranceUs);
   1274 
   1275         mPlayer.reset();
   1276     }
   1277 
   1278     public void testLocalVideo_MKV_H265_1280x720_500kbps_25fps_AAC_Stereo_128kbps_44100Hz()
   1279             throws Exception {
   1280         if (IGNORE_TESTS) {
   1281             return;
   1282         }
   1283         playVideoTest(
   1284                 R.raw.video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz, 1280, 720);
   1285     }
   1286     public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz()
   1287             throws Exception {
   1288         if (IGNORE_TESTS) {
   1289             return;
   1290         }
   1291         playVideoTest(
   1292                 R.raw.video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
   1293     }
   1294 
   1295     public void testLocalVideo_MP4_H264_480x360_500kbps_30fps_AAC_Stereo_128kbps_44110Hz()
   1296             throws Exception {
   1297         if (IGNORE_TESTS) {
   1298             return;
   1299         }
   1300         playVideoTest(
   1301                 R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
   1302     }
   1303 
   1304     public void testLocalVideo_MP4_H264_480x360_1000kbps_25fps_AAC_Stereo_128kbps_44110Hz()
   1305             throws Exception {
   1306         if (IGNORE_TESTS) {
   1307             return;
   1308         }
   1309         playVideoTest(
   1310                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
   1311     }
   1312 
   1313     public void testLocalVideo_MP4_H264_480x360_1000kbps_30fps_AAC_Stereo_128kbps_44110Hz()
   1314             throws Exception {
   1315         if (IGNORE_TESTS) {
   1316             return;
   1317         }
   1318         playVideoTest(
   1319                 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
   1320     }
   1321 
   1322     public void testLocalVideo_MP4_H264_480x360_1350kbps_25fps_AAC_Stereo_128kbps_44110Hz()
   1323             throws Exception {
   1324         if (IGNORE_TESTS) {
   1325             return;
   1326         }
   1327         playVideoTest(
   1328                 R.raw.video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
   1329     }
   1330 
   1331     public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz()
   1332             throws Exception {
   1333         if (IGNORE_TESTS) {
   1334             return;
   1335         }
   1336         playVideoTest(
   1337                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
   1338     }
   1339 
   1340     public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz_frag()
   1341             throws Exception {
   1342         if (IGNORE_TESTS) {
   1343             return;
   1344         }
   1345         playVideoTest(
   1346                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented,
   1347                 480, 360);
   1348     }
   1349 
   1350 
   1351     public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz()
   1352             throws Exception {
   1353         if (IGNORE_TESTS) {
   1354             return;
   1355         }
   1356         playVideoTest(
   1357                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz, 480, 360);
   1358     }
   1359 
   1360     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_11025Hz()
   1361             throws Exception {
   1362         if (IGNORE_TESTS) {
   1363             return;
   1364         }
   1365         playVideoTest(
   1366                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
   1367     }
   1368 
   1369     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_22050Hz()
   1370             throws Exception {
   1371         if (IGNORE_TESTS) {
   1372             return;
   1373         }
   1374         playVideoTest(
   1375                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
   1376     }
   1377 
   1378     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_11025Hz()
   1379             throws Exception {
   1380         if (IGNORE_TESTS) {
   1381             return;
   1382         }
   1383         playVideoTest(
   1384                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
   1385     }
   1386 
   1387     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_22050Hz()
   1388             throws Exception {
   1389         if (IGNORE_TESTS) {
   1390             return;
   1391         }
   1392         playVideoTest(
   1393                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
   1394     }
   1395 
   1396     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_11025Hz()
   1397             throws Exception {
   1398         if (IGNORE_TESTS) {
   1399             return;
   1400         }
   1401         playVideoTest(
   1402                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
   1403     }
   1404 
   1405     public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_22050Hz()
   1406             throws Exception {
   1407         if (IGNORE_TESTS) {
   1408             return;
   1409         }
   1410         playVideoTest(
   1411                 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
   1412     }
   1413 
   1414     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_11025Hz()
   1415             throws Exception {
   1416         if (IGNORE_TESTS) {
   1417             return;
   1418         }
   1419         playVideoTest(
   1420                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
   1421     }
   1422 
   1423     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_22050Hz()
   1424             throws Exception {
   1425         if (IGNORE_TESTS) {
   1426             return;
   1427         }
   1428         playVideoTest(
   1429                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
   1430     }
   1431 
   1432     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_11025Hz()
   1433             throws Exception {
   1434         if (IGNORE_TESTS) {
   1435             return;
   1436         }
   1437         playVideoTest(
   1438                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
   1439     }
   1440 
   1441     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_22050Hz()
   1442             throws Exception {
   1443         if (IGNORE_TESTS) {
   1444             return;
   1445         }
   1446         playVideoTest(
   1447                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
   1448     }
   1449 
   1450     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_11025Hz()
   1451             throws Exception {
   1452         if (IGNORE_TESTS) {
   1453             return;
   1454         }
   1455         playVideoTest(
   1456                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
   1457     }
   1458 
   1459     public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_22050Hz()
   1460             throws Exception {
   1461         if (IGNORE_TESTS) {
   1462             return;
   1463         }
   1464         playVideoTest(
   1465                 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
   1466     }
   1467 
   1468     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_11025Hz()
   1469             throws Exception {
   1470         if (IGNORE_TESTS) {
   1471             return;
   1472         }
   1473         playVideoTest(
   1474                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
   1475     }
   1476 
   1477     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_22050Hz()
   1478             throws Exception {
   1479         if (IGNORE_TESTS) {
   1480             return;
   1481         }
   1482         playVideoTest(
   1483                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
   1484     }
   1485 
   1486     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_11025Hz()
   1487             throws Exception {
   1488         if (IGNORE_TESTS) {
   1489             return;
   1490         }
   1491         playVideoTest(
   1492                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
   1493     }
   1494 
   1495     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_22050Hz()
   1496             throws Exception {
   1497         if (IGNORE_TESTS) {
   1498             return;
   1499         }
   1500         playVideoTest(
   1501                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
   1502     }
   1503 
   1504     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_11025Hz()
   1505             throws Exception {
   1506         if (IGNORE_TESTS) {
   1507             return;
   1508         }
   1509         playVideoTest(
   1510                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
   1511     }
   1512 
   1513     public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_22050Hz()
   1514             throws Exception {
   1515         if (IGNORE_TESTS) {
   1516             return;
   1517         }
   1518         playVideoTest(
   1519                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
   1520     }
   1521 
   1522     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_11025Hz()
   1523             throws Exception {
   1524         if (IGNORE_TESTS) {
   1525             return;
   1526         }
   1527         playVideoTest(
   1528                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
   1529     }
   1530 
   1531     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_22050Hz()
   1532             throws Exception {
   1533         if (IGNORE_TESTS) {
   1534             return;
   1535         }
   1536         playVideoTest(
   1537                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
   1538     }
   1539 
   1540     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_11025Hz()
   1541             throws Exception {
   1542         if (IGNORE_TESTS) {
   1543             return;
   1544         }
   1545         playVideoTest(
   1546                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
   1547     }
   1548 
   1549     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_22050Hz()
   1550             throws Exception {
   1551         if (IGNORE_TESTS) {
   1552             return;
   1553         }
   1554         playVideoTest(
   1555                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
   1556     }
   1557 
   1558     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_11025Hz()
   1559             throws Exception {
   1560         if (IGNORE_TESTS) {
   1561             return;
   1562         }
   1563         playVideoTest(
   1564                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
   1565     }
   1566 
   1567     public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_22050Hz()
   1568             throws Exception {
   1569         if (IGNORE_TESTS) {
   1570             return;
   1571         }
   1572         playVideoTest(
   1573                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_22050hz, 176, 144);
   1574     }
   1575 
   1576     private void readSubtitleTracks() throws Exception {
   1577         mSubtitleTrackIndex.clear();
   1578         List<MediaPlayer2.TrackInfo> trackInfos = mPlayer.getTrackInfo();
   1579         if (trackInfos == null || trackInfos.size() == 0) {
   1580             return;
   1581         }
   1582 
   1583         Vector<Integer> subtitleTrackIndex = new Vector<>();
   1584         for (int i = 0; i < trackInfos.size(); ++i) {
   1585             assertTrue(trackInfos.get(i) != null);
   1586             if (trackInfos.get(i).getTrackType() ==
   1587                     MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
   1588                 subtitleTrackIndex.add(i);
   1589             }
   1590         }
   1591 
   1592         mSubtitleTrackIndex.addAll(subtitleTrackIndex);
   1593     }
   1594 
   1595     private void selectSubtitleTrack(int index) throws Exception {
   1596         int trackIndex = mSubtitleTrackIndex.get(index);
   1597         mPlayer.selectTrack(trackIndex);
   1598         mSelectedSubtitleIndex = index;
   1599     }
   1600 
   1601     private void deselectSubtitleTrack(int index) throws Exception {
   1602         int trackIndex = mSubtitleTrackIndex.get(index);
   1603         mOnDeselectTrackCalled.reset();
   1604         mPlayer.deselectTrack(trackIndex);
   1605         mOnDeselectTrackCalled.waitForSignal();
   1606         if (mSelectedSubtitleIndex == index) {
   1607             mSelectedSubtitleIndex = -1;
   1608         }
   1609     }
   1610 
   1611     public void testDeselectTrackForSubtitleTracks() throws Throwable {
   1612         if (IGNORE_TESTS) {
   1613             return;
   1614         }
   1615         if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
   1616             return; // skip;
   1617         }
   1618 
   1619         getInstrumentation().waitForIdleSync();
   1620 
   1621         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1622             @Override
   1623             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1624                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1625                     mOnPrepareCalled.signal();
   1626                 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
   1627                     mOnInfoCalled.signal();
   1628                 }
   1629             }
   1630 
   1631             @Override
   1632             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1633                 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
   1634                     mOnSeekCompleteCalled.signal();
   1635                 } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   1636                     mOnPlayCalled.signal();
   1637                 } else if (what == MediaPlayer2.CALL_COMPLETED_DESELECT_TRACK) {
   1638                     mCallStatus = status;
   1639                     mOnDeselectTrackCalled.signal();
   1640                 }
   1641             }
   1642         };
   1643         synchronized (mEventCbLock) {
   1644             mEventCallbacks.add(ecb);
   1645         }
   1646 
   1647         mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
   1648             @Override
   1649             public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
   1650                 if (data != null && data.getData() != null) {
   1651                     mOnSubtitleDataCalled.signal();
   1652                 }
   1653             }
   1654         });
   1655 
   1656         mPlayer.setDisplay(getActivity().getSurfaceHolder());
   1657         mPlayer.setScreenOnWhilePlaying(true);
   1658         mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
   1659 
   1660         mOnPrepareCalled.reset();
   1661         mPlayer.prepare();
   1662         mOnPrepareCalled.waitForSignal();
   1663 
   1664         mOnPlayCalled.reset();
   1665         mPlayer.play();
   1666         mOnPlayCalled.waitForSignal();
   1667         assertTrue(mPlayer.isPlaying());
   1668 
   1669         // Closed caption tracks are in-band.
   1670         // So, those tracks will be found after processing a number of frames.
   1671         mOnInfoCalled.waitForSignal(1500);
   1672 
   1673         mOnInfoCalled.reset();
   1674         mOnInfoCalled.waitForSignal(1500);
   1675 
   1676         readSubtitleTracks();
   1677 
   1678         // Run twice to check if repeated selection-deselection on the same track works well.
   1679         for (int i = 0; i < 2; i++) {
   1680             // Waits until at least one subtitle is fired. Timeout is 2.5 seconds.
   1681             selectSubtitleTrack(i);
   1682             mOnSubtitleDataCalled.reset();
   1683             assertTrue(mOnSubtitleDataCalled.waitForSignal(2500));
   1684 
   1685             // Try deselecting track.
   1686             deselectSubtitleTrack(i);
   1687             mOnSubtitleDataCalled.reset();
   1688             assertFalse(mOnSubtitleDataCalled.waitForSignal(1500));
   1689         }
   1690 
   1691         // Deselecting unselected track: expected error status
   1692         mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
   1693         deselectSubtitleTrack(0);
   1694         assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR);
   1695 
   1696         mPlayer.reset();
   1697     }
   1698 
   1699     public void testChangeSubtitleTrack() throws Throwable {
   1700         if (IGNORE_TESTS) {
   1701             return;
   1702         }
   1703         if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
   1704             return; // skip;
   1705         }
   1706 
   1707         mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
   1708             @Override
   1709             public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
   1710                 if (data != null && data.getData() != null) {
   1711                     mOnSubtitleDataCalled.signal();
   1712                 }
   1713             }
   1714         });
   1715 
   1716         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1717             @Override
   1718             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1719                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1720                     mOnPrepareCalled.signal();
   1721                 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
   1722                     mOnInfoCalled.signal();
   1723                 }
   1724             }
   1725 
   1726             @Override
   1727             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1728                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   1729                     mOnPlayCalled.signal();
   1730                 }
   1731             }
   1732         };
   1733         synchronized (mEventCbLock) {
   1734             mEventCallbacks.add(ecb);
   1735         }
   1736 
   1737         mPlayer.setDisplay(getActivity().getSurfaceHolder());
   1738         mPlayer.setScreenOnWhilePlaying(true);
   1739         mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
   1740 
   1741         mOnPrepareCalled.reset();
   1742         mPlayer.prepare();
   1743         mOnPrepareCalled.waitForSignal();
   1744 
   1745         mOnPlayCalled.reset();
   1746         mPlayer.play();
   1747         mOnPlayCalled.waitForSignal();
   1748         assertTrue(mPlayer.isPlaying());
   1749 
   1750         // Closed caption tracks are in-band.
   1751         // So, those tracks will be found after processing a number of frames.
   1752         mOnInfoCalled.waitForSignal(1500);
   1753 
   1754         mOnInfoCalled.reset();
   1755         mOnInfoCalled.waitForSignal(1500);
   1756 
   1757         readSubtitleTracks();
   1758 
   1759         // Waits until at least two captions are fired. Timeout is 2.5 sec.
   1760         selectSubtitleTrack(0);
   1761         assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
   1762 
   1763         mOnSubtitleDataCalled.reset();
   1764         selectSubtitleTrack(1);
   1765         assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
   1766 
   1767         mPlayer.reset();
   1768     }
   1769 
   1770     public void testGetTrackInfoForVideoWithSubtitleTracks() throws Throwable {
   1771         if (IGNORE_TESTS) {
   1772             return;
   1773         }
   1774         if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
   1775             return; // skip;
   1776         }
   1777 
   1778         getInstrumentation().waitForIdleSync();
   1779 
   1780         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1781             @Override
   1782             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1783                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1784                     mOnPrepareCalled.signal();
   1785                 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
   1786                     mOnInfoCalled.signal();
   1787                 }
   1788             }
   1789 
   1790             @Override
   1791             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1792                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   1793                     mOnPlayCalled.signal();
   1794                 }
   1795             }
   1796         };
   1797         synchronized (mEventCbLock) {
   1798             mEventCallbacks.add(ecb);
   1799         }
   1800 
   1801         mPlayer.setDisplay(getActivity().getSurfaceHolder());
   1802         mPlayer.setScreenOnWhilePlaying(true);
   1803         mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
   1804 
   1805         mOnPrepareCalled.reset();
   1806         mPlayer.prepare();
   1807         mOnPrepareCalled.waitForSignal();
   1808 
   1809         mOnPlayCalled.reset();
   1810         mPlayer.play();
   1811         mOnPlayCalled.waitForSignal();
   1812         assertTrue(mPlayer.isPlaying());
   1813 
   1814         // The media metadata will be changed while playing since closed caption tracks are in-band
   1815         // and those tracks will be found after processing a number of frames. These tracks will be
   1816         // found within one second.
   1817         mOnInfoCalled.waitForSignal(1500);
   1818 
   1819         mOnInfoCalled.reset();
   1820         mOnInfoCalled.waitForSignal(1500);
   1821 
   1822         readSubtitleTracks();
   1823         assertEquals(2, mSubtitleTrackIndex.size());
   1824 
   1825         mPlayer.reset();
   1826     }
   1827 
   1828     /*
   1829      *  This test assumes the resources being tested are between 8 and 14 seconds long
   1830      *  The ones being used here are 10 seconds long.
   1831      */
   1832     public void testResumeAtEnd() throws Throwable {
   1833         if (IGNORE_TESTS) {
   1834             return;
   1835         }
   1836         int testsRun =
   1837             testResumeAtEnd(R.raw.loudsoftmp3) +
   1838             testResumeAtEnd(R.raw.loudsoftwav) +
   1839             testResumeAtEnd(R.raw.loudsoftogg) +
   1840             testResumeAtEnd(R.raw.loudsoftitunes) +
   1841             testResumeAtEnd(R.raw.loudsoftfaac) +
   1842             testResumeAtEnd(R.raw.loudsoftaac);
   1843         if (testsRun == 0) {
   1844             MediaUtils.skipTest("no decoder found");
   1845         }
   1846     }
   1847 
   1848     // returns 1 if test was run, 0 otherwise
   1849     private int testResumeAtEnd(int res) throws Throwable {
   1850         if (!loadResource(res)) {
   1851             Log.i(LOG_TAG, "testResumeAtEnd: No decoder found for " +
   1852                 mContext.getResources().getResourceEntryName(res) +
   1853                 " --- skipping.");
   1854             return 0; // skip
   1855         }
   1856         mOnCompletionCalled.reset();
   1857         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1858             @Override
   1859             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1860                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1861                     mOnPrepareCalled.signal();
   1862                 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
   1863                     mOnCompletionCalled.signal();
   1864                     mPlayer.play();
   1865                 }
   1866             }
   1867         };
   1868         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   1869 
   1870         mOnPrepareCalled.reset();
   1871         mPlayer.prepare();
   1872         mOnPrepareCalled.waitForSignal();
   1873 
   1874         // skip the first part of the file so we reach EOF sooner
   1875         mPlayer.seekTo(5000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1876         mPlayer.play();
   1877         // sleep long enough that we restart playback at least once, but no more
   1878         Thread.sleep(10000);
   1879         assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying());
   1880         mPlayer.reset();
   1881         assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal());
   1882         return 1;
   1883     }
   1884 
   1885     public void testPositionAtEnd() throws Throwable {
   1886         if (IGNORE_TESTS) {
   1887             return;
   1888         }
   1889         int testsRun =
   1890             testPositionAtEnd(R.raw.test1m1shighstereo) +
   1891             testPositionAtEnd(R.raw.loudsoftmp3) +
   1892             testPositionAtEnd(R.raw.loudsoftwav) +
   1893             testPositionAtEnd(R.raw.loudsoftogg) +
   1894             testPositionAtEnd(R.raw.loudsoftitunes) +
   1895             testPositionAtEnd(R.raw.loudsoftfaac) +
   1896             testPositionAtEnd(R.raw.loudsoftaac);
   1897         if (testsRun == 0) {
   1898             MediaUtils.skipTest(LOG_TAG, "no decoder found");
   1899         }
   1900     }
   1901 
   1902     private int testPositionAtEnd(int res) throws Throwable {
   1903         if (!loadResource(res)) {
   1904             Log.i(LOG_TAG, "testPositionAtEnd: No decoder found for " +
   1905                 mContext.getResources().getResourceEntryName(res) +
   1906                 " --- skipping.");
   1907             return 0; // skip
   1908         }
   1909         AudioAttributes attributes = new AudioAttributes.Builder()
   1910                 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
   1911                 .build();
   1912         mPlayer.setAudioAttributes(attributes);
   1913 
   1914         mOnCompletionCalled.reset();
   1915         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1916             @Override
   1917             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1918                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1919                     mOnPrepareCalled.signal();
   1920                 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
   1921                     mOnCompletionCalled.signal();
   1922                 }
   1923             }
   1924 
   1925             @Override
   1926             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1927                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   1928                     mOnPlayCalled.signal();
   1929                 }
   1930             }
   1931         };
   1932         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   1933 
   1934         mOnPrepareCalled.reset();
   1935         mPlayer.prepare();
   1936         mOnPrepareCalled.waitForSignal();
   1937 
   1938         long duration = mPlayer.getDuration();
   1939         assertTrue("resource too short", duration > 6000);
   1940         mPlayer.seekTo(duration - 5000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   1941         mOnPlayCalled.reset();
   1942         mPlayer.play();
   1943         mOnPlayCalled.waitForSignal();
   1944         while (mPlayer.isPlaying()) {
   1945             Log.i("@@@@", "position: " + mPlayer.getCurrentPosition());
   1946             Thread.sleep(500);
   1947         }
   1948         Log.i("@@@@", "final position: " + mPlayer.getCurrentPosition());
   1949         assertTrue(mPlayer.getCurrentPosition() > duration - 1000);
   1950         mPlayer.reset();
   1951         return 1;
   1952     }
   1953 
   1954     public void testCallback() throws Throwable {
   1955         if (IGNORE_TESTS) {
   1956             return;
   1957         }
   1958         final int mp4Duration = 8484;
   1959 
   1960         if (!checkLoadResource(R.raw.testvideo)) {
   1961             return; // skip;
   1962         }
   1963 
   1964         mPlayer.setDisplay(getActivity().getSurfaceHolder());
   1965         mPlayer.setScreenOnWhilePlaying(true);
   1966 
   1967         mOnCompletionCalled.reset();
   1968         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   1969             @Override
   1970             public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd,
   1971                     int width, int height) {
   1972                 mOnVideoSizeChangedCalled.signal();
   1973             }
   1974 
   1975             @Override
   1976             public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1977                 mOnErrorCalled.signal();
   1978             }
   1979 
   1980             @Override
   1981             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   1982                 mOnInfoCalled.signal();
   1983 
   1984                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   1985                     mOnPrepareCalled.signal();
   1986                 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
   1987                     mOnCompletionCalled.signal();
   1988                 }
   1989             }
   1990 
   1991             @Override
   1992             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   1993                 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
   1994                     mOnSeekCompleteCalled.signal();
   1995                 } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   1996                     mOnPlayCalled.signal();
   1997                 }
   1998             }
   1999         };
   2000         synchronized (mEventCbLock) {
   2001             mEventCallbacks.add(ecb);
   2002         }
   2003 
   2004         assertFalse(mOnPrepareCalled.isSignalled());
   2005         assertFalse(mOnVideoSizeChangedCalled.isSignalled());
   2006         mPlayer.prepare();
   2007         mOnPrepareCalled.waitForSignal();
   2008         mOnVideoSizeChangedCalled.waitForSignal();
   2009 
   2010         mOnSeekCompleteCalled.reset();
   2011         mPlayer.seekTo(mp4Duration >> 1, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   2012         mOnSeekCompleteCalled.waitForSignal();
   2013 
   2014         assertFalse(mOnCompletionCalled.isSignalled());
   2015         mPlayer.play();
   2016         mOnPlayCalled.waitForSignal();
   2017         while(mPlayer.isPlaying()) {
   2018             Thread.sleep(SLEEP_TIME);
   2019         }
   2020         assertFalse(mPlayer.isPlaying());
   2021         mOnCompletionCalled.waitForSignal();
   2022         assertFalse(mOnErrorCalled.isSignalled());
   2023         mPlayer.reset();
   2024     }
   2025 
   2026     public void testRecordAndPlay() throws Exception {
   2027         if (IGNORE_TESTS) {
   2028             return;
   2029         }
   2030         if (!hasMicrophone()) {
   2031             MediaUtils.skipTest(LOG_TAG, "no microphone");
   2032             return;
   2033         }
   2034         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
   2035                 || !MediaUtils.checkEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
   2036             return; // skip
   2037         }
   2038         File outputFile = new File(Environment.getExternalStorageDirectory(),
   2039                 "record_and_play.3gp");
   2040         String outputFileLocation = outputFile.getAbsolutePath();
   2041         try {
   2042             recordMedia(outputFileLocation);
   2043 
   2044             Uri uri = Uri.parse(outputFileLocation);
   2045             MediaPlayer2 mp = MediaPlayer2.create();
   2046             try {
   2047                 mp.setDataSource(new DataSourceDesc.Builder()
   2048                         .setDataSource(mContext, uri)
   2049                         .build());
   2050                 mp.prepare();
   2051                 Thread.sleep(SLEEP_TIME);
   2052                 playAndStop(mp);
   2053             } finally {
   2054                 mp.close();
   2055             }
   2056 
   2057             try {
   2058                 mp = createMediaPlayer2(mContext, uri);
   2059                 playAndStop(mp);
   2060             } finally {
   2061                 if (mp != null) {
   2062                     mp.close();
   2063                 }
   2064             }
   2065 
   2066             try {
   2067                 mp = createMediaPlayer2(mContext, uri, getActivity().getSurfaceHolder());
   2068                 playAndStop(mp);
   2069             } finally {
   2070                 if (mp != null) {
   2071                     mp.close();
   2072                 }
   2073             }
   2074         } finally {
   2075             outputFile.delete();
   2076         }
   2077     }
   2078 
   2079     private void playAndStop(MediaPlayer2 mp) throws Exception {
   2080         mp.play();
   2081         Thread.sleep(SLEEP_TIME);
   2082         mp.reset();
   2083     }
   2084 
   2085     private void recordMedia(String outputFile) throws Exception {
   2086         MediaRecorder mr = new MediaRecorder();
   2087         try {
   2088             mr.setAudioSource(MediaRecorder.AudioSource.MIC);
   2089             mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
   2090             mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
   2091             mr.setOutputFile(outputFile);
   2092 
   2093             mr.prepare();
   2094             mr.start();
   2095             Thread.sleep(SLEEP_TIME);
   2096             mr.stop();
   2097         } finally {
   2098             mr.release();
   2099         }
   2100     }
   2101 
   2102     private boolean hasMicrophone() {
   2103         return getActivity().getPackageManager().hasSystemFeature(
   2104                 PackageManager.FEATURE_MICROPHONE);
   2105     }
   2106 
   2107     // Smoke test playback from a Media2DataSource.
   2108     public void testPlaybackFromAMedia2DataSource() throws Exception {
   2109         if (IGNORE_TESTS) {
   2110             return;
   2111         }
   2112         final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
   2113         final int duration = 10000;
   2114 
   2115         if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
   2116             return;
   2117         }
   2118 
   2119         TestMedia2DataSource dataSource =
   2120                 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
   2121         // Test returning -1 from getSize() to indicate unknown size.
   2122         dataSource.returnFromGetSize(-1);
   2123         mPlayer.setDataSource(new DataSourceDesc.Builder()
   2124                 .setDataSource(dataSource)
   2125                 .build());
   2126         playLoadedVideo(null, null, -1);
   2127         assertTrue(mPlayer.isPlaying());
   2128 
   2129         // Test pause and restart.
   2130         mPlayer.pause();
   2131         Thread.sleep(SLEEP_TIME);
   2132         assertFalse(mPlayer.isPlaying());
   2133 
   2134         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   2135             @Override
   2136             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   2137                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   2138                     mOnPrepareCalled.signal();
   2139                 }
   2140             }
   2141 
   2142             @Override
   2143             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   2144                 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
   2145                     mOnPlayCalled.signal();
   2146                 }
   2147             }
   2148         };
   2149         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   2150 
   2151         mOnPlayCalled.reset();
   2152         mPlayer.play();
   2153         mOnPlayCalled.waitForSignal();
   2154         assertTrue(mPlayer.isPlaying());
   2155 
   2156         // Test reset.
   2157         mPlayer.reset();
   2158         mPlayer.setDataSource(new DataSourceDesc.Builder()
   2159                 .setDataSource(dataSource)
   2160                 .build());
   2161 
   2162         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   2163 
   2164         mOnPrepareCalled.reset();
   2165         mPlayer.prepare();
   2166         mOnPrepareCalled.waitForSignal();
   2167 
   2168         mOnPlayCalled.reset();
   2169         mPlayer.play();
   2170         mOnPlayCalled.waitForSignal();
   2171         assertTrue(mPlayer.isPlaying());
   2172 
   2173         // Test seek. Note: the seek position is cached and returned as the
   2174         // current position so there's no point in comparing them.
   2175         mPlayer.seekTo(duration - SLEEP_TIME, MediaPlayer2.SEEK_PREVIOUS_SYNC);
   2176         while (mPlayer.isPlaying()) {
   2177             Thread.sleep(SLEEP_TIME);
   2178         }
   2179     }
   2180 
   2181     public void testNullMedia2DataSourceIsRejected() throws Exception {
   2182         if (IGNORE_TESTS) {
   2183             return;
   2184         }
   2185         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   2186             @Override
   2187             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   2188                 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
   2189                     mCallStatus = status;
   2190                     mOnPlayCalled.signal();
   2191                 }
   2192             }
   2193         };
   2194         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   2195 
   2196         mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
   2197         mPlayer.setDataSource((DataSourceDesc)null);
   2198         mOnPlayCalled.waitForSignal();
   2199         assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR);
   2200     }
   2201 
   2202     public void testMedia2DataSourceIsClosedOnReset() throws Exception {
   2203         if (IGNORE_TESTS) {
   2204             return;
   2205         }
   2206         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   2207             @Override
   2208             public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
   2209                 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
   2210                     mCallStatus = status;
   2211                     mOnPlayCalled.signal();
   2212                 }
   2213             }
   2214         };
   2215         mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
   2216 
   2217         TestMedia2DataSource dataSource = new TestMedia2DataSource(new byte[0]);
   2218         mPlayer.setDataSource(new DataSourceDesc.Builder()
   2219                 .setDataSource(dataSource)
   2220                 .build());
   2221         mOnPlayCalled.waitForSignal();
   2222         mPlayer.reset();
   2223         assertTrue(dataSource.isClosed());
   2224     }
   2225 
   2226     public void testPlaybackFailsIfMedia2DataSourceThrows() throws Exception {
   2227         if (IGNORE_TESTS) {
   2228             return;
   2229         }
   2230         final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
   2231         if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
   2232             return;
   2233         }
   2234 
   2235         setOnErrorListener();
   2236         TestMedia2DataSource dataSource =
   2237                 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
   2238         mPlayer.setDataSource(new DataSourceDesc.Builder()
   2239                 .setDataSource(dataSource)
   2240                 .build());
   2241 
   2242         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   2243             @Override
   2244             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   2245                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   2246                     mOnPrepareCalled.signal();
   2247                 }
   2248             }
   2249         };
   2250         synchronized (mEventCbLock) {
   2251             mEventCallbacks.add(ecb);
   2252         }
   2253 
   2254         mOnPrepareCalled.reset();
   2255         mPlayer.prepare();
   2256         mOnPrepareCalled.waitForSignal();
   2257 
   2258         dataSource.throwFromReadAt();
   2259         mPlayer.play();
   2260         assertTrue(mOnErrorCalled.waitForSignal());
   2261     }
   2262 
   2263     public void testPlaybackFailsIfMedia2DataSourceReturnsAnError() throws Exception {
   2264         if (IGNORE_TESTS) {
   2265             return;
   2266         }
   2267         final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
   2268         if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
   2269             return;
   2270         }
   2271 
   2272         TestMedia2DataSource dataSource =
   2273                 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
   2274         mPlayer.setDataSource(new DataSourceDesc.Builder()
   2275                 .setDataSource(dataSource)
   2276                 .build());
   2277 
   2278         setOnErrorListener();
   2279         MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
   2280             @Override
   2281             public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
   2282                 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
   2283                     mOnPrepareCalled.signal();
   2284                 }
   2285             }
   2286         };
   2287         synchronized (mEventCbLock) {
   2288             mEventCallbacks.add(ecb);
   2289         }
   2290 
   2291         mOnPrepareCalled.reset();
   2292         mPlayer.prepare();
   2293         mOnPrepareCalled.waitForSignal();
   2294 
   2295         dataSource.returnFromReadAt(-2);
   2296         mPlayer.play();
   2297         assertTrue(mOnErrorCalled.waitForSignal());
   2298     }
   2299 }
   2300