1 /* 2 * Copyright (C) 2008 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.media.cts; 18 19 import com.android.cts.stub.R; 20 21 import dalvik.annotation.TestLevel; 22 import dalvik.annotation.TestTargetClass; 23 import dalvik.annotation.TestTargetNew; 24 import dalvik.annotation.TestTargets; 25 import dalvik.annotation.ToBeFixed; 26 27 import android.content.Context; 28 import android.content.res.AssetFileDescriptor; 29 import android.media.AudioManager; 30 import android.media.SoundPool; 31 import android.test.AndroidTestCase; 32 33 import java.io.File; 34 import java.io.FileDescriptor; 35 import java.io.FileOutputStream; 36 import java.io.InputStream; 37 38 @TestTargetClass(SoundPool.class) 39 public class SoundPoolTest extends AndroidTestCase { 40 41 private static final int SOUNDPOOL_STREAMS = 4; 42 private static final int SOUND_A = R.raw.a_4; 43 private static final int SOUND_CS = R.raw.c_sharp_5; 44 private static final int SOUND_E = R.raw.e_5; 45 private static final int SOUND_B = R.raw.b_5; 46 private static final int SOUND_GS = R.raw.g_sharp_5; 47 private static final int PRIORITY = 1; 48 private static final int LOUD = 20; 49 private static final int QUIET = LOUD / 2; 50 private static final int SILENT = 0; 51 52 private static final int[] SOUNDS = { SOUND_A, SOUND_CS, SOUND_E, SOUND_B, SOUND_GS }; 53 54 private static final String FILE_NAME = "a_4.ogg"; 55 private File mFile; 56 private SoundPool mSoundPool; 57 58 @Override 59 protected void setUp() throws Exception { 60 super.setUp(); 61 mFile = new File(mContext.getFilesDir(), FILE_NAME); 62 } 63 64 @Override 65 protected void tearDown() throws Exception { 66 super.tearDown(); 67 if (mFile.exists()) { 68 mFile.delete(); 69 } 70 if (mSoundPool != null) { 71 mSoundPool.release(); 72 mSoundPool = null; 73 return; 74 } 75 } 76 77 @TestTargets({ 78 @TestTargetNew( 79 level = TestLevel.COMPLETE, 80 method = "load", 81 args = {AssetFileDescriptor.class, int.class} 82 ), 83 @TestTargetNew( 84 level = TestLevel.COMPLETE, 85 method = "load", 86 args = {Context.class, int.class, int.class} 87 ), 88 @TestTargetNew( 89 level = TestLevel.COMPLETE, 90 method = "load", 91 args = {FileDescriptor.class, long.class, long.class, int.class} 92 ), 93 @TestTargetNew( 94 level = TestLevel.COMPLETE, 95 method = "load", 96 args = {String.class, int.class} 97 ), 98 @TestTargetNew( 99 level = TestLevel.SUFFICIENT, 100 method = "unload", 101 args = {int.class} 102 ), 103 @TestTargetNew( 104 level = TestLevel.COMPLETE, 105 method = "release", 106 args = {} 107 ) 108 }) 109 @ToBeFixed(explanation = "unload() does not return true as specified") 110 public void testLoad() throws Exception { 111 int srcQuality = 100; 112 mSoundPool = new SoundPool(SOUNDPOOL_STREAMS, AudioManager.STREAM_MUSIC, srcQuality); 113 int sampleId1 = mSoundPool.load(mContext, SOUND_A, PRIORITY); 114 waitUntilLoaded(sampleId1); 115 // should return true, but returns false 116 mSoundPool.unload(sampleId1); 117 118 AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(SOUND_CS); 119 int sampleId2; 120 sampleId2 = mSoundPool.load(afd, PRIORITY); 121 waitUntilLoaded(sampleId2); 122 mSoundPool.unload(sampleId2); 123 124 FileDescriptor fd = afd.getFileDescriptor(); 125 long offset = afd.getStartOffset(); 126 long length = afd.getLength(); 127 int sampleId3; 128 sampleId3 = mSoundPool.load(fd, offset, length, PRIORITY); 129 waitUntilLoaded(sampleId3); 130 mSoundPool.unload(sampleId3); 131 132 String path = mFile.getAbsolutePath(); 133 createSoundFile(mFile); 134 int sampleId4; 135 sampleId4 = mSoundPool.load(path, PRIORITY); 136 waitUntilLoaded(sampleId4); 137 mSoundPool.unload(sampleId4); 138 } 139 140 private void createSoundFile(File f) throws Exception { 141 FileOutputStream fOutput = null; 142 try { 143 fOutput = new FileOutputStream(f); 144 InputStream is = mContext.getResources().openRawResource(SOUND_A); 145 byte[] buffer = new byte[1024]; 146 int length = is.read(buffer); 147 while (length != -1) { 148 fOutput.write(buffer, 0, length); 149 length = is.read(buffer); 150 } 151 } finally { 152 if (fOutput != null) { 153 fOutput.flush(); 154 fOutput.close(); 155 } 156 } 157 } 158 159 @TestTargets({ 160 @TestTargetNew( 161 level = TestLevel.COMPLETE, 162 method = "load", 163 args = {Context.class, int.class, int.class} 164 ), 165 @TestTargetNew( 166 level = TestLevel.COMPLETE, 167 method = "pause", 168 args = {int.class} 169 ), 170 @TestTargetNew( 171 level = TestLevel.COMPLETE, 172 method = "play", 173 args = {int.class, float.class, float.class, int.class, int.class, float.class} 174 ), 175 @TestTargetNew( 176 level = TestLevel.COMPLETE, 177 method = "resume", 178 args = {int.class} 179 ), 180 @TestTargetNew( 181 level = TestLevel.COMPLETE, 182 method = "setLoop", 183 args = {int.class, int.class} 184 ), 185 @TestTargetNew( 186 level = TestLevel.COMPLETE, 187 method = "setPriority", 188 args = {int.class, int.class} 189 ), 190 @TestTargetNew( 191 level = TestLevel.COMPLETE, 192 method = "setRate", 193 args = {int.class, float.class} 194 ), 195 @TestTargetNew( 196 level = TestLevel.COMPLETE, 197 method = "setVolume", 198 args = {int.class, float.class, float.class} 199 ), 200 @TestTargetNew( 201 level = TestLevel.COMPLETE, 202 method = "SoundPool", 203 args = {int.class, int.class, int.class} 204 ), 205 @TestTargetNew( 206 level = TestLevel.COMPLETE, 207 method = "stop", 208 args = {int.class} 209 ) 210 }) 211 public void testSoundPoolOp() throws Exception { 212 int srcQuality = 100; 213 mSoundPool = new SoundPool(SOUNDPOOL_STREAMS, AudioManager.STREAM_MUSIC, srcQuality); 214 int sampleID = loadSampleSync(SOUND_A, PRIORITY); 215 216 int waitMsec = 1000; 217 float leftVolume = SILENT; 218 float rightVolume = LOUD; 219 int priority = 1; 220 int loop = 0; 221 float rate = 1f; 222 int streamID = mSoundPool.play(sampleID, leftVolume, rightVolume, priority, loop, rate); 223 assertTrue(streamID != 0); 224 Thread.sleep(waitMsec); 225 rate = 1.4f; 226 mSoundPool.setRate(streamID, rate); 227 Thread.sleep(waitMsec); 228 mSoundPool.setRate(streamID, 1f); 229 Thread.sleep(waitMsec); 230 mSoundPool.pause(streamID); 231 Thread.sleep(waitMsec); 232 mSoundPool.resume(streamID); 233 Thread.sleep(waitMsec); 234 mSoundPool.stop(streamID); 235 236 streamID = mSoundPool.play(sampleID, leftVolume, rightVolume, priority, loop, rate); 237 assertTrue(streamID != 0); 238 loop = -1;// loop forever 239 mSoundPool.setLoop(streamID, loop); 240 Thread.sleep(waitMsec); 241 leftVolume = SILENT; 242 rightVolume = SILENT; 243 mSoundPool.setVolume(streamID, leftVolume, rightVolume); 244 Thread.sleep(waitMsec); 245 rightVolume = LOUD; 246 mSoundPool.setVolume(streamID, leftVolume, rightVolume); 247 priority = 0; 248 mSoundPool.setPriority(streamID, priority); 249 Thread.sleep(waitMsec * 10); 250 mSoundPool.stop(streamID); 251 mSoundPool.unload(sampleID); 252 } 253 254 @TestTargets({ 255 @TestTargetNew( 256 level = TestLevel.COMPLETE, 257 method = "load", 258 args = {Context.class, int.class, int.class} 259 ), 260 @TestTargetNew( 261 level = TestLevel.COMPLETE, 262 method = "play", 263 args = {int.class, float.class, float.class, int.class, int.class, float.class} 264 ), 265 @TestTargetNew( 266 level = TestLevel.COMPLETE, 267 method = "SoundPool", 268 args = {int.class, int.class, int.class} 269 ), 270 @TestTargetNew( 271 level = TestLevel.COMPLETE, 272 method = "stop", 273 args = {int.class} 274 ) 275 }) 276 public void testMultiSound() throws Exception { 277 int srcQuality = 100; 278 mSoundPool = new SoundPool(SOUNDPOOL_STREAMS, AudioManager.STREAM_MUSIC, srcQuality); 279 int sampleID1 = loadSampleSync(SOUND_A, PRIORITY); 280 int sampleID2 = loadSampleSync(SOUND_CS, PRIORITY); 281 long waitMsec = 1000; 282 Thread.sleep(waitMsec); 283 284 // play sounds one at a time 285 int streamID1 = mSoundPool.play(sampleID1, LOUD, QUIET, PRIORITY, -1, 1); 286 assertTrue(streamID1 != 0); 287 Thread.sleep(waitMsec * 4); 288 mSoundPool.stop(streamID1); 289 int streamID2 = mSoundPool.play(sampleID2, QUIET, LOUD, PRIORITY, -1, 1); 290 assertTrue(streamID2 != 0); 291 Thread.sleep(waitMsec * 4); 292 mSoundPool.stop(streamID2); 293 294 // play both at once repeating the first, but not the second 295 streamID1 = mSoundPool.play(sampleID1, LOUD, QUIET, PRIORITY, 1, 1); 296 streamID2 = mSoundPool.play(sampleID2, QUIET, LOUD, PRIORITY, 0, 1); 297 assertTrue(streamID1 != 0); 298 assertTrue(streamID2 != 0); 299 Thread.sleep(4000); 300 // both streams should have stopped by themselves; no way to check 301 302 mSoundPool.release(); 303 mSoundPool = null; 304 } 305 306 @TestTargets({ 307 @TestTargetNew( 308 level = TestLevel.COMPLETE, 309 method = "load", 310 args = {Context.class, int.class, int.class} 311 ), 312 @TestTargetNew( 313 level = TestLevel.COMPLETE, 314 method = "SoundPool", 315 args = {int.class, int.class, int.class} 316 ) 317 }) 318 public void testLoadMore() throws Exception { 319 mSoundPool = new SoundPool(SOUNDPOOL_STREAMS, AudioManager.STREAM_MUSIC, 0); 320 int[] soundIds = new int[SOUNDS.length]; 321 int[] streamIds = new int[SOUNDS.length]; 322 for (int i = 0; i < SOUNDS.length; i++) { 323 soundIds[i] = loadSampleSync(SOUNDS[i], PRIORITY); 324 System.out.println("load: " + soundIds[i]); 325 } 326 for (int i = 0; i < soundIds.length; i++) { 327 streamIds[i] = mSoundPool.play(soundIds[i], LOUD, LOUD, PRIORITY, -1, 1); 328 } 329 Thread.sleep(3000); 330 for (int stream : streamIds) { 331 assertTrue(stream != 0); 332 mSoundPool.stop(stream); 333 } 334 for (int sound : soundIds) { 335 mSoundPool.unload(sound); 336 } 337 mSoundPool.release(); 338 } 339 340 /** 341 * Load a sample and wait until it is ready to be played. 342 * @return The sample ID. 343 * @throws InterruptedException 344 */ 345 private int loadSampleSync(int sampleId, int prio) throws InterruptedException { 346 int sample = mSoundPool.load(mContext, sampleId, prio); 347 waitUntilLoaded(sample); 348 return sample; 349 } 350 351 /** 352 * Wait until the specified sample is loaded. 353 * @param sampleId The sample ID. 354 * @throws InterruptedException 355 */ 356 private void waitUntilLoaded(int sampleId) throws InterruptedException { 357 int stream = 0; 358 while (stream == 0) { 359 Thread.sleep(500); 360 stream = mSoundPool.play(sampleId, SILENT, SILENT, 1, 0, 1); 361 } 362 mSoundPool.stop(stream); 363 } 364 } 365