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 com.android.cts.widget.R; 20 21 import android.app.Activity; 22 import android.app.Instrumentation; 23 import android.content.Context; 24 import android.cts.util.MediaUtils; 25 import android.cts.util.PollingCheck; 26 import android.media.MediaCodecInfo; 27 import android.media.MediaCodecList; 28 import android.media.MediaPlayer; 29 import android.media.MediaPlayer.OnCompletionListener; 30 import android.media.MediaPlayer.OnErrorListener; 31 import android.media.MediaPlayer.OnPreparedListener; 32 import android.test.ActivityInstrumentationTestCase2; 33 import android.test.UiThreadTest; 34 import android.util.Log; 35 import android.view.View.MeasureSpec; 36 import android.widget.MediaController; 37 import android.widget.VideoView; 38 39 import java.io.IOException; 40 import java.io.InputStream; 41 import java.io.OutputStream; 42 43 /** 44 * Test {@link VideoView}. 45 */ 46 public class VideoViewTest extends ActivityInstrumentationTestCase2<VideoViewCtsActivity> { 47 /** Debug TAG. **/ 48 private static final String TAG = "VideoViewTest"; 49 /** The maximum time to wait for an operation. */ 50 private static final long TIME_OUT = 15000L; 51 /** The interval time to wait for completing an operation. */ 52 private static final long OPERATION_INTERVAL = 1500L; 53 /** The duration of R.raw.testvideo. */ 54 private static final int TEST_VIDEO_DURATION = 11047; 55 /** The full name of R.raw.testvideo. */ 56 private static final String VIDEO_NAME = "testvideo.3gp"; 57 /** delta for duration in case user uses different decoders on different 58 hardware that report a duration that's different by a few milliseconds */ 59 private static final int DURATION_DELTA = 100; 60 61 private VideoView mVideoView; 62 private Activity mActivity; 63 private Instrumentation mInstrumentation; 64 private String mVideoPath; 65 66 private static class MockListener { 67 private boolean mTriggered; 68 MockListener()69 MockListener() { 70 mTriggered = false; 71 } 72 isTriggered()73 public boolean isTriggered() { 74 return mTriggered; 75 } 76 onEvent()77 protected void onEvent() { 78 mTriggered = true; 79 } 80 } 81 82 private static class MockOnPreparedListener extends MockListener 83 implements OnPreparedListener { onPrepared(MediaPlayer mp)84 public void onPrepared(MediaPlayer mp) { 85 super.onEvent(); 86 } 87 } 88 89 private static class MockOnErrorListener extends MockListener implements OnErrorListener { onError(MediaPlayer mp, int what, int extra)90 public boolean onError(MediaPlayer mp, int what, int extra) { 91 super.onEvent(); 92 return false; 93 } 94 } 95 96 private static class MockOnCompletionListener extends MockListener 97 implements OnCompletionListener { onCompletion(MediaPlayer mp)98 public void onCompletion(MediaPlayer mp) { 99 super.onEvent(); 100 } 101 } 102 hasCodec()103 private boolean hasCodec() { 104 return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo); 105 } 106 107 /** 108 * Instantiates a new video view test. 109 */ VideoViewTest()110 public VideoViewTest() { 111 super("com.android.cts.widget", VideoViewCtsActivity.class); 112 } 113 114 /** 115 * Find the video view specified by id. 116 * 117 * @param id the id 118 * @return the video view 119 */ findVideoViewById(int id)120 private VideoView findVideoViewById(int id) { 121 return (VideoView) mActivity.findViewById(id); 122 } 123 prepareSampleVideo()124 private String prepareSampleVideo() throws IOException { 125 InputStream source = null; 126 OutputStream target = null; 127 128 try { 129 source = mActivity.getResources().openRawResource(R.raw.testvideo); 130 target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_WORLD_READABLE); 131 132 final byte[] buffer = new byte[1024]; 133 for (int len = source.read(buffer); len > 0; len = source.read(buffer)) { 134 target.write(buffer, 0, len); 135 } 136 } finally { 137 if (source != null) { 138 source.close(); 139 } 140 if (target != null) { 141 target.close(); 142 } 143 } 144 145 return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath(); 146 } 147 148 /** 149 * Wait for an asynchronous media operation complete. 150 * @throws InterruptedException 151 */ waitForOperationComplete()152 private void waitForOperationComplete() throws InterruptedException { 153 Thread.sleep(OPERATION_INTERVAL); 154 } 155 156 @Override setUp()157 protected void setUp() throws Exception { 158 super.setUp(); 159 mActivity = getActivity(); 160 mInstrumentation = getInstrumentation(); 161 mVideoPath = prepareSampleVideo(); 162 assertNotNull(mVideoPath); 163 mVideoView = findVideoViewById(R.id.videoview); 164 } 165 makeVideoView()166 private void makeVideoView() { 167 mActivity.runOnUiThread(new Runnable() { 168 public void run() { 169 MediaController mediaController = new MediaController(mActivity); 170 mVideoView.setMediaController(mediaController); 171 } 172 }); 173 mInstrumentation.waitForIdleSync(); 174 } 175 176 @UiThreadTest testConstructor()177 public void testConstructor() { 178 new VideoView(mActivity); 179 180 new VideoView(mActivity, null); 181 182 new VideoView(mActivity, null, 0); 183 } 184 testPlayVideo1()185 public void testPlayVideo1() throws Throwable { 186 makeVideoView(); 187 // Don't run the test if the codec isn't supported. 188 if (!hasCodec()) { 189 Log.i(TAG, "SKIPPING testPlayVideo1(): codec is not supported"); 190 return; 191 } 192 193 final MockOnPreparedListener preparedListener = new MockOnPreparedListener(); 194 mVideoView.setOnPreparedListener(preparedListener); 195 final MockOnCompletionListener completionListener = new MockOnCompletionListener(); 196 mVideoView.setOnCompletionListener(completionListener); 197 198 runTestOnUiThread(new Runnable() { 199 public void run() { 200 mVideoView.setVideoPath(mVideoPath); 201 } 202 }); 203 new PollingCheck(TIME_OUT) { 204 @Override 205 protected boolean check() { 206 return preparedListener.isTriggered(); 207 } 208 }.run(); 209 assertFalse(completionListener.isTriggered()); 210 211 runTestOnUiThread(new Runnable() { 212 public void run() { 213 mVideoView.start(); 214 } 215 }); 216 // wait time is longer than duration in case system is sluggish 217 new PollingCheck(mVideoView.getDuration() + TIME_OUT) { 218 @Override 219 protected boolean check() { 220 return completionListener.isTriggered(); 221 } 222 }.run(); 223 } 224 testSetOnErrorListener()225 public void testSetOnErrorListener() throws Throwable { 226 makeVideoView(); 227 final MockOnErrorListener listener = new MockOnErrorListener(); 228 mVideoView.setOnErrorListener(listener); 229 230 runTestOnUiThread(new Runnable() { 231 public void run() { 232 String path = "unknown path"; 233 mVideoView.setVideoPath(path); 234 mVideoView.start(); 235 } 236 }); 237 mInstrumentation.waitForIdleSync(); 238 239 new PollingCheck(TIME_OUT) { 240 @Override 241 protected boolean check() { 242 return listener.isTriggered(); 243 } 244 }.run(); 245 } 246 testGetBufferPercentage()247 public void testGetBufferPercentage() throws Throwable { 248 makeVideoView(); 249 // Don't run the test if the codec isn't supported. 250 if (!hasCodec()) { 251 Log.i(TAG, "SKIPPING testGetBufferPercentage(): codec is not supported"); 252 return; 253 } 254 255 final MockOnPreparedListener prepareListener = new MockOnPreparedListener(); 256 mVideoView.setOnPreparedListener(prepareListener); 257 258 runTestOnUiThread(new Runnable() { 259 public void run() { 260 mVideoView.setVideoPath(mVideoPath); 261 } 262 }); 263 mInstrumentation.waitForIdleSync(); 264 265 new PollingCheck(TIME_OUT) { 266 @Override 267 protected boolean check() { 268 return prepareListener.isTriggered(); 269 } 270 }.run(); 271 int percent = mVideoView.getBufferPercentage(); 272 assertTrue(percent >= 0 && percent <= 100); 273 } 274 275 @UiThreadTest testResolveAdjustedSize()276 public void testResolveAdjustedSize() { 277 mVideoView = new VideoView(mActivity); 278 279 final int desiredSize = 100; 280 int resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.UNSPECIFIED); 281 assertEquals(desiredSize, resolvedSize); 282 283 final int specSize = MeasureSpec.getSize(MeasureSpec.AT_MOST); 284 resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.AT_MOST); 285 assertEquals(Math.min(desiredSize, specSize), resolvedSize); 286 287 resolvedSize = mVideoView.resolveAdjustedSize(desiredSize, MeasureSpec.EXACTLY); 288 assertEquals(specSize, resolvedSize); 289 } 290 testGetDuration()291 public void testGetDuration() throws Throwable { 292 // Don't run the test if the codec isn't supported. 293 if (!hasCodec()) { 294 Log.i(TAG, "SKIPPING testGetDuration(): codec is not supported"); 295 return; 296 } 297 298 runTestOnUiThread(new Runnable() { 299 public void run() { 300 mVideoView.setVideoPath(mVideoPath); 301 } 302 }); 303 waitForOperationComplete(); 304 assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA); 305 } 306 307 @UiThreadTest 308 public void testSetMediaController() { 309 final MediaController ctlr = new MediaController(mActivity); 310 mVideoView.setMediaController(ctlr); 311 } 312 } 313