1 /* 2 * Copyright (C) 2010 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.media.R; 20 21 import android.content.res.AssetFileDescriptor; 22 import android.media.audiofx.AudioEffect; 23 import android.media.AudioFormat; 24 import android.media.AudioManager; 25 import android.media.AudioRecord; 26 import android.media.AudioTrack; 27 import android.media.audiofx.PresetReverb; 28 import android.media.audiofx.EnvironmentalReverb; 29 import android.media.audiofx.Equalizer; 30 import android.media.MediaPlayer; 31 import android.media.MediaRecorder; 32 33 import android.os.Looper; 34 import android.test.AndroidTestCase; 35 import android.util.Log; 36 import java.util.UUID; 37 38 public class AudioEffectTest extends PostProcTestBase { 39 40 private String TAG = "AudioEffectTest"; 41 private final static int MIN_NUMBER_EFFECTS = 1; 42 // allow +/- 5% tolerance between set and get delays 43 private final static float DELAY_TOLERANCE = 1.05f; 44 // allow +/- 5% tolerance between set and get ratios 45 private final static float RATIO_TOLERANCE = 1.05f; 46 // AudioRecord sampling rate 47 private final static int SAMPLING_RATE = 44100; 48 49 private final static int MAX_LOOPER_WAIT_COUNT = 10; 50 51 private AudioEffect mEffect = null; 52 private AudioEffect mEffect2 = null; 53 private MediaPlayer mMediaPlayer = null; 54 private int mError = 0; 55 56 private ListenerThread mEffectListenerLooper = null; 57 58 //----------------------------------------------------------------- 59 // AUDIOEFFECT TESTS: 60 //---------------------------------- 61 62 //----------------------------------------------------------------- 63 // 0 - static methods 64 //---------------------------------- 65 66 //Test case 0.0: test queryEffects() and platfrom at least provides an Equalizer test0_0QueryEffects()67 public void test0_0QueryEffects() throws Exception { 68 69 AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); 70 71 assertTrue("test0_0QueryEffects: number of effects < MIN_NUMBER_EFFECTS: "+desc.length, 72 (desc.length >= MIN_NUMBER_EFFECTS)); 73 74 boolean hasEQ = false; 75 76 for (int i = 0; i < desc.length; i++) { 77 if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) { 78 hasEQ = true; 79 break; 80 } 81 } 82 assertTrue("test0_0QueryEffects: equalizer not found", hasEQ); 83 } 84 85 //----------------------------------------------------------------- 86 // 1 - constructor 87 //---------------------------------- 88 getAudioRecord()89 private AudioRecord getAudioRecord() { 90 AudioRecord ar = null; 91 try { 92 ar = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 93 SAMPLING_RATE, 94 AudioFormat.CHANNEL_CONFIGURATION_MONO, 95 AudioFormat.ENCODING_PCM_16BIT, 96 AudioRecord.getMinBufferSize(SAMPLING_RATE, 97 AudioFormat.CHANNEL_CONFIGURATION_MONO, 98 AudioFormat.ENCODING_PCM_16BIT) * 10); 99 assertNotNull("Could not create AudioRecord", ar); 100 assertEquals("AudioRecord not initialized", 101 AudioRecord.STATE_INITIALIZED, ar.getState()); 102 } catch (IllegalArgumentException e) { 103 fail("AudioRecord invalid parameter"); 104 } 105 return ar; 106 } 107 108 // // Test case 1.0: test constructor from effect type and get effect ID 109 // public void test1_0ConstructorFromType() ... 110 // Note: This test was removed because it used hidden api's. 111 112 113 // //Test case 1.1: test constructor from effect uuid 114 // public void test1_1ConstructorFromUuid() ... 115 // Note: This test was removed because: 116 // 1. will fail in devices that offload effects 117 // 2. it used hidden api's. 118 119 // //Test case 1.2: test constructor failure from unknown type 120 // public void test1_2ConstructorUnknownType() ... 121 // Note: This test was removed because it used hidden api's. 122 123 //Test case 1.3: test getEnabled() failure when called on released effect test1_3GetEnabledAfterRelease()124 public void test1_3GetEnabledAfterRelease() throws Exception { 125 try { 126 AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, 127 AudioEffect.EFFECT_TYPE_NULL, 128 0, 129 0); 130 assertNotNull("could not create AudioEffect", effect); 131 effect.release(); 132 try { 133 effect.getEnabled(); 134 fail("getEnabled() processed after release()"); 135 } catch (IllegalStateException e) { 136 137 } 138 } catch (IllegalArgumentException e) { 139 fail("AudioEffect not found"); 140 } catch (UnsupportedOperationException e) { 141 fail("Effect library not loaded"); 142 } 143 } 144 145 //Test case 1.4: test contructor on mediaPlayer audio session test1_4InsertOnMediaPlayer()146 public void test1_4InsertOnMediaPlayer() throws Exception { 147 MediaPlayer mp = new MediaPlayer(); 148 assertNotNull("could not create mediaplayer", mp); 149 AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3); 150 mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); 151 afd.close(); 152 getEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, mp.getAudioSessionId()); 153 try { 154 mEffect.setEnabled(true); 155 156 } catch (IllegalStateException e) { 157 fail("AudioEffect not initialized"); 158 } finally { 159 mp.release(); 160 releaseEffect(); 161 } 162 } 163 164 //Test case 1.5: test auxiliary effect attachement on MediaPlayer test1_5AuxiliaryOnMediaPlayer()165 public void test1_5AuxiliaryOnMediaPlayer() throws Exception { 166 if (!isPresetReverbAvailable()) { 167 return; 168 } 169 synchronized(mLock) { 170 mInitialized = false; 171 createMediaPlayerLooper(); 172 waitForLooperInitialization_l(); 173 174 mError = 0; 175 AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3); 176 mMediaPlayer.setDataSource(afd.getFileDescriptor(), 177 afd.getStartOffset(), 178 afd.getLength()); 179 afd.close(); 180 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 181 try { 182 try { 183 mMediaPlayer.attachAuxEffect(mEffect.getId()); 184 mMediaPlayer.setAuxEffectSendLevel(1.0f); 185 mLock.wait(1000); 186 } catch(Exception e) { 187 fail("Attach effect: wait was interrupted."); 188 } 189 assertTrue("error on attachAuxEffect", mError == 0); 190 } catch (IllegalStateException e) { 191 fail("attach aux effect failed"); 192 } finally { 193 terminateMediaPlayerLooper(); 194 releaseEffect(); 195 } 196 } 197 } 198 199 //Test case 1.6: test auxiliary effect attachement failure before setDatasource test1_6AuxiliaryOnMediaPlayerFailure()200 public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception { 201 if (!isPresetReverbAvailable()) { 202 return; 203 } 204 synchronized(mLock) { 205 mInitialized = false; 206 createMediaPlayerLooper(); 207 waitForLooperInitialization_l(); 208 209 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 210 211 mError = 0; 212 int looperWaitCount = MAX_LOOPER_WAIT_COUNT; 213 while (mError == 0 && (looperWaitCount-- > 0)) { 214 try { 215 try { 216 mMediaPlayer.attachAuxEffect(mEffect.getId()); 217 } catch (IllegalStateException e) { 218 terminateMediaPlayerLooper(); 219 releaseEffect(); 220 fail("attach aux effect failed"); 221 } 222 mLock.wait(); 223 } catch(Exception e) { 224 } 225 } 226 assertTrue("no error on attachAuxEffect", mError != 0); 227 } 228 terminateMediaPlayerLooper(); 229 releaseEffect(); 230 } 231 232 233 //Test case 1.7: test auxiliary effect attachement on AudioTrack test1_7AuxiliaryOnAudioTrack()234 public void test1_7AuxiliaryOnAudioTrack() throws Exception { 235 if (!isPresetReverbAvailable()) { 236 return; 237 } 238 AudioTrack track = null; 239 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 240 try { 241 track = new AudioTrack( 242 AudioManager.STREAM_MUSIC, 243 44100, 244 AudioFormat.CHANNEL_OUT_MONO, 245 AudioFormat.ENCODING_PCM_16BIT, 246 AudioTrack.getMinBufferSize(44100, 247 AudioFormat.CHANNEL_OUT_MONO, 248 AudioFormat.ENCODING_PCM_16BIT), 249 AudioTrack.MODE_STREAM); 250 assertNotNull("could not create AudioTrack", track); 251 252 int status = track.attachAuxEffect(mEffect.getId()); 253 if (status != AudioTrack.SUCCESS) { 254 fail("could not attach aux effect"); 255 } 256 status = track.setAuxEffectSendLevel(1.0f); 257 if (status != AudioTrack.SUCCESS) { 258 fail("could not set send level"); 259 } 260 } catch (IllegalStateException e) { 261 fail("could not attach aux effect"); 262 } catch (IllegalArgumentException e) { 263 fail("could not create AudioTrack"); 264 } finally { 265 if (track != null) { 266 track.release(); 267 } 268 releaseEffect(); 269 } 270 } 271 272 //----------------------------------------------------------------- 273 // 2 - enable/ disable 274 //---------------------------------- 275 276 277 //Test case 2.0: test setEnabled() and getEnabled() in valid state test2_0SetEnabledGetEnabled()278 public void test2_0SetEnabledGetEnabled() throws Exception { 279 try { 280 AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, 281 AudioEffect.EFFECT_TYPE_NULL, 282 0, 283 0); 284 assertNotNull("could not create AudioEffect", effect); 285 try { 286 effect.setEnabled(true); 287 assertTrue("invalid state from getEnabled", effect.getEnabled()); 288 effect.setEnabled(false); 289 assertFalse("invalid state to getEnabled", effect.getEnabled()); 290 291 } catch (IllegalStateException e) { 292 fail("setEnabled() in wrong state"); 293 } finally { 294 effect.release(); 295 } 296 } catch (IllegalArgumentException e) { 297 fail("AudioEffect not found"); 298 299 } catch (UnsupportedOperationException e) { 300 fail("Effect library not loaded"); 301 } 302 } 303 304 //Test case 2.1: test setEnabled() throws exception after release test2_1SetEnabledAfterRelease()305 public void test2_1SetEnabledAfterRelease() throws Exception { 306 try { 307 AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, 308 AudioEffect.EFFECT_TYPE_NULL, 309 0, 310 0); 311 assertNotNull("could not create AudioEffect", effect); 312 effect.release(); 313 try { 314 effect.setEnabled(true); 315 fail("setEnabled() processed after release"); 316 } catch (IllegalStateException e) { 317 // test passed 318 } 319 } catch (IllegalArgumentException e) { 320 fail("AudioEffect not found"); 321 } catch (UnsupportedOperationException e) { 322 fail("Effect library not loaded"); 323 } 324 } 325 326 //----------------------------------------------------------------- 327 // 3 - set/get parameters 328 //---------------------------------- 329 330 //Test case 3.0: test setParameter(byte[], byte[]) / getParameter(byte[], byte[]) test3_0SetParameterByteArrayByteArray()331 public void test3_0SetParameterByteArrayByteArray() throws Exception { 332 if (!isPresetReverbAvailable()) { 333 return; 334 } 335 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 336 try { 337 byte[] param = mEffect.intToByteArray(PresetReverb.PARAM_PRESET); 338 byte[] value = new byte[2]; 339 int status = mEffect.getParameter(param, value); 340 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 341 short preset = PresetReverb.PRESET_SMALLROOM; 342 if (mEffect.byteArrayToShort(value) == preset) { 343 preset = PresetReverb.PRESET_MEDIUMROOM; 344 } 345 value = mEffect.shortToByteArray(preset); 346 status = mEffect.setParameter(param, value); 347 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 348 status = mEffect.getParameter(param, value); 349 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 350 assertEquals("get/set Parameter failed", preset, 351 mEffect.byteArrayToShort(value)); 352 353 } catch (IllegalArgumentException e) { 354 fail("Bad parameter value"); 355 } catch (UnsupportedOperationException e) { 356 fail("setParameter() rejected"); 357 } catch (IllegalStateException e) { 358 fail("setParameter() called in wrong state"); 359 } finally { 360 releaseEffect(); 361 } 362 } 363 364 //Test case 3.1: test setParameter(int, int) / getParameter(int, int[]) test3_1SetParameterIntInt()365 public void test3_1SetParameterIntInt() throws Exception { 366 if (!isEnvReverbAvailable()) { 367 return; 368 } 369 getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0); 370 try { 371 int param = EnvironmentalReverb.PARAM_DECAY_TIME; 372 int[] value = new int[1]; 373 int status = mEffect.getParameter(param, value); 374 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 375 int time = 500; 376 if (value[0] == time) { 377 time = 1000; 378 } 379 status = mEffect.setParameter(param, time); 380 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 381 status = mEffect.getParameter(param, value); 382 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 383 assertTrue("got incorrect decay time", 384 ((float)value[0] > (float)(time / DELAY_TOLERANCE)) && 385 ((float)value[0] < (float)(time * DELAY_TOLERANCE))); 386 387 } catch (IllegalArgumentException e) { 388 fail("Bad parameter value"); 389 } catch (UnsupportedOperationException e) { 390 fail("setParameter() rejected"); 391 } catch (IllegalStateException e) { 392 fail("setParameter() called in wrong state"); 393 } finally { 394 releaseEffect(); 395 } 396 } 397 398 //Test case 3.2: test setParameter(int, short) / getParameter(int, short[]) test3_2SetParameterIntShort()399 public void test3_2SetParameterIntShort() throws Exception { 400 if (!isPresetReverbAvailable()) { 401 return; 402 } 403 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 404 try { 405 int param = PresetReverb.PARAM_PRESET; 406 short[] value = new short[1]; 407 int status = mEffect.getParameter(param, value); 408 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 409 short preset = PresetReverb.PRESET_SMALLROOM; 410 if (value[0] == preset) { 411 preset = PresetReverb.PRESET_MEDIUMROOM; 412 } 413 status = mEffect.setParameter(param, preset); 414 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 415 status = mEffect.getParameter(param, value); 416 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 417 assertEquals("get/set Parameter failed", preset, value[0]); 418 419 } catch (IllegalArgumentException e) { 420 fail("Bad parameter value"); 421 } catch (UnsupportedOperationException e) { 422 fail("setParameter() rejected"); 423 } catch (IllegalStateException e) { 424 fail("setParameter() called in wrong state"); 425 } finally { 426 releaseEffect(); 427 } 428 } 429 430 //Test case 3.3: test setParameter(int, byte[]) / getParameter(int, byte[]) test3_3SetParameterIntByteArray()431 public void test3_3SetParameterIntByteArray() throws Exception { 432 if (!isEnvReverbAvailable()) { 433 return; 434 } 435 getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0); 436 try { 437 int param = EnvironmentalReverb.PARAM_DECAY_TIME; 438 byte[] value = new byte[4]; 439 int status = mEffect.getParameter(param, value); 440 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 441 int time = 500; 442 if (mEffect.byteArrayToInt(value) == time) { 443 time = 1000; 444 } 445 value = mEffect.intToByteArray(time); 446 status = mEffect.setParameter(param, value); 447 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 448 status = mEffect.getParameter(param, value); 449 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 450 int time2 = mEffect.byteArrayToInt(value); 451 assertTrue("got incorrect decay time", 452 ((float)time2 > (float)(time / DELAY_TOLERANCE)) && 453 ((float)time2 < (float)(time * DELAY_TOLERANCE))); 454 455 } catch (IllegalArgumentException e) { 456 fail("Bad parameter value"); 457 } catch (UnsupportedOperationException e) { 458 fail("setParameter() rejected"); 459 } catch (IllegalStateException e) { 460 fail("setParameter() called in wrong state"); 461 } finally { 462 releaseEffect(); 463 } 464 } 465 466 //Test case 3.4: test setParameter(int[], int[]) / getParameter(int[], int[]) test3_4SetParameterIntArrayIntArray()467 public void test3_4SetParameterIntArrayIntArray() throws Exception { 468 if (!isEnvReverbAvailable()) { 469 return; 470 } 471 getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0); 472 try { 473 int[] param = new int[1]; 474 int[] value = new int[1]; 475 param[0] = EnvironmentalReverb.PARAM_DECAY_TIME; 476 int status = mEffect.getParameter(param, value); 477 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 478 int[] time = new int[1]; 479 time[0] = 500; 480 if (value[0] == time[0]) { 481 time[0] = 1000; 482 } 483 status = mEffect.setParameter(param, time); 484 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 485 status = mEffect.getParameter(param, value); 486 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 487 assertTrue("got incorrect decay time", 488 ((float)value[0] > (float)(time[0] / DELAY_TOLERANCE)) && 489 ((float)value[0] < (float)(time[0] * DELAY_TOLERANCE))); 490 491 } catch (IllegalArgumentException e) { 492 fail("Bad parameter value"); 493 } catch (UnsupportedOperationException e) { 494 fail("setParameter() rejected"); 495 } catch (IllegalStateException e) { 496 fail("setParameter() called in wrong state"); 497 } finally { 498 releaseEffect(); 499 } 500 } 501 502 //Test case 3.5: test setParameter(int[], short[]) / getParameter(int[], short[]) 503 test3_5SetParameterIntArrayShortArray()504 public void test3_5SetParameterIntArrayShortArray() throws Exception { 505 if (!isPresetReverbAvailable()) { 506 return; 507 } 508 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 509 try { 510 int[] param = new int[1]; 511 param[0] = PresetReverb.PARAM_PRESET; 512 short[] value = new short[1]; 513 int status = mEffect.getParameter(param, value); 514 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 515 short[] preset = new short[1]; 516 preset[0] = PresetReverb.PRESET_SMALLROOM; 517 if (value[0] == preset[0]) { 518 preset[0] = PresetReverb.PRESET_MEDIUMROOM; 519 } 520 status = mEffect.setParameter(param, preset); 521 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 522 status = mEffect.getParameter(param, value); 523 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 524 assertEquals("get/set Parameter failed", preset[0], value[0]); 525 526 } catch (IllegalArgumentException e) { 527 fail("Bad parameter value"); 528 } catch (UnsupportedOperationException e) { 529 fail("setParameter() rejected"); 530 } catch (IllegalStateException e) { 531 fail("setParameter() called in wrong state"); 532 } finally { 533 releaseEffect(); 534 } 535 } 536 537 //Test case 3.6: test setParameter(int[], byte[]) / getParameter(int[], byte[]) test3_6SetParameterIntArrayByteArray()538 public void test3_6SetParameterIntArrayByteArray() throws Exception { 539 if (!isEnvReverbAvailable()) { 540 return; 541 } 542 getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0); 543 try { 544 int[] param = new int[1]; 545 param[0] = EnvironmentalReverb.PARAM_DECAY_TIME; 546 byte[] value = new byte[4]; 547 int status = mEffect.getParameter(param, value); 548 assertFalse("getParameter 1 failed", AudioEffect.isError(status)); 549 int time = 500; 550 if (mEffect.byteArrayToInt(value) == time) { 551 time = 1000; 552 } 553 554 status = mEffect.setParameter(param, mEffect.intToByteArray(time)); 555 assertEquals("setParameter failed", AudioEffect.SUCCESS, status); 556 status = mEffect.getParameter(param, value); 557 assertFalse("getParameter 2 failed", AudioEffect.isError(status)); 558 int time2 = mEffect.byteArrayToInt(value); 559 assertTrue("got incorrect decay time", 560 ((float)time2 > (float)(time / DELAY_TOLERANCE)) && 561 ((float)time2 < (float)(time * DELAY_TOLERANCE))); 562 563 } catch (IllegalArgumentException e) { 564 fail("Bad parameter value"); 565 } catch (UnsupportedOperationException e) { 566 fail("setParameter() rejected"); 567 } catch (IllegalStateException e) { 568 fail("setParameter() called in wrong state"); 569 } finally { 570 releaseEffect(); 571 } 572 } 573 574 //Test case 3.7: test setParameter() throws exception after release() test3_7SetParameterAfterRelease()575 public void test3_7SetParameterAfterRelease() throws Exception { 576 if (!isPresetReverbAvailable()) { 577 return; 578 } 579 AudioEffect effect = null; 580 try { 581 effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 582 AudioEffect.EFFECT_TYPE_NULL, 583 0, 584 0); 585 assertNotNull("could not create AudioEffect", effect); 586 effect.release(); 587 effect.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_SMALLROOM); 588 fail("setParameter() processed after release"); 589 } catch (IllegalArgumentException e) { 590 fail("Bad parameter value"); 591 } catch (UnsupportedOperationException e) { 592 fail("setParameter() rejected"); 593 } catch (IllegalStateException e) { 594 // test passed 595 } finally { 596 if (effect != null) { 597 effect.release(); 598 } 599 } 600 } 601 602 //Test case 3.8: test getParameter() throws exception after release() test3_8GetParameterAfterRelease()603 public void test3_8GetParameterAfterRelease() throws Exception { 604 if (!isPresetReverbAvailable()) { 605 return; 606 } 607 AudioEffect effect = null; 608 try { 609 effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 610 AudioEffect.EFFECT_TYPE_NULL, 611 0, 612 0); 613 assertNotNull("could not create AudioEffect", effect); 614 effect.release(); 615 short[] value = new short[1]; 616 effect.getParameter(PresetReverb.PARAM_PRESET, value); 617 fail("getParameter() processed after release"); 618 } catch (IllegalArgumentException e) { 619 fail("Bad parameter value"); 620 } catch (UnsupportedOperationException e) { 621 fail("getParameter() rejected"); 622 } catch (IllegalStateException e) { 623 // test passed 624 } finally { 625 if (effect != null) { 626 effect.release(); 627 } 628 } 629 } 630 631 //----------------------------------------------------------------- 632 // 4 priority and listeners 633 //---------------------------------- 634 635 //Test case 4.0: test control passed to higher priority client test4_0setEnabledLowerPriority()636 public void test4_0setEnabledLowerPriority() throws Exception { 637 AudioEffect effect1 = null; 638 AudioEffect effect2 = null; 639 try { 640 effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, 641 AudioEffect.EFFECT_TYPE_NULL, 642 0, 643 0); 644 effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, 645 AudioEffect.EFFECT_TYPE_NULL, 646 1, 647 0); 648 649 assertNotNull("could not create AudioEffect", effect1); 650 assertNotNull("could not create AudioEffect", effect2); 651 652 assertTrue("Effect2 does not have control", effect2.hasControl()); 653 assertFalse("Effect1 has control", effect1.hasControl()); 654 assertTrue("Effect1 can enable", 655 effect1.setEnabled(true) == AudioEffect.ERROR_INVALID_OPERATION); 656 assertFalse("Effect1 has enabled", effect2.getEnabled()); 657 658 } catch (IllegalArgumentException e) { 659 fail("Effect not found"); 660 } catch (UnsupportedOperationException e) { 661 fail("Effect library not loaded"); 662 } finally { 663 if (effect1 != null) { 664 effect1.release(); 665 } 666 if (effect2 != null) { 667 effect2.release(); 668 } 669 } 670 } 671 672 //Test case 4.1: test control passed to higher priority client test4_1setParameterLowerPriority()673 public void test4_1setParameterLowerPriority() throws Exception { 674 if (!isPresetReverbAvailable()) { 675 return; 676 } 677 AudioEffect effect1 = null; 678 AudioEffect effect2 = null; 679 try { 680 effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 681 AudioEffect.EFFECT_TYPE_NULL, 682 0, 683 0); 684 effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 685 AudioEffect.EFFECT_TYPE_NULL, 686 1, 687 0); 688 689 assertNotNull("could not create AudioEffect", effect1); 690 assertNotNull("could not create AudioEffect", effect2); 691 692 int status = effect2.setParameter(PresetReverb.PARAM_PRESET, 693 PresetReverb.PRESET_SMALLROOM); 694 assertEquals("Effect2 setParameter failed", 695 AudioEffect.SUCCESS, status); 696 697 status = effect1.setParameter(PresetReverb.PARAM_PRESET, 698 PresetReverb.PRESET_MEDIUMROOM); 699 assertEquals("Effect1 setParameter did not fail", 700 AudioEffect.ERROR_INVALID_OPERATION, status); 701 702 short[] value = new short[1]; 703 status = effect2.getParameter(PresetReverb.PARAM_PRESET, value); 704 assertFalse("Effect2 getParameter failed", 705 AudioEffect.isError(status)); 706 assertEquals("Effect1 changed parameter", PresetReverb.PRESET_SMALLROOM 707 , value[0]); 708 709 710 } catch (IllegalArgumentException e) { 711 fail("Effect not found"); 712 } catch (UnsupportedOperationException e) { 713 fail("Effect library not loaded"); 714 } finally { 715 if (effect1 != null) { 716 effect1.release(); 717 } 718 if (effect2 != null) { 719 effect2.release(); 720 } 721 } 722 } 723 724 //Test case 4.2: test control status listener test4_2ControlStatusListener()725 public void test4_2ControlStatusListener() throws Exception { 726 if (!isPresetReverbAvailable()) { 727 return; 728 } 729 synchronized(mLock) { 730 mHasControl = true; 731 mInitialized = false; 732 createListenerLooper(true, false, false); 733 waitForLooperInitialization_l(); 734 735 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 736 int looperWaitCount = MAX_LOOPER_WAIT_COUNT; 737 while (mHasControl && (looperWaitCount-- > 0)) { 738 try { 739 mLock.wait(); 740 } catch(Exception e) { 741 } 742 } 743 terminateListenerLooper(); 744 releaseEffect(); 745 } 746 assertFalse("effect control not lost by effect1", mHasControl); 747 } 748 749 //Test case 4.3: test enable status listener test4_3EnableStatusListener()750 public void test4_3EnableStatusListener() throws Exception { 751 if (!isPresetReverbAvailable()) { 752 return; 753 } 754 synchronized(mLock) { 755 mInitialized = false; 756 createListenerLooper(false, true, false); 757 waitForLooperInitialization_l(); 758 759 mEffect2.setEnabled(true); 760 mIsEnabled = true; 761 762 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 763 assertTrue("effect not enabled", mEffect.getEnabled()); 764 int looperWaitCount = MAX_LOOPER_WAIT_COUNT; 765 while (mIsEnabled && (looperWaitCount-- > 0)) { 766 try { 767 mEffect.setEnabled(false); 768 mLock.wait(); 769 } catch(Exception e) { 770 } 771 } 772 terminateListenerLooper(); 773 releaseEffect(); 774 } 775 assertFalse("enable status not updated", mIsEnabled); 776 } 777 778 //Test case 4.4: test parameter changed listener test4_4ParameterChangedListener()779 public void test4_4ParameterChangedListener() throws Exception { 780 if (!isPresetReverbAvailable()) { 781 return; 782 } 783 synchronized(mLock) { 784 mInitialized = false; 785 createListenerLooper(false, false, true); 786 waitForLooperInitialization_l(); 787 int status = mEffect2.setParameter(PresetReverb.PARAM_PRESET, 788 PresetReverb.PRESET_SMALLROOM); 789 assertEquals("mEffect2 setParameter failed", 790 AudioEffect.SUCCESS, status); 791 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 792 mChangedParameter = -1; 793 mEffect.setParameter(PresetReverb.PARAM_PRESET, 794 PresetReverb.PRESET_MEDIUMROOM); 795 int looperWaitCount = MAX_LOOPER_WAIT_COUNT; 796 while (mChangedParameter == -1 && (looperWaitCount-- > 0)) { 797 try { 798 mLock.wait(); 799 } catch(Exception e) { 800 } 801 } 802 terminateListenerLooper(); 803 releaseEffect(); 804 } 805 assertEquals("parameter change not received", 806 PresetReverb.PARAM_PRESET, mChangedParameter); 807 } 808 809 //----------------------------------------------------------------- 810 // 5 command method 811 //---------------------------------- 812 813 814 //Test case 5.0: test command method test5_0Command()815 public void test5_0Command() throws Exception { 816 if (!isPresetReverbAvailable()) { 817 return; 818 } 819 getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0); 820 try { 821 byte[] cmd = new byte[0]; 822 byte[] reply = new byte[4]; 823 // command 3 is ENABLE 824 int status = mEffect.command(3, cmd, reply); 825 assertFalse("command failed", AudioEffect.isError(status)); 826 assertTrue("effect not enabled", mEffect.getEnabled()); 827 828 } catch (IllegalStateException e) { 829 fail("command in illegal state"); 830 } finally { 831 releaseEffect(); 832 } 833 } 834 835 836 //----------------------------------------------------------------- 837 // private methods 838 //---------------------------------- 839 getEffect(UUID type, int session)840 private void getEffect(UUID type, int session) { 841 if (mEffect == null || session != mSession) { 842 if (session != mSession && mEffect != null) { 843 mEffect.release(); 844 mEffect = null; 845 } 846 try { 847 mEffect = new AudioEffect(type, 848 AudioEffect.EFFECT_TYPE_NULL, 849 0, 850 session); 851 mSession = session; 852 } catch (IllegalArgumentException e) { 853 Log.e(TAG, "getEffect() AudioEffect not found exception: "+e); 854 } catch (UnsupportedOperationException e) { 855 Log.e(TAG, "getEffect() Effect library not loaded exception: "+e); 856 } 857 } 858 assertNotNull("could not create mEffect", mEffect); 859 } 860 releaseEffect()861 private void releaseEffect() { 862 if (mEffect != null) { 863 mEffect.release(); 864 mEffect = null; 865 } 866 } 867 waitForLooperInitialization_l()868 private void waitForLooperInitialization_l() { 869 int looperWaitCount = MAX_LOOPER_WAIT_COUNT; 870 while (!mInitialized && (looperWaitCount-- > 0)) { 871 try { 872 mLock.wait(); 873 } catch(Exception e) { 874 } 875 } 876 assertTrue(mInitialized); 877 } 878 879 // Initializes the equalizer listener looper 880 class ListenerThread extends Thread { 881 boolean mControl; 882 boolean mEnable; 883 boolean mParameter; 884 ListenerThread(boolean control, boolean enable, boolean parameter)885 public ListenerThread(boolean control, boolean enable, boolean parameter) { 886 super(); 887 mControl = control; 888 mEnable = enable; 889 mParameter = parameter; 890 } 891 cleanUp()892 public void cleanUp() { 893 if (mEffect2 != null) { 894 mEffect2.setControlStatusListener(null); 895 mEffect2.setEnableStatusListener(null); 896 mEffect2.setParameterListener(null); 897 } 898 } 899 } 900 createListenerLooper(boolean control, boolean enable, boolean parameter)901 private void createListenerLooper(boolean control, boolean enable, boolean parameter) { 902 mEffectListenerLooper = new ListenerThread(control, enable, parameter) { 903 @Override 904 public void run() { 905 // Set up a looper 906 Looper.prepare(); 907 908 // Save the looper so that we can terminate this thread 909 // after we are done with it. 910 mLooper = Looper.myLooper(); 911 912 mEffect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 913 AudioEffect.EFFECT_TYPE_NULL, 914 0, 915 0); 916 assertNotNull("could not create Equalizer2", mEffect2); 917 918 synchronized(mLock) { 919 if (mControl) { 920 mEffect2.setControlStatusListener( 921 new AudioEffect.OnControlStatusChangeListener() { 922 public void onControlStatusChange( 923 AudioEffect effect, boolean controlGranted) { 924 synchronized(mLock) { 925 if (effect == mEffect2) { 926 mHasControl = controlGranted; 927 mLock.notify(); 928 } 929 } 930 } 931 }); 932 } 933 if (mEnable) { 934 mEffect2.setEnableStatusListener( 935 new AudioEffect.OnEnableStatusChangeListener() { 936 public void onEnableStatusChange(AudioEffect effect, boolean enabled) { 937 synchronized(mLock) { 938 if (effect == mEffect2) { 939 mIsEnabled = enabled; 940 mLock.notify(); 941 } 942 } 943 } 944 }); 945 } 946 if (mParameter) { 947 mEffect2.setParameterListener(new AudioEffect.OnParameterChangeListener() { 948 public void onParameterChange(AudioEffect effect, int status, byte[] param, 949 byte[] value) 950 { 951 synchronized(mLock) { 952 if (effect == mEffect2) { 953 mChangedParameter = mEffect2.byteArrayToInt(param); 954 mLock.notify(); 955 } 956 } 957 } 958 }); 959 } 960 mInitialized = true; 961 mLock.notify(); 962 } 963 Looper.loop(); // Blocks forever until Looper.quit() is called. 964 } 965 }; 966 mEffectListenerLooper.start(); 967 } 968 969 // Terminates the listener looper thread. terminateListenerLooper()970 private void terminateListenerLooper() { 971 if (mEffectListenerLooper != null) { 972 mEffectListenerLooper.cleanUp(); 973 if (mLooper != null) { 974 mLooper.quit(); 975 mLooper = null; 976 } 977 try { 978 mEffectListenerLooper.join(); 979 } catch(InterruptedException e) { 980 } 981 mEffectListenerLooper = null; 982 } 983 if (mEffect2 != null) { 984 mEffect2.release(); 985 mEffect2 = null; 986 } 987 } 988 989 /* 990 * Initializes the message looper so that the MediaPlayer object can 991 * receive the callback messages. 992 */ createMediaPlayerLooper()993 private void createMediaPlayerLooper() { 994 new Thread() { 995 @Override 996 public void run() { 997 // Set up a looper to be used by mMediaPlayer. 998 Looper.prepare(); 999 1000 // Save the looper so that we can terminate this thread 1001 // after we are done with it. 1002 mLooper = Looper.myLooper(); 1003 1004 mMediaPlayer = new MediaPlayer(); 1005 1006 synchronized(mLock) { 1007 mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { 1008 public boolean onError(MediaPlayer player, int what, int extra) { 1009 synchronized(mLock) { 1010 mError = what; 1011 mLock.notify(); 1012 } 1013 return true; 1014 } 1015 }); 1016 mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 1017 public void onCompletion(MediaPlayer player) { 1018 synchronized(mLock) { 1019 mLock.notify(); 1020 } 1021 } 1022 }); 1023 mInitialized = true; 1024 mLock.notify(); 1025 } 1026 Looper.loop(); // Blocks forever until Looper.quit() is called. 1027 } 1028 }.start(); 1029 } 1030 /* 1031 * Terminates the message looper thread. 1032 */ terminateMediaPlayerLooper()1033 private void terminateMediaPlayerLooper() { 1034 if (mLooper != null) { 1035 mLooper.quit(); 1036 mLooper = null; 1037 } 1038 if (mMediaPlayer != null) { 1039 mMediaPlayer.release(); 1040 } 1041 } 1042 1043 } 1044