blob: 6cc3800236494da8c4fdff83c25fba749da5a63e [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.widget.cts;
import static com.android.compatibility.common.util.CtsMockitoUtils.within;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.MediaPlayer;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.view.View.MeasureSpec;
import android.widget.MediaController;
import android.widget.VideoView;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
* Test {@link VideoView}.
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
public class VideoViewTest {
/** Debug TAG. **/
private static final String TAG = "VideoViewTest";
/** The maximum time to wait for an operation. */
private static final long TIME_OUT = 15000L;
/** The interval time to wait for completing an operation. */
private static final long OPERATION_INTERVAL = 1500L;
/** The duration of R.raw.testvideo. */
private static final int TEST_VIDEO_DURATION = 11047;
/** The full name of R.raw.testvideo. */
private static final String VIDEO_NAME = "testvideo.3gp";
/** delta for duration in case user uses different decoders on different
hardware that report a duration that's different by a few milliseconds */
private static final int DURATION_DELTA = 100;
/** AudioAttributes to be used by this player */
private static final AudioAttributes AUDIO_ATTR = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
private Instrumentation mInstrumentation;
private Activity mActivity;
private VideoView mVideoView;
private String mVideoPath;
@Rule
public ActivityTestRule<VideoViewCtsActivity> mActivityRule =
new ActivityTestRule<>(VideoViewCtsActivity.class);
@Before
public void setup() throws Throwable {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivity = mActivityRule.getActivity();
mVideoView = (VideoView) mActivity.findViewById(R.id.videoview);
mVideoPath = prepareSampleVideo();
assertNotNull(mVideoPath);
}
private boolean hasCodec() {
return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
}
private String prepareSampleVideo() throws IOException {
try (InputStream source = mActivity.getResources().openRawResource(R.raw.testvideo);
OutputStream target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_PRIVATE)) {
final byte[] buffer = new byte[1024];
for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
target.write(buffer, 0, len);
}
}
return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath();
}
private void makeVideoView() throws Throwable {
mActivityRule.runOnUiThread(() -> {
MediaController mediaController = new MediaController(mActivity);
mVideoView.setMediaController(mediaController);
});
mInstrumentation.waitForIdleSync();
}
@UiThreadTest
@Test
public void testConstructor() {
new VideoView(mActivity);
new VideoView(mActivity, null);
new VideoView(mActivity, null, 0);
}
@Test
public void testPlayVideo() throws Throwable {
makeVideoView();
// Don't run the test if the codec isn't supported.
if (!hasCodec()) {
Log.i(TAG, "SKIPPING testPlayVideo1(): codec is not supported");
return;
}
final MediaPlayer.OnPreparedListener mockPreparedListener =
mock(MediaPlayer.OnPreparedListener.class);
mVideoView.setOnPreparedListener(mockPreparedListener);
final MediaPlayer.OnCompletionListener mockCompletionListener =
mock(MediaPlayer.OnCompletionListener.class);
mVideoView.setOnCompletionListener(mockCompletionListener);
mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
verify(mockPreparedListener, within(TIME_OUT)).onPrepared(any(MediaPlayer.class));
verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
verifyZeroInteractions(mockCompletionListener);
mActivityRule.runOnUiThread(mVideoView::start);
// wait time is longer than duration in case system is sluggish
verify(mockCompletionListener, within(TIME_OUT)).onCompletion(any(MediaPlayer.class));
verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
}
private static final class MyPlaybackCallback extends AudioManager.AudioPlaybackCallback {
boolean mMatchingPlayerFound = false;
@Override
public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
for (AudioPlaybackConfiguration apc : configs) {
if (apc.getAudioAttributes().getUsage() == AUDIO_ATTR.getUsage()
&& apc.getAudioAttributes().getContentType()
== AUDIO_ATTR.getContentType()) {
mMatchingPlayerFound = true;
break;
}
}
}
}
@Test
public void testAudioAttributes() throws Throwable {
makeVideoView();
// Don't run the test if the codec isn't supported.
if (!hasCodec()) {
Log.i(TAG, "SKIPPING testAudioAttributes(): codec is not supported");
return;
}
final MediaPlayer.OnCompletionListener mockCompletionListener =
mock(MediaPlayer.OnCompletionListener.class);
mVideoView.setOnCompletionListener(mockCompletionListener);
mVideoView.setAudioAttributes(AUDIO_ATTR);
mVideoView.setAudioFocusRequest(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
final AudioManager am = (AudioManager) mActivity.getSystemService(Context.AUDIO_SERVICE);
final MyPlaybackCallback myCb = new MyPlaybackCallback();
mActivityRule.runOnUiThread(() -> am.registerAudioPlaybackCallback(myCb, null));
mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
mActivityRule.runOnUiThread(mVideoView::start);
// wait time is longer than duration in case system is sluggish
verify(mockCompletionListener, within(TIME_OUT)).onCompletion(any(MediaPlayer.class));
verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
// TODO is there a more compact way to test this with mockito?
assertTrue("Audio playback configuration not found for VideoView",
myCb.mMatchingPlayerFound);
}
@Test
public void testSetOnErrorListener() throws Throwable {
makeVideoView();
final MediaPlayer.OnErrorListener mockErrorListener =
mock(MediaPlayer.OnErrorListener.class);
mVideoView.setOnErrorListener(mockErrorListener);
mActivityRule.runOnUiThread(() -> {
String path = "unknown path";
mVideoView.setVideoPath(path);
mVideoView.start();
});
mInstrumentation.waitForIdleSync();
verify(mockErrorListener, within(TIME_OUT)).onError(
any(MediaPlayer.class), anyInt(), anyInt());
verify(mockErrorListener, times(1)).onError(any(MediaPlayer.class), anyInt(), anyInt());
}
@Test
public void testGetBufferPercentage() throws Throwable {
makeVideoView();
// Don't run the test if the codec isn't supported.
if (!hasCodec()) {
Log.i(TAG, "SKIPPING testGetBufferPercentage(): codec is not supported");
return;
}
final MediaPlayer.OnPreparedListener mockPreparedListener =
mock(MediaPlayer.OnPreparedListener.class);
mVideoView.setOnPreparedListener(mockPreparedListener);
mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
mInstrumentation.waitForIdleSync();
verify(mockPreparedListener, within(TIME_OUT)).onPrepared(any(MediaPlayer.class));
verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
int percent = mVideoView.getBufferPercentage();
assertTrue(percent >= 0 && percent <= 100);
}
@UiThreadTest
@Test
public void testResolveAdjustedSize() {
mVideoView = new VideoView(mActivity);
final int desiredSize = 100;
int resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.UNSPECIFIED);
assertEquals(desiredSize, resolvedSize);
final int specSize = MeasureSpec.getSize(MeasureSpec.AT_MOST);
resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.AT_MOST);
assertEquals(Math.min(desiredSize, specSize), resolvedSize);
resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.EXACTLY);
assertEquals(specSize, resolvedSize);
}
@Test
public void testGetDuration() throws Throwable {
// Don't run the test if the codec isn't supported.
if (!hasCodec()) {
Log.i(TAG, "SKIPPING testGetDuration(): codec is not supported");
return;
}
mActivityRule.runOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
SystemClock.sleep(OPERATION_INTERVAL);
assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA);
}
@UiThreadTest
@Test
public void testSetMediaController() {
final MediaController ctlr = new MediaController(mActivity);
mVideoView.setMediaController(ctlr);
}
}