/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.cts;

import com.android.cts.media.R;

import android.content.res.AssetFileDescriptor;
import android.media.audiofx.AudioEffect;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.EnvironmentalReverb;
import android.media.audiofx.Equalizer;
import android.media.MediaPlayer;
import android.media.MediaRecorder;

import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.Log;
import java.util.UUID;

public class AudioEffectTest extends PostProcTestBase {

    private String TAG = "AudioEffectTest";
    private final static int MIN_NUMBER_EFFECTS = 1;
    // allow +/- 5% tolerance between set and get delays
    private final static float DELAY_TOLERANCE = 1.05f;
    // allow +/- 5% tolerance between set and get ratios
    private final static float RATIO_TOLERANCE = 1.05f;
    // AudioRecord sampling rate
    private final static int SAMPLING_RATE = 44100;

    private final static int MAX_LOOPER_WAIT_COUNT = 10;

    private AudioEffect mEffect = null;
    private AudioEffect mEffect2 = null;
    private MediaPlayer mMediaPlayer = null;
    private int mError = 0;

    private ListenerThread mEffectListenerLooper = null;

    //-----------------------------------------------------------------
    // AUDIOEFFECT TESTS:
    //----------------------------------

    //-----------------------------------------------------------------
    // 0 - static methods
    //----------------------------------

    //Test case 0.0: test queryEffects() and platfrom at least provides an Equalizer
    public void test0_0QueryEffects() throws Exception {

        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();

        assertTrue("test0_0QueryEffects: number of effects < MIN_NUMBER_EFFECTS: "+desc.length,
                (desc.length >= MIN_NUMBER_EFFECTS));

        boolean hasEQ = false;

        for (int i = 0; i < desc.length; i++) {
            if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
                hasEQ = true;
                break;
            }
        }
        assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
    }

    //-----------------------------------------------------------------
    // 1 - constructor
    //----------------------------------

    private AudioRecord getAudioRecord() {
        AudioRecord ar = null;
        try {
            ar = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
                    SAMPLING_RATE,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    AudioRecord.getMinBufferSize(SAMPLING_RATE,
                            AudioFormat.CHANNEL_CONFIGURATION_MONO,
                            AudioFormat.ENCODING_PCM_16BIT) * 10);
            assertNotNull("Could not create AudioRecord", ar);
            assertEquals("AudioRecord not initialized",
                    AudioRecord.STATE_INITIALIZED, ar.getState());
        } catch (IllegalArgumentException e) {
            fail("AudioRecord invalid parameter");
        }
        return ar;
    }

//    // Test case 1.0: test constructor from effect type and get effect ID
//    public void test1_0ConstructorFromType() ...
//    Note: This test was removed because it used hidden api's.


//    //Test case 1.1: test constructor from effect uuid
//    public void test1_1ConstructorFromUuid() ...
//    Note: This test was removed because:
//     1. will fail in devices that offload effects
//     2. it used hidden api's.

