Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget.cts;
     18 
     19 import static com.android.compatibility.common.util.CtsMockitoUtils.within;
     20 
     21 import static org.junit.Assert.assertEquals;
     22 import static org.junit.Assert.assertNotNull;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.mockito.Matchers.any;
     25 import static org.mockito.Matchers.anyInt;
     26 import static org.mockito.Mockito.mock;
     27 import static org.mockito.Mockito.times;
     28 import static org.mockito.Mockito.verify;
     29 import static org.mockito.Mockito.verifyZeroInteractions;
     30 
     31 import android.app.Activity;
     32 import android.app.Instrumentation;
     33 import android.content.Context;
     34 import android.media.AudioAttributes;
     35 import android.media.AudioManager;
     36 import android.media.AudioPlaybackConfiguration;
     37 import android.media.MediaPlayer;
     38 import android.os.SystemClock;
     39 import android.support.test.InstrumentationRegistry;
     40 import android.support.test.annotation.UiThreadTest;
     41 import android.support.test.filters.LargeTest;
     42 import android.support.test.rule.ActivityTestRule;
     43 import android.support.test.runner.AndroidJUnit4;
     44 import android.util.Log;
     45 import android.view.View.MeasureSpec;
     46 import android.widget.MediaController;
     47 import android.widget.VideoView;
     48 
     49 import com.android.compatibility.common.util.MediaUtils;
     50 
     51 import org.junit.Before;
     52 import org.junit.Rule;
     53 import org.junit.Test;
     54 import org.junit.runner.RunWith;
     55 
     56 import java.io.IOException;
     57 import java.io.InputStream;
     58 import java.io.OutputStream;
     59 import java.util.List;
     60 
     61 /**
     62  * Test {@link VideoView}.
     63  */
     64 @LargeTest
     65 @RunWith(AndroidJUnit4.class)
     66 public class VideoViewTest {
     67     /** Debug TAG. **/
     68     private static final String TAG = "VideoViewTest";
     69     /** The maximum time to wait for an operation. */
     70     private static final long   TIME_OUT = 15000L;
     71     /** The interval time to wait for completing an operation. */
     72     private static final long   OPERATION_INTERVAL  = 1500L;
     73     /** The duration of R.raw.testvideo. */
     74     private static final int    TEST_VIDEO_DURATION = 11047;
     75     /** The full name of R.raw.testvideo. */
     76     private static final String VIDEO_NAME   = "testvideo.3gp";
     77     /** delta for duration in case user uses different decoders on different
     78         hardware that report a duration that's different by a few milliseconds */
     79     private static final int DURATION_DELTA = 100;
     80     /** AudioAttributes to be used by this player */
     81     private static final AudioAttributes AUDIO_ATTR = new AudioAttributes.Builder()
     82             .setUsage(AudioAttributes.USAGE_GAME)
     83             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
     84             .build();
     85 
     86     private Instrumentation mInstrumentation;
     87     private Activity mActivity;
     88     private VideoView mVideoView;
     89     private String mVideoPath;
     90 
     91     @Rule
     92     public ActivityTestRule<VideoViewCtsActivity> mActivityRule =
     93             new ActivityTestRule<>(VideoViewCtsActivity.class);
     94 
     95     @Before
     96     public void setup() throws Throwable {
     97         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     98         mActivity = mActivityRule.getActivity();
     99         mVideoView = (VideoView) mActivity.findViewById(R.id.videoview);
    100 
    101         mVideoPath = prepareSampleVideo();
    102         assertNotNull(mVideoPath);
    103     }
    104 
    105     private boolean hasCodec() {
    106         return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
    107     }
    108 
    109     private String prepareSampleVideo() throws IOException {
    110         try (InputStream source = mActivity.getResources().openRawResource(R.raw.testvideo);
    111              OutputStream target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_PRIVATE)) {
    112             final byte[] buffer = new byte[1024];
    113             for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
    114                 target.write(buffer, 0, len);
    115             }
    116         }
    117 
    118         return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath();
    119     }
    120 
    121     private void makeVideoView() throws Throwable {
    122         mActivityRule.runOnUiThread(() -> {
    123             MediaController mediaController = new MediaController(mActivity);
    124             mVideoView.setMediaController(mediaController);
    125         });
    126         mInstrumentation.waitForIdleSync();
    127     }
    128 
    129     @UiThreadTest
    130     @Test
    131     public void testConstructor() {
    132         new VideoView(mActivity);
    133 
    134         new VideoView(mActivity, null);
    135 
    136         new VideoView(mActivity, null, 0);
    137     }
    138 
    139     @Test
    140     public void testPlayVideo() throws Throwable {
    141         makeVideoView();
    142         // Don't run the test if the codec isn't supported.
    143         if (!hasCodec()) {
    144             Log.i(TAG, "SKIPPING testPlayVideo1(): codec is not supported");
    145             return;
    146         }
    147 
    148         final MediaPlayer.OnPreparedListener mockPreparedListener =
    149                 mock(MediaPlayer.OnPreparedListener.class);
    150         mVideoView.setOnPreparedListener(mockPreparedListener);
    151 
    152         final MediaPlayer.OnCompletionListener mockCompletionListener =
    153                 mock(MediaPlayer.OnCompletionListener.class);
    154         mVideoView.setOnCompletionListener(mockCompletionListener);
    155 
    156         mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
    157         verify(mockPreparedListener, within(TIME_OUT)).onPrepared(any(MediaPlayer.class));
    158         verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
    159         verifyZeroInteractions(mockCompletionListener);
    160 
    161         mActivityRule.runOnUiThread(mVideoView::start);
    162         // wait time is longer than duration in case system is sluggish
    163         verify(mockCompletionListener, within(TIME_OUT)).onCompletion(any(MediaPlayer.class));
    164         verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
    165     }
    166 
    167     private static final class MyPlaybackCallback extends AudioManager.AudioPlaybackCallback {
    168         boolean mMatchingPlayerFound = false;
    169 
    170         @Override
    171         public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
    172             for (AudioPlaybackConfiguration apc : configs) {
    173                 if (apc.getAudioAttributes().getUsage() == AUDIO_ATTR.getUsage()
    174                         && apc.getAudioAttributes().getContentType()
    175                                 == AUDIO_ATTR.getContentType()) {
    176                     mMatchingPlayerFound = true;
    177                     break;
    178                 }
    179             }
    180         }
    181     }
    182 
    183     @Test
    184     public void testAudioAttributes() throws Throwable {
    185         makeVideoView();
    186         // Don't run the test if the codec isn't supported.
    187         if (!hasCodec()) {
    188             Log.i(TAG, "SKIPPING testAudioAttributes(): codec is not supported");
    189             return;
    190         }
    191 
    192         final MediaPlayer.OnCompletionListener mockCompletionListener =
    193                 mock(MediaPlayer.OnCompletionListener.class);
    194         mVideoView.setOnCompletionListener(mockCompletionListener);
    195 
    196         mVideoView.setAudioAttributes(AUDIO_ATTR);
    197         mVideoView.setAudioFocusRequest(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
    198 
    199         final AudioManager am = (AudioManager) mActivity.getSystemService(Context.AUDIO_SERVICE);
    200         final MyPlaybackCallback myCb = new MyPlaybackCallback();
    201         mActivityRule.runOnUiThread(() -> am.registerAudioPlaybackCallback(myCb, null));
    202         mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
    203         mActivityRule.runOnUiThread(mVideoView::start);
    204         // wait time is longer than duration in case system is sluggish
    205         verify(mockCompletionListener, within(TIME_OUT)).onCompletion(any(MediaPlayer.class));
    206         verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
    207 
    208         // TODO is there a more compact way to test this with mockito?
    209         assertTrue("Audio playback configuration not found for VideoView",
    210                 myCb.mMatchingPlayerFound);
    211     }
    212 
    213     @Test
    214     public void testSetOnErrorListener() throws Throwable {
    215         makeVideoView();
    216 
    217         final MediaPlayer.OnErrorListener mockErrorListener =
    218                 mock(MediaPlayer.OnErrorListener.class);
    219         mVideoView.setOnErrorListener(mockErrorListener);
    220 
    221         mActivityRule.runOnUiThread(() -> {
    222             String path = "unknown path";
    223             mVideoView.setVideoPath(path);
    224             mVideoView.start();
    225         });
    226         mInstrumentation.waitForIdleSync();
    227 
    228         verify(mockErrorListener, within(TIME_OUT)).onError(
    229                 any(MediaPlayer.class), anyInt(), anyInt());
    230         verify(mockErrorListener, times(1)).onError(any(MediaPlayer.class), anyInt(), anyInt());
    231     }
    232 
    233     @Test
    234     public void testGetBufferPercentage() throws Throwable {
    235         makeVideoView();
    236         // Don't run the test if the codec isn't supported.
    237         if (!hasCodec()) {
    238             Log.i(TAG, "SKIPPING testGetBufferPercentage(): codec is not supported");
    239             return;
    240         }
    241 
    242         final MediaPlayer.OnPreparedListener mockPreparedListener =
    243                 mock(MediaPlayer.OnPreparedListener.class);
    244         mVideoView.setOnPreparedListener(mockPreparedListener);
    245 
    246         mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
    247         mInstrumentation.waitForIdleSync();
    248 
    249         verify(mockPreparedListener, within(TIME_OUT)).onPrepared(any(MediaPlayer.class));
    250         verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
    251         int percent = mVideoView.getBufferPercentage();
    252         assertTrue(percent >= 0 && percent <= 100);
    253     }
    254 
    255     @UiThreadTest
    256     @Test
    257     public void testResolveAdjustedSize() {
    258         mVideoView = new VideoView(mActivity);
    259 
    260         final int desiredSize = 100;
    261         int resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.UNSPECIFIED);
    262         assertEquals(desiredSize, resolvedSize);
    263 
    264         final int specSize = MeasureSpec.getSize(MeasureSpec.AT_MOST);
    265         resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.AT_MOST);
    266         assertEquals(Math.min(desiredSize, specSize), resolvedSize);
    267 
    268         resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.EXACTLY);
    269         assertEquals(specSize, resolvedSize);
    270     }
    271 
    272     @Test
    273     public void testGetDuration() throws Throwable {
    274         // Don't run the test if the codec isn't supported.
    275         if (!hasCodec()) {
    276             Log.i(TAG, "SKIPPING testGetDuration(): codec is not supported");
    277             return;
    278         }
    279 
    280         mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
    281         SystemClock.sleep(OPERATION_INTERVAL);
    282         assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA);
    283     }
    284 
    285     @UiThreadTest
    286     @Test
    287     public void testSetMediaController() {
    288         final MediaController ctlr = new MediaController(mActivity);
    289         mVideoView.setMediaController(ctlr);
    290     }
    291 }
    292