1/* 2 * Copyright (C) 2011 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 17package com.android.ex.variablespeed; 18 19import com.google.common.io.Closeables; 20 21import android.content.ContentResolver; 22import android.content.ContentValues; 23import android.content.res.AssetManager; 24import android.net.Uri; 25import android.provider.VoicemailContract; 26import android.test.InstrumentationTestCase; 27 28import java.io.IOException; 29import java.io.InputStream; 30import java.io.OutputStream; 31import java.lang.annotation.Retention; 32import java.lang.annotation.RetentionPolicy; 33import java.util.HashMap; 34import java.util.Map; 35import java.util.concurrent.TimeUnit; 36 37/** 38 * Base test for checking implementations of {@link MediaPlayerProxy}. 39 * <p> 40 * The purpose behind this class is to collect tests that implementations of 41 * MediaPlayerProxy should support. 42 * <p> 43 * This allows tests to show that the built-in {@link android.media.MediaPlayer} is performing 44 * correctly with respect to the contract it provides, i.e. test my understanding of that contract. 45 * <p> 46 * It allows us to test the current {@link VariableSpeed} implementation, and make sure that this 47 * too corresponds with the MediaPlayer implementation. 48 * <p> 49 * These tests cannot be run on their own - you must provide a concrete subclass of this test case - 50 * and in that subclass you will provide an implementation of the abstract 51 * {@link #createTestMediaPlayer()} method to construct the player you would like to test. Every 52 * test will construct the player in {@link #setUp()} and release it in {@link #tearDown()}. 53 */ 54public abstract class MediaPlayerProxyTestCase extends InstrumentationTestCase { 55 private static final float ERROR_TOLERANCE_MILLIS = 1000f; 56 57 /** The phone number to use when inserting test data into the content provider. */ 58 private static final String CONTACT_NUMBER = "01234567890"; 59 60 /** 61 * A map from filename + mime type to the uri we can use to play from the content provider. 62 * <p> 63 * This is lazily filled in by the {@link #getTestContentUri(String, String)} method. 64 * <p> 65 * This map is keyed from the concatenation of filename and mime type with a "+" separator, it's 66 * not perfect but it doesn't matter in this test code. 67 */ 68 private final Map<String, Uri> mContentUriMap = new HashMap<String, Uri>(); 69 70 /** The system under test. */ 71 private MediaPlayerProxy mPlayer; 72 73 private AwaitableCompletionListener mCompletionListener; 74 private AwaitableErrorListener mErrorListener; 75 76 @Override 77 protected void setUp() throws Exception { 78 super.setUp(); 79 mPlayer = createTestMediaPlayer(); 80 mCompletionListener = new AwaitableCompletionListener(); 81 mErrorListener = new AwaitableErrorListener(); 82 } 83 84 @Override 85 protected void tearDown() throws Exception { 86 mCompletionListener = null; 87 mErrorListener = null; 88 mPlayer.release(); 89 mPlayer = null; 90 cleanupContentUriIfNecessary(); 91 super.tearDown(); 92 } 93 94 public abstract MediaPlayerProxy createTestMediaPlayer() throws Exception; 95 96 /** Annotation to indicate that test should throw an {@link IllegalStateException}. */ 97 @Retention(RetentionPolicy.RUNTIME) 98 public @interface ShouldThrowIllegalStateException { 99 } 100 101 @Override 102 protected void runTest() throws Throwable { 103 // Tests annotated with ShouldThrowIllegalStateException will fail if they don't. 104 // Tests not annotated this way are run as normal. 105 if (getClass().getMethod(getName()).isAnnotationPresent( 106 ShouldThrowIllegalStateException.class)) { 107 try { 108 super.runTest(); 109 fail("Expected this method to throw an IllegalStateException, but it didn't"); 110 } catch (IllegalStateException e) { 111 // Expected. 112 } 113 } else { 114 super.runTest(); 115 } 116 } 117 118 public void testReleaseMultipleTimesHasNoEffect() throws Exception { 119 mPlayer.release(); 120 mPlayer.release(); 121 } 122 123 public void testResetOnNewlyCreatedObject() throws Exception { 124 mPlayer.reset(); 125 } 126 127 public void testSetDataSource() throws Exception { 128 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 129 } 130 131 @ShouldThrowIllegalStateException 132 public void testSetDataSourceTwice_ShouldFailWithIllegalState() throws Exception { 133 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 134 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 135 } 136 137 @ShouldThrowIllegalStateException 138 public void testSetDataSourceAfterRelease_ShouldFailWithIllegalState() throws Exception { 139 mPlayer.release(); 140 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 141 } 142 143 public void testPrepare() throws Exception { 144 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 145 mPlayer.prepare(); 146 } 147 148 @ShouldThrowIllegalStateException 149 public void testPrepareBeforeSetDataSource_ShouldFail() throws Exception { 150 mPlayer.prepare(); 151 } 152 153 @ShouldThrowIllegalStateException 154 public void testPrepareTwice_ShouldFailWithIllegalState() throws Exception { 155 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 156 mPlayer.prepare(); 157 mPlayer.prepare(); 158 } 159 160 public void testStartThenImmediatelyRelease() throws Exception { 161 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 162 mPlayer.prepare(); 163 mPlayer.start(); 164 } 165 166 public void testPlayABitThenRelease() throws Exception { 167 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 168 mPlayer.prepare(); 169 mPlayer.start(); 170 Thread.sleep(2000); 171 } 172 173 public void testPlayFully() throws Exception { 174 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 175 mPlayer.prepare(); 176 mPlayer.setOnCompletionListener(mCompletionListener); 177 mPlayer.start(); 178 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 179 } 180 181 public void testGetDuration() throws Exception { 182 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 183 mPlayer.prepare(); 184 int duration = mPlayer.getDuration(); 185 assertTrue("duration was " + duration, duration > 0); 186 mPlayer.setOnCompletionListener(mCompletionListener); 187 mPlayer.start(); 188 assertEquals(duration, mPlayer.getDuration()); 189 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 190 assertEquals(duration, mPlayer.getDuration()); 191 } 192 193 @ShouldThrowIllegalStateException 194 public void testGetDurationAfterRelease_ShouldFail() throws Exception { 195 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 196 mPlayer.release(); 197 mPlayer.getDuration(); 198 } 199 200 @ShouldThrowIllegalStateException 201 public void testGetPositionAfterRelease_ShouldFail() throws Exception { 202 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 203 mPlayer.release(); 204 mPlayer.getCurrentPosition(); 205 } 206 207 public void testGetCurrentPosition_ZeroBeforePlaybackBegins() throws Exception { 208 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 209 assertEquals(0, mPlayer.getCurrentPosition()); 210 mPlayer.prepare(); 211 assertEquals(0, mPlayer.getCurrentPosition()); 212 } 213 214 public void testGetCurrentPosition_DuringPlayback() throws Exception { 215 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 216 mPlayer.prepare(); 217 mPlayer.start(); 218 Thread.sleep(2000); 219 assertEquals(2000, mPlayer.getCurrentPosition(), ERROR_TOLERANCE_MILLIS); 220 } 221 222 public void testGetCurrentPosition_FinishedPlaying() throws Exception { 223 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 224 mPlayer.prepare(); 225 mPlayer.setOnCompletionListener(mCompletionListener); 226 mPlayer.start(); 227 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 228 assertEquals(mPlayer.getDuration(), mPlayer.getCurrentPosition(), ERROR_TOLERANCE_MILLIS); 229 } 230 231 public void testGetCurrentPosition_DuringPlaybackWithSeek() throws Exception { 232 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 233 mPlayer.prepare(); 234 mPlayer.seekTo(1500); 235 mPlayer.start(); 236 Thread.sleep(1500); 237 assertEquals(3000, mPlayer.getCurrentPosition(), ERROR_TOLERANCE_MILLIS); 238 } 239 240 public void testSeekHalfWayBeforePlaying() throws Exception { 241 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 242 mPlayer.prepare(); 243 assertTrue(mPlayer.getDuration() > 0); 244 mPlayer.seekTo(mPlayer.getDuration() / 2); 245 mPlayer.start(); 246 mPlayer.setOnCompletionListener(mCompletionListener); 247 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 248 } 249 250 public void testHalfWaySeekWithStutteringAudio() throws Exception { 251 // The audio contained in this file has a stutter if we seek to half way and play. 252 // It shouldn't have. 253 setDataSourceFromContentProvider(mPlayer, "fake_voicemail2.mp3", "audio/mp3"); 254 mPlayer.prepare(); 255 assertTrue(mPlayer.getDuration() > 0); 256 mPlayer.seekTo(mPlayer.getDuration() / 2); 257 mPlayer.start(); 258 mPlayer.setOnCompletionListener(mCompletionListener); 259 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 260 } 261 262 public void testResetWithoutReleaseAndThenReUse() throws Exception { 263 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 264 mPlayer.reset(); 265 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 266 mPlayer.prepare(); 267 mPlayer.seekTo(mPlayer.getDuration() / 2); 268 mPlayer.start(); 269 Thread.sleep(1000); 270 } 271 272 public void testResetAfterPlaybackThenReUse() throws Exception { 273 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 274 mPlayer.setOnCompletionListener(mCompletionListener); 275 mPlayer.prepare(); 276 mPlayer.start(); 277 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 278 mPlayer.reset(); 279 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 280 mPlayer.prepare(); 281 mPlayer.start(); 282 Thread.sleep(2000); 283 } 284 285 public void testResetDuringPlaybackThenReUse() throws Exception { 286 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 287 mPlayer.prepare(); 288 mPlayer.start(); 289 Thread.sleep(2000); 290 mPlayer.reset(); 291 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 292 mPlayer.prepare(); 293 mPlayer.start(); 294 Thread.sleep(2000); 295 } 296 297 public void testFinishPlayingThenSeekToHalfWayThenPlayAgain() throws Exception { 298 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 299 mPlayer.prepare(); 300 mPlayer.setOnCompletionListener(mCompletionListener); 301 mPlayer.start(); 302 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 303 mPlayer.seekTo(mPlayer.getDuration() / 2); 304 mPlayer.start(); 305 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 306 } 307 308 public void testPause_DuringPlayback() throws Exception { 309 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 310 mPlayer.prepare(); 311 mPlayer.start(); 312 assertTrue(mPlayer.isPlaying()); 313 Thread.sleep(2000); 314 assertTrue(mPlayer.isPlaying()); 315 mPlayer.pause(); 316 assertFalse(mPlayer.isPlaying()); 317 } 318 319 public void testPause_DoesNotInvokeCallback() throws Exception { 320 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 321 mPlayer.prepare(); 322 mPlayer.setOnCompletionListener(mCompletionListener); 323 mPlayer.start(); 324 mPlayer.pause(); 325 Thread.sleep(200); 326 mCompletionListener.assertNoMoreCallbacks(); 327 } 328 329 public void testReset_DoesNotInvokeCallback() throws Exception { 330 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 331 mPlayer.prepare(); 332 mPlayer.setOnCompletionListener(mCompletionListener); 333 mPlayer.start(); 334 mPlayer.reset(); 335 Thread.sleep(200); 336 mCompletionListener.assertNoMoreCallbacks(); 337 } 338 339 public void testPause_MultipleTimes() throws Exception { 340 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 341 mPlayer.prepare(); 342 mPlayer.start(); 343 Thread.sleep(2000); 344 mPlayer.pause(); 345 mPlayer.pause(); 346 } 347 348 public void testDoubleStartWaitingForFinish() throws Exception { 349 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 350 mPlayer.prepare(); 351 mPlayer.setOnCompletionListener(mCompletionListener); 352 mPlayer.start(); 353 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 354 mPlayer.start(); 355 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 356 } 357 358 public void testTwoFastConsecutiveStarts() throws Exception { 359 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 360 mPlayer.prepare(); 361 mPlayer.setOnCompletionListener(mCompletionListener); 362 mPlayer.start(); 363 mPlayer.start(); 364 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 365 Thread.sleep(200); 366 mCompletionListener.assertNoMoreCallbacks(); 367 } 368 369 public void testThreeFastConsecutiveStarts() throws Exception { 370 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 371 mPlayer.prepare(); 372 mPlayer.setOnCompletionListener(mCompletionListener); 373 mPlayer.start(); 374 mPlayer.start(); 375 mPlayer.start(); 376 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 377 Thread.sleep(4000); 378 mCompletionListener.assertNoMoreCallbacks(); 379 } 380 381 public void testSeekDuringPlayback() throws Exception { 382 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 383 mPlayer.prepare(); 384 mPlayer.setOnCompletionListener(mCompletionListener); 385 mPlayer.start(); 386 Thread.sleep(2000); 387 mPlayer.seekTo(0); 388 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 389 Thread.sleep(200); 390 mCompletionListener.assertNoMoreCallbacks(); 391 } 392 393 public void testPlaySingleChannelLowSampleRate3gppFile() throws Exception { 394 setDataSourceFromContentProvider(mPlayer, "count_and_test.3gpp", "audio/3gpp"); 395 mPlayer.prepare(); 396 mPlayer.setOnCompletionListener(mCompletionListener); 397 mPlayer.start(); 398 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 399 } 400 401 public void testPlayTwoDifferentTypesWithSameMediaPlayer() throws Exception { 402 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 403 mPlayer.prepare(); 404 mPlayer.setOnCompletionListener(mCompletionListener); 405 mPlayer.start(); 406 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 407 mPlayer.reset(); 408 setDataSourceFromContentProvider(mPlayer, "count_and_test.3gpp", "audio/3gpp"); 409 mPlayer.prepare(); 410 mPlayer.start(); 411 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 412 } 413 414 public void testIllegalPreparingDoesntFireErrorListener() throws Exception { 415 mPlayer.setOnErrorListener(mErrorListener); 416 try { 417 mPlayer.prepare(); 418 fail("This should have thrown an IllegalStateException"); 419 } catch (IllegalStateException e) { 420 // Good, expected. 421 } 422 mErrorListener.assertNoMoreCallbacks(); 423 } 424 425 public void testSetDataSourceForMissingFile_ThrowsIOExceptionInPrepare() throws Exception { 426 mPlayer.setOnErrorListener(mErrorListener); 427 mPlayer.setDataSource("/this/file/does/not/exist/"); 428 try { 429 mPlayer.prepare(); 430 fail("Should have thrown IOException"); 431 } catch (IOException e) { 432 // Good, expected. 433 } 434 // Synchronous prepare does not report errors to the error listener. 435 mErrorListener.assertNoMoreCallbacks(); 436 } 437 438 public void testRepeatedlySeekingDuringPlayback() throws Exception { 439 // Start playback then seek repeatedly during playback to the same point. 440 // The real media player should play a stuttering audio, hopefully my player does too. 441 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 442 mPlayer.prepare(); 443 mPlayer.setOnCompletionListener(mCompletionListener); 444 mPlayer.start(); 445 Thread.sleep(500); 446 for (int i = 0; i < 40; ++i) { 447 Thread.sleep(200); 448 mPlayer.seekTo(2000); 449 } 450 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 451 } 452 453 public void testRepeatedlySeekingDuringPlaybackRandomAndVeryFast() throws Exception { 454 setDataSourceFromContentProvider(mPlayer, "quick_test_recording.mp3", "audio/mp3"); 455 mPlayer.prepare(); 456 mPlayer.setOnCompletionListener(mCompletionListener); 457 mPlayer.start(); 458 Thread.sleep(500); 459 for (int i = 0; i < 40; ++i) { 460 Thread.sleep(250); 461 mPlayer.seekTo(1500 + (int) (Math.random() * 1000)); 462 } 463 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 464 } 465 466 public void testSeekToEndThenPlayThenRateChangeCrash() throws Exception { 467 // Unit test for this bug: http://b/5140693 468 // This test proves that the bug is fixed. 469 setDataSourceFromContentProvider(mPlayer, "fake_voicemail.mp3", "audio/mp3"); 470 mPlayer.prepare(); 471 mPlayer.seekTo(mPlayer.getDuration() - 1); 472 mPlayer.setOnCompletionListener(mCompletionListener); 473 mPlayer.start(); 474 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 475 // Prior to the fix, this next line was causing a crash. 476 // The reason behind this was due to our having seeked so close to the end of the file 477 // that insufficient data was being read, and thus we weren't able to yet determine the 478 // sample rate and number of channels, which was causing an assertion failure when trying 479 // to create the time scaler. 480 setVariableSpeedRateIfSupported(1.0f); 481 } 482 483 public void testVariableSpeedRateChangeAtDifferentTimes() throws Exception { 484 // Just check that we can set the rate at any point during playback. 485 setVariableSpeedRateIfSupported(1.05f); 486 setDataSourceFromContentProvider(mPlayer, "fake_voicemail.mp3", "audio/mp3"); 487 setVariableSpeedRateIfSupported(1.10f); 488 mPlayer.prepare(); 489 setVariableSpeedRateIfSupported(1.15f); 490 mPlayer.seekTo(mPlayer.getDuration() / 2); 491 setVariableSpeedRateIfSupported(1.20f); 492 mPlayer.setOnCompletionListener(mCompletionListener); 493 setVariableSpeedRateIfSupported(1.25f); 494 mPlayer.start(); 495 setVariableSpeedRateIfSupported(1.30f); 496 mCompletionListener.awaitOneCallback(10, TimeUnit.SECONDS); 497 setVariableSpeedRateIfSupported(1.35f); 498 } 499 500 /** 501 * If we have a variable speed media player proxy, set the variable speed rate. 502 * <p> 503 * If we don't have a variable speed media player proxy, this method will be a no-op. 504 */ 505 private void setVariableSpeedRateIfSupported(float rate) { 506 if (mPlayer instanceof SingleThreadedMediaPlayerProxy) { 507 ((SingleThreadedMediaPlayerProxy) mPlayer).setVariableSpeed(rate); 508 } else if (mPlayer instanceof VariableSpeed) { 509 ((VariableSpeed) mPlayer).setVariableSpeed(rate); 510 } 511 } 512 513 /** 514 * Gets the {@link Uri} for the test audio content we should play. 515 * <p> 516 * If this is the first time we've called this method, for a given file type and mime type, then 517 * we'll have to insert some data into the content provider so that we can play it. 518 * <p> 519 * This is not thread safe, but doesn't need to be because all unit tests are executed from a 520 * single thread, sequentially. 521 */ 522 private Uri getTestContentUri(String assetFilename, String assetMimeType) throws IOException { 523 String key = keyFor(assetFilename, assetMimeType); 524 if (mContentUriMap.containsKey(key)) { 525 return mContentUriMap.get(key); 526 } 527 ContentValues values = new ContentValues(); 528 values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis())); 529 values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER); 530 values.put(VoicemailContract.Voicemails.MIME_TYPE, assetMimeType); 531 String packageName = getInstrumentation().getTargetContext().getPackageName(); 532 Uri uri = getContentResolver().insert( 533 VoicemailContract.Voicemails.buildSourceUri(packageName), values); 534 AssetManager assets = getAssets(); 535 OutputStream outputStream = null; 536 InputStream inputStream = null; 537 try { 538 inputStream = assets.open(assetFilename); 539 outputStream = getContentResolver().openOutputStream(uri); 540 copyBetweenStreams(inputStream, outputStream); 541 mContentUriMap.put(key, uri); 542 return uri; 543 } finally { 544 Closeables.closeQuietly(outputStream); 545 Closeables.closeQuietly(inputStream); 546 } 547 } 548 549 private String keyFor(String assetFilename, String assetMimeType) { 550 return assetFilename + "+" + assetMimeType; 551 } 552 553 public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException { 554 byte[] buffer = new byte[1024]; 555 int bytesRead; 556 while ((bytesRead = in.read(buffer)) != -1) { 557 out.write(buffer, 0, bytesRead); 558 } 559 } 560 561 private void cleanupContentUriIfNecessary() { 562 for (Uri uri : mContentUriMap.values()) { 563 getContentResolver().delete(uri, null, null); 564 } 565 mContentUriMap.clear(); 566 } 567 568 private void setDataSourceFromContentProvider(MediaPlayerProxy player, String assetFilename, 569 String assetMimeType) throws IOException { 570 player.setDataSource(getInstrumentation().getTargetContext(), 571 getTestContentUri(assetFilename, assetMimeType)); 572 } 573 574 private ContentResolver getContentResolver() { 575 return getInstrumentation().getContext().getContentResolver(); 576 } 577 578 private AssetManager getAssets() { 579 return getInstrumentation().getContext().getAssets(); 580 } 581} 582