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