//    //Test case 1.2: test constructor failure from unknown type
//    public void test1_2ConstructorUnknownType() ...
//    Note: This test was removed because it used hidden api's.

    //Test case 1.3: test getEnabled() failure when called on released effect
    public void test1_3GetEnabledAfterRelease() throws Exception {
        try {
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);
            assertNotNull("could not create AudioEffect", effect);
            effect.release();
            try {
                effect.getEnabled();
                fail("getEnabled() processed after release()");
            } catch (IllegalStateException e) {

            }
        } catch (IllegalArgumentException e) {
            fail("AudioEffect not found");
        } catch (UnsupportedOperationException e) {
            fail("Effect library not loaded");
        }
    }

    //Test case 1.4: test contructor on mediaPlayer audio session
    public void test1_4InsertOnMediaPlayer() throws Exception {
        MediaPlayer mp = new MediaPlayer();
        assertNotNull("could not create mediaplayer", mp);
        AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        afd.close();
        getEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, mp.getAudioSessionId());
        try {
            mEffect.setEnabled(true);

        } catch (IllegalStateException e) {
            fail("AudioEffect not initialized");
        } finally {
            mp.release();
            releaseEffect();
        }
    }

    //Test case 1.5: test auxiliary effect attachement on MediaPlayer
    public void test1_5AuxiliaryOnMediaPlayer() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        synchronized(mLock) {
            mInitialized = false;
            createMediaPlayerLooper();
            waitForLooperInitialization_l();

            mError = 0;
            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
            mMediaPlayer.setDataSource(afd.getFileDescriptor(),
                                       afd.getStartOffset(),
                                       afd.getLength());
            afd.close();
            getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
            try {
                try {
                    mMediaPlayer.attachAuxEffect(mEffect.getId());
                    mMediaPlayer.setAuxEffectSendLevel(1.0f);
                    mLock.wait(1000);
                } catch(Exception e) {
                    fail("Attach effect: wait was interrupted.");
                }
                assertTrue("error on attachAuxEffect", mError == 0);
            } catch (IllegalStateException e) {
                fail("attach aux effect failed");
            } finally {
                terminateMediaPlayerLooper();
                releaseEffect();
            }
        }
    }

    //Test case 1.6: test auxiliary effect attachement failure before setDatasource
    public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        synchronized(mLock) {
            mInitialized = false;
            createMediaPlayerLooper();
            waitForLooperInitialization_l();

            getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);

            mError = 0;
            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
            while (mError == 0 && (looperWaitCount-- > 0)) {
                try {
                    try {
                        mMediaPlayer.attachAuxEffect(mEffect.getId());
                    } catch (IllegalStateException e) {
                        terminateMediaPlayerLooper();
                        releaseEffect();
                        fail("attach aux effect failed");
                    }
                    mLock.wait();
                } catch(Exception e) {
                }
            }
            assertTrue("no error on attachAuxEffect", mError != 0);
        }
        terminateMediaPlayerLooper();
        releaseEffect();
    }


    //Test case 1.7: test auxiliary effect attachement on AudioTrack
    public void test1_7AuxiliaryOnAudioTrack() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        AudioTrack track = null;
        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
        try {
            track = new AudioTrack(
                                AudioManager.STREAM_MUSIC,
                                44100,
                                AudioFormat.CHANNEL_OUT_MONO,
                                AudioFormat.ENCODING_PCM_16BIT,
                                AudioTrack.getMinBufferSize(44100,
                                                            AudioFormat.CHANNEL_OUT_MONO,
                                                            AudioFormat.ENCODING_PCM_16BIT),
                                                            AudioTrack.MODE_STREAM);
            assertNotNull("could not create AudioTrack", track);

            int status = track.attachAuxEffect(mEffect.getId());
            if (status != AudioTrack.SUCCESS) {
                fail("could not attach aux effect");
            }
            status = track.setAuxEffectSendLevel(1.0f);
            if (status != AudioTrack.SUCCESS) {
                fail("could not set send level");
            }
        } catch (IllegalStateException e) {
            fail("could not attach aux effect");
        } catch (IllegalArgumentException e) {
            fail("could not create AudioTrack");
        } finally {
            if (track != null) {
                track.release();
            }
            releaseEffect();
        }
    }

    //-----------------------------------------------------------------
    // 2 - enable/ disable
    //----------------------------------


    //Test case 2.0: test setEnabled() and getEnabled() in valid state
    public void test2_0SetEnabledGetEnabled() throws Exception {
        try {
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);
            assertNotNull("could not create AudioEffect", effect);
            try {
                effect.setEnabled(true);
                assertTrue("invalid state from getEnabled", effect.getEnabled());
                effect.setEnabled(false);
                assertFalse("invalid state to getEnabled", effect.getEnabled());

            } catch (IllegalStateException e) {
                fail("setEnabled() in wrong state");
            } finally {
                effect.release();
            }
        } catch (IllegalArgumentException e) {
            fail("AudioEffect not found");

        } catch (UnsupportedOperationException e) {
            fail("Effect library not loaded");
        }
    }

    //Test case 2.1: test setEnabled() throws exception after release
    public void test2_1SetEnabledAfterRelease() throws Exception {
        try {
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);
            assertNotNull("could not create AudioEffect", effect);
            effect.release();
            try {
                effect.setEnabled(true);
                fail("setEnabled() processed after release");
            } catch (IllegalStateException e) {
                // test passed
            }
        } catch (IllegalArgumentException e) {
            fail("AudioEffect not found");
        } catch (UnsupportedOperationException e) {
            fail("Effect library not loaded");
        }
    }

    //-----------------------------------------------------------------
    // 3 - set/get parameters
    //----------------------------------

    //Test case 3.0: test setParameter(byte[], byte[]) / getParameter(byte[], byte[])
    public void test3_0SetParameterByteArrayByteArray() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
        try {
            byte[] param = mEffect.intToByteArray(PresetReverb.PARAM_PRESET);
            byte[] value = new byte[2];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            short preset = PresetReverb.PRESET_SMALLROOM;
            if (mEffect.byteArrayToShort(value) == preset) {
                preset = PresetReverb.PRESET_MEDIUMROOM;
            }
            value = mEffect.shortToByteArray(preset);
            status = mEffect.setParameter(param, value);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            assertEquals("get/set Parameter failed", preset,
                    mEffect.byteArrayToShort(value));

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.1: test setParameter(int, int) / getParameter(int, int[])
    public void test3_1SetParameterIntInt() throws Exception {
        if (!isEnvReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
        try {
            int param = EnvironmentalReverb.PARAM_DECAY_TIME;
            int[] value = new int[1];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            int time = 500;
            if (value[0] == time) {
                time = 1000;
            }
            status = mEffect.setParameter(param, time);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            assertTrue("got incorrect decay time",
                    ((float)value[0] > (float)(time / DELAY_TOLERANCE)) &&
                    ((float)value[0] < (float)(time * DELAY_TOLERANCE)));

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.2: test setParameter(int, short) / getParameter(int, short[])
    public void test3_2SetParameterIntShort() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
        try {
            int param = PresetReverb.PARAM_PRESET;
            short[] value = new short[1];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            short preset = PresetReverb.PRESET_SMALLROOM;
            if (value[0] == preset) {
                preset = PresetReverb.PRESET_MEDIUMROOM;
            }
            status = mEffect.setParameter(param, preset);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            assertEquals("get/set Parameter failed", preset, value[0]);

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.3: test setParameter(int, byte[]) / getParameter(int, byte[])
    public void test3_3SetParameterIntByteArray() throws Exception {
        if (!isEnvReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
        try {
            int param = EnvironmentalReverb.PARAM_DECAY_TIME;
            byte[] value = new byte[4];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            int time = 500;
            if (mEffect.byteArrayToInt(value) == time) {
                time = 1000;
            }
            value = mEffect.intToByteArray(time);
            status = mEffect.setParameter(param, value);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            int time2 = mEffect.byteArrayToInt(value);
            assertTrue("got incorrect decay time",
                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.4: test setParameter(int[], int[]) / getParameter(int[], int[])
    public void test3_4SetParameterIntArrayIntArray() throws Exception {
        if (!isEnvReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
        try {
            int[] param = new int[1];
            int[] value = new int[1];
            param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            int[] time = new int[1];
            time[0] = 500;
            if (value[0] == time[0]) {
                time[0] = 1000;
            }
            status = mEffect.setParameter(param, time);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            assertTrue("got incorrect decay time",
                    ((float)value[0] > (float)(time[0] / DELAY_TOLERANCE)) &&
                    ((float)value[0] < (float)(time[0] * DELAY_TOLERANCE)));

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.5: test setParameter(int[], short[]) / getParameter(int[], short[])

    public void test3_5SetParameterIntArrayShortArray() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
        try {
            int[] param = new int[1];
            param[0] = PresetReverb.PARAM_PRESET;
            short[] value = new short[1];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            short[] preset = new short[1];
            preset[0] = PresetReverb.PRESET_SMALLROOM;
            if (value[0] == preset[0]) {
                preset[0] = PresetReverb.PRESET_MEDIUMROOM;
            }
            status = mEffect.setParameter(param, preset);
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            assertEquals("get/set Parameter failed", preset[0], value[0]);

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.6: test setParameter(int[], byte[]) / getParameter(int[], byte[])
    public void test3_6SetParameterIntArrayByteArray() throws Exception {
        if (!isEnvReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
        try {
            int[] param = new int[1];
            param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
            byte[] value = new byte[4];
            int status = mEffect.getParameter(param, value);
            assertFalse("getParameter 1 failed", AudioEffect.isError(status));
            int time = 500;
            if (mEffect.byteArrayToInt(value) == time) {
                time = 1000;
            }

            status = mEffect.setParameter(param, mEffect.intToByteArray(time));
            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
            status = mEffect.getParameter(param, value);
            assertFalse("getParameter 2 failed", AudioEffect.isError(status));
            int time2 = mEffect.byteArrayToInt(value);
            assertTrue("got incorrect decay time",
                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));

        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            fail("setParameter() called in wrong state");
        } finally {
            releaseEffect();
        }
    }

    //Test case 3.7: test setParameter() throws exception after release()
    public void test3_7SetParameterAfterRelease() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        AudioEffect effect = null;
        try {
            effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
                                    AudioEffect.EFFECT_TYPE_NULL,
                                    0,
                                    0);
            assertNotNull("could not create AudioEffect", effect);
            effect.release();
            effect.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_SMALLROOM);
            fail("setParameter() processed after release");
        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("setParameter() rejected");
        } catch (IllegalStateException e) {
            // test passed
        } finally {
            if (effect != null) {
                effect.release();
            }
        }
    }

    //Test case 3.8: test getParameter() throws exception after release()
    public void test3_8GetParameterAfterRelease() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        AudioEffect effect = null;
        try {
            effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
                                    AudioEffect.EFFECT_TYPE_NULL,
                                    0,
                                    0);
            assertNotNull("could not create AudioEffect", effect);
            effect.release();
            short[] value = new short[1];
            effect.getParameter(PresetReverb.PARAM_PRESET, value);
            fail("getParameter() processed after release");
        } catch (IllegalArgumentException e) {
            fail("Bad parameter value");
        } catch (UnsupportedOperationException e) {
            fail("getParameter() rejected");
        } catch (IllegalStateException e) {
            // test passed
        } finally {
            if (effect != null) {
                effect.release();
            }
        }
    }

    //-----------------------------------------------------------------
    // 4 priority and listeners
    //----------------------------------

    //Test case 4.0: test control passed to higher priority client
    public void test4_0setEnabledLowerPriority() throws Exception {
        AudioEffect effect1 = null;
        AudioEffect effect2 = null;
        try {
            effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                                    AudioEffect.EFFECT_TYPE_NULL,
                                    0,
                                    0);
            effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    1,
                    0);

            assertNotNull("could not create AudioEffect", effect1);
            assertNotNull("could not create AudioEffect", effect2);

            assertTrue("Effect2 does not have control", effect2.hasControl());
            assertFalse("Effect1 has control", effect1.hasControl());
            assertTrue("Effect1 can enable",
                    effect1.setEnabled(true) == AudioEffect.ERROR_INVALID_OPERATION);
            assertFalse("Effect1 has enabled", effect2.getEnabled());

        } catch (IllegalArgumentException e) {
            fail("Effect not found");
        } catch (UnsupportedOperationException e) {
            fail("Effect library not loaded");
        } finally {
            if (effect1 != null) {
                effect1.release();
            }
            if (effect2 != null) {
                effect2.release();
            }
        }
    }

    //Test case 4.1: test control passed to higher priority client
    public void test4_1setParameterLowerPriority() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        AudioEffect effect1 = null;
        AudioEffect effect2 = null;
        try {
            effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
                                    AudioEffect.EFFECT_TYPE_NULL,
                                    0,
                                    0);
            effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
                    AudioEffect.EFFECT_TYPE_NULL,
                    1,
                    0);

            assertNotNull("could not create AudioEffect", effect1);
            assertNotNull("could not create AudioEffect", effect2);

            int status = effect2.setParameter(PresetReverb.PARAM_PRESET,
                    PresetReverb.PRESET_SMALLROOM);
            assertEquals("Effect2 setParameter failed",
                    AudioEffect.SUCCESS, status);

            status = effect1.setParameter(PresetReverb.PARAM_PRESET,
                    PresetReverb.PRESET_MEDIUMROOM);
            assertEquals("Effect1 setParameter did not fail",
                    AudioEffect.ERROR_INVALID_OPERATION, status);

            short[] value = new short[1];
            status = effect2.getParameter(PresetReverb.PARAM_PRESET, value);
            assertFalse("Effect2 getParameter failed",
                    AudioEffect.isError(status));
            assertEquals("Effect1 changed parameter", PresetReverb.PRESET_SMALLROOM
                    , value[0]);


        } catch (IllegalArgumentException e) {
            fail("Effect not found");
        } catch (UnsupportedOperationException e) {
            fail("Effect library not loaded");
        } finally {
            if (effect1 != null) {
                effect1.release();
            }
            if (effect2 != null) {
                effect2.release();
            }
        }
    }

    //Test case 4.2: test control status listener
    public void test4_2ControlStatusListener() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        synchronized(mLock) {
            mHasControl = true;
            mInitialized = false;
            createListenerLooper(true, false, false);
            waitForLooperInitialization_l();

            getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
            while (mHasControl && (looperWaitCount-- > 0)) {
                try {
                    mLock.wait();
                } catch(Exception e) {
                }
            }
            terminateListenerLooper();
            releaseEffect();
        }
        assertFalse("effect control not lost by effect1", mHasControl);
    }

    //Test case 4.3: test enable status listener
    public void test4_3EnableStatusListener() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        synchronized(mLock) {
            mInitialized = false;
            createListenerLooper(false, true, false);
            waitForLooperInitialization_l();

            mEffect2.setEnabled(true);
            mIsEnabled = true;

            getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
            assertTrue("effect not enabled", mEffect.getEnabled());
            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
            while (mIsEnabled && (looperWaitCount-- > 0)) {
                try {
                    mEffect.setEnabled(false);
                    mLock.wait();
                } catch(Exception e) {
                }
            }
            terminateListenerLooper();
            releaseEffect();
        }
        assertFalse("enable status not updated", mIsEnabled);
    }

    //Test case 4.4: test parameter changed listener
    public void test4_4ParameterChangedListener() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        synchronized(mLock) {
            mInitialized = false;
            createListenerLooper(false, false, true);
            waitForLooperInitialization_l();
            int status = mEffect2.setParameter(PresetReverb.PARAM_PRESET,
                    PresetReverb.PRESET_SMALLROOM);
            assertEquals("mEffect2 setParameter failed",
                    AudioEffect.SUCCESS, status);
            getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
            mChangedParameter = -1;
            mEffect.setParameter(PresetReverb.PARAM_PRESET,
                    PresetReverb.PRESET_MEDIUMROOM);
            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
            while (mChangedParameter == -1 && (looperWaitCount-- > 0)) {
                try {
                    mLock.wait();
                } catch(Exception e) {
                }
            }
            terminateListenerLooper();
            releaseEffect();
        }
        assertEquals("parameter change not received",
                PresetReverb.PARAM_PRESET, mChangedParameter);
    }

    //-----------------------------------------------------------------
    // 5 command method
    //----------------------------------


    //Test case 5.0: test command method
    public void test5_0Command() throws Exception {
        if (!isPresetReverbAvailable()) {
            return;
        }
        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
        try {
            byte[] cmd = new byte[0];
            byte[] reply = new byte[4];
            // command 3 is ENABLE
            int status = mEffect.command(3, cmd, reply);
            assertFalse("command failed", AudioEffect.isError(status));
            assertTrue("effect not enabled", mEffect.getEnabled());

        } catch (IllegalStateException e) {
            fail("command in illegal state");
        } finally {
            releaseEffect();
        }
    }


    //-----------------------------------------------------------------
    // private methods
    //----------------------------------

    private void getEffect(UUID type, int session) {
         if (mEffect == null || session != mSession) {
             if (session != mSession && mEffect != null) {
                 mEffect.release();
                 mEffect = null;
             }
             try {
                 mEffect = new AudioEffect(type,
                                             AudioEffect.EFFECT_TYPE_NULL,
                                             0,
                                             session);
                 mSession = session;
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "getEffect() AudioEffect not found exception: "+e);
            } catch (UnsupportedOperationException e) {
                Log.e(TAG, "getEffect() Effect library not loaded exception: "+e);
            }
         }
         assertNotNull("could not create mEffect", mEffect);
    }

    private void releaseEffect() {
        if (mEffect != null) {
            mEffect.release();
            mEffect = null;
        }
    }

    private void waitForLooperInitialization_l() {
        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
        while (!mInitialized && (looperWaitCount-- > 0)) {
            try {
                mLock.wait();
            } catch(Exception e) {
            }
        }
        assertTrue(mInitialized);
    }

    // Initializes the equalizer listener looper
    class ListenerThread extends Thread {
        boolean mControl;
        boolean mEnable;
        boolean mParameter;

        public ListenerThread(boolean control, boolean enable, boolean parameter) {
            super();
            mControl = control;
            mEnable = enable;
            mParameter = parameter;
        }

        public void cleanUp() {
            if (mEffect2 != null) {
                mEffect2.setControlStatusListener(null);
                mEffect2.setEnableStatusListener(null);
                mEffect2.setParameterListener(null);
            }
        }
    }

    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
            @Override
            public void run() {
                // Set up a looper
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                mEffect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
                        AudioEffect.EFFECT_TYPE_NULL,
                        0,
                        0);
                assertNotNull("could not create Equalizer2", mEffect2);

                synchronized(mLock) {
                    if (mControl) {
                        mEffect2.setControlStatusListener(
                                new AudioEffect.OnControlStatusChangeListener() {
                            public void onControlStatusChange(
                                    AudioEffect effect, boolean controlGranted) {
                                synchronized(mLock) {
                                    if (effect == mEffect2) {
                                        mHasControl = controlGranted;
                                        mLock.notify();
                                    }
                                }
                            }
                        });
                    }
                    if (mEnable) {
                        mEffect2.setEnableStatusListener(
                                new AudioEffect.OnEnableStatusChangeListener() {
                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
                                synchronized(mLock) {
                                    if (effect == mEffect2) {
                                        mIsEnabled = enabled;
                                        mLock.notify();
                                    }
                                }
                            }
                        });
                    }
                    if (mParameter) {
                        mEffect2.setParameterListener(new AudioEffect.OnParameterChangeListener() {
                            public void onParameterChange(AudioEffect effect, int status, byte[] param,
                                    byte[] value)
                            {
                                synchronized(mLock) {
                                    if (effect == mEffect2) {
                                        mChangedParameter = mEffect2.byteArrayToInt(param);
                                        mLock.notify();
                                    }
                                }
                            }
                        });
                    }
                    mInitialized = true;
                    mLock.notify();
                }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        };
        mEffectListenerLooper.start();
    }

    // Terminates the listener looper thread.
    private void terminateListenerLooper() {
        if (mEffectListenerLooper != null) {
            mEffectListenerLooper.cleanUp();
            if (mLooper != null) {
                mLooper.quit();
                mLooper = null;
            }
            try {
                mEffectListenerLooper.join();
            } catch(InterruptedException e) {
            }
            mEffectListenerLooper = null;
        }
        if (mEffect2 != null) {
            mEffect2.release();
            mEffect2 = null;
        }
    }

    /*
     * Initializes the message looper so that the MediaPlayer object can
     * receive the callback messages.
     */
    private void createMediaPlayerLooper() {
        new Thread() {
            @Override
            public void run() {
                // Set up a looper to be used by mMediaPlayer.
                Looper.prepare();

                // Save the looper so that we can terminate this thread
                // after we are done with it.
                mLooper = Looper.myLooper();

                mMediaPlayer = new MediaPlayer();

                synchronized(mLock) {
                    mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                        public boolean onError(MediaPlayer player, int what, int extra) {
                            synchronized(mLock) {
                                mError = what;
                                mLock.notify();
                            }
                            return true;
                        }
                    });
                    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        public void onCompletion(MediaPlayer player) {
                            synchronized(mLock) {
                                mLock.notify();
                            }
                        }
                    });
                    mInitialized = true;
                    mLock.notify();
                }
                Looper.loop();  // Blocks forever until Looper.quit() is called.
            }
        }.start();
    }
    /*
     * Terminates the message looper thread.
     */
    private void terminateMediaPlayerLooper() {
        if (mLooper != null) {
            mLooper.quit();
            mLooper = null;
        }
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
        }
    }

}
