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