/*
 * Copyright (C) 2010-2011 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 com.android.musicfx;

import android.content.Context;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.audiofx.AudioEffect;
import android.media.audiofx.BassBoost;
import android.media.audiofx.Equalizer;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.Virtualizer;
import android.util.Log;

import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;

/**
 * The Common class defines constants to be used by the control panels.
 */
public class ControlPanelEffect {

    private final static String TAG = "MusicFXControlPanelEffect";

    /**
     * Audio session priority
     */
    private static final int PRIORITY = 0;

    /**
     * The control mode specifies if control panel updates effects and preferences or only
     * preferences.
     */
    static enum ControlMode {
        /**
         * Control panel updates effects and preferences. Applicable when audio session is delivered
         * by user.
         */
        CONTROL_EFFECTS,
        /**
         * Control panel only updates preferences. Applicable when there was no audio or invalid
         * session provided by user.
         */
        CONTROL_PREFERENCES
    }

    static enum Key {
        global_enabled, virt_enabled, virt_strength, virt_type, bb_enabled, bb_strength, te_enabled, te_strength, avl_enabled, lm_enabled, lm_strength, eq_enabled, eq_num_bands, eq_level_range, eq_center_freq, eq_band_level, eq_num_presets, eq_preset_name, eq_preset_user_band_level, eq_preset_user_band_level_default, eq_preset_opensl_es_band_level, eq_preset_ci_extreme_band_level, eq_current_preset, pr_enabled, pr_current_preset
    }

    // Effect/audio session Mappings
    /**
     * Hashmap initial capacity
     */
    private static final int HASHMAP_INITIAL_CAPACITY = 16;
    /**
     * Hashmap load factor
     */
    private static final float HASHMAP_LOAD_FACTOR = 0.75f;
    /**
     * ConcurrentHashMap concurrency level
     */
    private static final int HASHMAP_CONCURRENCY_LEVEL = 2;

    /**
     * Map containing the Virtualizer audio session, effect mappings.
     */
    private static final ConcurrentHashMap<Integer, Virtualizer> mVirtualizerInstances = new ConcurrentHashMap<Integer, Virtualizer>(
            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
    /**
     * Map containing the BB audio session, effect mappings.
     */
    private static final ConcurrentHashMap<Integer, BassBoost> mBassBoostInstances = new ConcurrentHashMap<Integer, BassBoost>(
            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
    /**
     * Map containing the EQ audio session, effect mappings.
     */
    private static final ConcurrentHashMap<Integer, Equalizer> mEQInstances = new ConcurrentHashMap<Integer, Equalizer>(
            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
    /**
     * Map containing the PR audio session, effect mappings.
     */
    private static final ConcurrentHashMap<Integer, PresetReverb> mPresetReverbInstances = new ConcurrentHashMap<Integer, PresetReverb>(
            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);

    /**
     * Map containing the package name, audio session mappings.
     */
    private static final ConcurrentHashMap<String, Integer> mPackageSessions = new ConcurrentHashMap<String, Integer>(
            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);

    // Defaults
    final static boolean GLOBAL_ENABLED_DEFAULT = false;
    private final static boolean VIRTUALIZER_ENABLED_DEFAULT = true;
    private final static int VIRTUALIZER_STRENGTH_DEFAULT = 1000;
    private final static boolean BASS_BOOST_ENABLED_DEFAULT = true;
    private final static int BASS_BOOST_STRENGTH_DEFAULT = 667;
    private final static boolean PRESET_REVERB_ENABLED_DEFAULT = false;
    private final static int PRESET_REVERB_CURRENT_PRESET_DEFAULT = 0; // None

    // EQ defaults
    private final static boolean EQUALIZER_ENABLED_DEFAULT = true;
    private final static String EQUALIZER_PRESET_NAME_DEFAULT = "Preset";
    private final static short EQUALIZER_NUMBER_BANDS_DEFAULT = 5;
    private final static short EQUALIZER_NUMBER_PRESETS_DEFAULT = 0;
    private final static short[] EQUALIZER_BAND_LEVEL_RANGE_DEFAULT = { -1500, 1500 };
    private final static int[] EQUALIZER_CENTER_FREQ_DEFAULT = { 60000, 230000, 910000, 3600000,
            14000000 };
    private final static short[] EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL = { 0, 800, 400, 100, 1000 };
    private final static short[] EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT = { 0, 0, 0, 0, 0 };
    private final static short[][] EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT = new short[EQUALIZER_NUMBER_PRESETS_DEFAULT][EQUALIZER_NUMBER_BANDS_DEFAULT];

    // EQ effect properties which are invariable over all EQ effects sessions
    private static short[] mEQBandLevelRange = EQUALIZER_BAND_LEVEL_RANGE_DEFAULT;
    private static short mEQNumBands = EQUALIZER_NUMBER_BANDS_DEFAULT;
    private static int[] mEQCenterFreq = EQUALIZER_CENTER_FREQ_DEFAULT;
    private static short mEQNumPresets = EQUALIZER_NUMBER_PRESETS_DEFAULT;
    private static short[][] mEQPresetOpenSLESBandLevel = EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT;
    private static String[] mEQPresetNames;
    private static boolean mIsEQInitialized = false;
    private final static Object mEQInitLock = new Object();

    /**
     * Default int argument used in methods to see that the arg is a dummy. Used for method
     * overloading.
     */
    private final static int DUMMY_ARGUMENT = -1;

    /**
     * Inits effects preferences for the given context and package name in the control panel. If
     * preferences for the given package name don't exist, they are created and initialized.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     */
    public static void initEffectsPreferences(final Context context, final String packageName,
            final int audioSession) {
        final SharedPreferences prefs = context.getSharedPreferences(packageName,
                Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = prefs.edit();
        final ControlMode controlMode = getControlMode(audioSession);

        // init preferences
        try {
            // init global on/off switch
            final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
                    GLOBAL_ENABLED_DEFAULT);
            editor.putBoolean(Key.global_enabled.toString(), isGlobalEnabled);
            Log.v(TAG, "isGlobalEnabled = " + isGlobalEnabled);

            // Virtualizer
            final boolean isVIEnabled = prefs.getBoolean(Key.virt_enabled.toString(),
                    VIRTUALIZER_ENABLED_DEFAULT);
            final int vIStrength = prefs.getInt(Key.virt_strength.toString(),
                    VIRTUALIZER_STRENGTH_DEFAULT);
            editor.putBoolean(Key.virt_enabled.toString(), isVIEnabled);
            editor.putInt(Key.virt_strength.toString(), vIStrength);

            // BassBoost
            final boolean isBBEnabled = prefs.getBoolean(Key.bb_enabled.toString(),
                    BASS_BOOST_ENABLED_DEFAULT);
            final int bBStrength = prefs.getInt(Key.bb_strength.toString(),
                    BASS_BOOST_STRENGTH_DEFAULT);
            editor.putBoolean(Key.bb_enabled.toString(), isBBEnabled);
            editor.putInt(Key.bb_strength.toString(), bBStrength);

            // Equalizer
            synchronized (mEQInitLock) {
                // If EQ is not initialized already create "dummy" audio session created by
                // MediaPlayer and create effect on it to retrieve the invariable EQ properties
                if (!mIsEQInitialized) {
                    final MediaPlayer mediaPlayer = new MediaPlayer();
                    final int session = mediaPlayer.getAudioSessionId();
                    Equalizer equalizerEffect = null;
                    try {
                        Log.d(TAG, "Creating dummy EQ effect on session " + session);
                        equalizerEffect = new Equalizer(PRIORITY, session);

                        mEQBandLevelRange = equalizerEffect.getBandLevelRange();
                        mEQNumBands = equalizerEffect.getNumberOfBands();
                        mEQCenterFreq = new int[mEQNumBands];
                        for (short band = 0; band < mEQNumBands; band++) {
                            mEQCenterFreq[band] = equalizerEffect.getCenterFreq(band);
                        }
                        mEQNumPresets = equalizerEffect.getNumberOfPresets();
                        mEQPresetNames = new String[mEQNumPresets];
                        mEQPresetOpenSLESBandLevel = new short[mEQNumPresets][mEQNumBands];
                        for (short preset = 0; preset < mEQNumPresets; preset++) {
                            mEQPresetNames[preset] = equalizerEffect.getPresetName(preset);
                            equalizerEffect.usePreset(preset);
                            for (short band = 0; band < mEQNumBands; band++) {
                                mEQPresetOpenSLESBandLevel[preset][band] = equalizerEffect
                                        .getBandLevel(band);
                            }
                        }

                        mIsEQInitialized = true;
                    } catch (final IllegalStateException e) {
                        Log.e(TAG, "Equalizer: " + e);
                    } catch (final IllegalArgumentException e) {
                        Log.e(TAG, "Equalizer: " + e);
                    } catch (final UnsupportedOperationException e) {
                        Log.e(TAG, "Equalizer: " + e);
                    } catch (final RuntimeException e) {
                        Log.e(TAG, "Equalizer: " + e);
                    } finally {
                        if (equalizerEffect != null) {
                            Log.d(TAG, "Releasing dummy EQ effect");
                            equalizerEffect.release();
                        }
                        mediaPlayer.release();

                        // When there was a failure set some good defaults
                        if (!mIsEQInitialized) {
                            mEQPresetOpenSLESBandLevel = new short[mEQNumPresets][mEQNumBands];
                            for (short preset = 0; preset < mEQNumPresets; preset++) {
                                // Init preset names to a dummy name
                                mEQPresetNames[preset] = prefs.getString(
                                        Key.eq_preset_name.toString() + preset,
                                        EQUALIZER_PRESET_NAME_DEFAULT + preset);
                                if (preset < EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT.length) {
                                    mEQPresetOpenSLESBandLevel[preset] = Arrays.copyOf(
                                            EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT[preset],
                                            mEQNumBands);
                                }
                            }
                        }
                    }
                }
                editor.putInt(Key.eq_level_range.toString() + 0, mEQBandLevelRange[0]);
                editor.putInt(Key.eq_level_range.toString() + 1, mEQBandLevelRange[1]);
                editor.putInt(Key.eq_num_bands.toString(), mEQNumBands);
                editor.putInt(Key.eq_num_presets.toString(), mEQNumPresets);
                // Resetting the EQ arrays depending on the real # bands with defaults if
                // band < default size else 0 by copying default arrays over new ones
                final short[] eQPresetCIExtremeBandLevel = Arrays.copyOf(
                        EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, mEQNumBands);
                final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
                        EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, mEQNumBands);
                // If no preset prefs set use CI EXTREME (= numPresets)
                final short eQPreset = (short) prefs.getInt(Key.eq_current_preset.toString(),
                        mEQNumPresets);
                editor.putInt(Key.eq_current_preset.toString(), eQPreset);
                final short[] bandLevel = new short[mEQNumBands];
                for (short band = 0; band < mEQNumBands; band++) {
                    if (controlMode == ControlMode.CONTROL_PREFERENCES) {
                        if (eQPreset < mEQNumPresets) {
                            // OpenSL ES effect presets
                            bandLevel[band] = mEQPresetOpenSLESBandLevel[eQPreset][band];
                        } else if (eQPreset == mEQNumPresets) {
                            // CI EXTREME
                            bandLevel[band] = eQPresetCIExtremeBandLevel[band];
                        } else {
                            // User
                            bandLevel[band] = (short) prefs.getInt(
                                    Key.eq_preset_user_band_level.toString() + band,
                                    eQPresetUserBandLevelDefault[band]);
                        }
                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel[band]);
                    }
                    editor.putInt(Key.eq_center_freq.toString() + band, mEQCenterFreq[band]);
                    editor.putInt(Key.eq_preset_ci_extreme_band_level.toString() + band,
                            eQPresetCIExtremeBandLevel[band]);
                    editor.putInt(Key.eq_preset_user_band_level_default.toString() + band,
                            eQPresetUserBandLevelDefault[band]);
                }
                for (short preset = 0; preset < mEQNumPresets; preset++) {
                    editor.putString(Key.eq_preset_name.toString() + preset, mEQPresetNames[preset]);
                    for (short band = 0; band < mEQNumBands; band++) {
                        editor.putInt(Key.eq_preset_opensl_es_band_level.toString() + preset + "_"
                                + band, mEQPresetOpenSLESBandLevel[preset][band]);
                    }
                }
            }
            final boolean isEQEnabled = prefs.getBoolean(Key.eq_enabled.toString(),
                    EQUALIZER_ENABLED_DEFAULT);
            editor.putBoolean(Key.eq_enabled.toString(), isEQEnabled);

            // Preset reverb
            final boolean isEnabledPR = prefs.getBoolean(Key.pr_enabled.toString(),
                    PRESET_REVERB_ENABLED_DEFAULT);
            final short presetPR = (short) prefs.getInt(Key.pr_current_preset.toString(),
                    PRESET_REVERB_CURRENT_PRESET_DEFAULT);
            editor.putBoolean(Key.pr_enabled.toString(), isEnabledPR);
            editor.putInt(Key.pr_current_preset.toString(), presetPR);

            editor.commit();
        } catch (final RuntimeException e) {
            Log.e(TAG, "initEffectsPreferences: processingEnabled: " + e);
        }
    }

    /**
     * Gets the effect control mode based on the given audio session in the control panel. Control
     * mode defines if the control panel is controlling effects and/or preferences
     *
     * @param audioSession
     *            System wide unique audio session identifier.
     * @return effect control mode
     */
    public static ControlMode getControlMode(final int audioSession) {
        if (audioSession == AudioEffect.ERROR_BAD_VALUE) {
            return ControlMode.CONTROL_PREFERENCES;
        }
        return ControlMode.CONTROL_EFFECTS;
    }

    /**
     * Sets boolean parameter to value for given key
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @param value
     */
    public static void setParameterBoolean(final Context context, final String packageName,
            final int audioSession, final Key key, final boolean value) {
        try {
            final SharedPreferences prefs = context.getSharedPreferences(packageName,
                    Context.MODE_PRIVATE);
            final ControlMode controlMode = getControlMode(audioSession);
            boolean enabled = value;

            // Global on/off
            if (key == Key.global_enabled) {
                boolean processingEnabled = false;
                if (value == true) {
                    // enable all with respect to preferences
                    if (controlMode == ControlMode.CONTROL_EFFECTS) {
                        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
                        if (virtualizerEffect != null) {
                            virtualizerEffect.setEnabled(prefs.getBoolean(
                                    Key.virt_enabled.toString(), VIRTUALIZER_ENABLED_DEFAULT));
                            final int vIStrength = prefs.getInt(Key.virt_strength.toString(),
                                    VIRTUALIZER_STRENGTH_DEFAULT);
                            setParameterInt(context, packageName,
                                    audioSession, Key.virt_strength, vIStrength);
                        }
                        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
                        if (bassBoostEffect != null) {
                            bassBoostEffect.setEnabled(prefs.getBoolean(Key.bb_enabled.toString(),
                                    BASS_BOOST_ENABLED_DEFAULT));
                            final int bBStrength = prefs.getInt(Key.bb_strength.toString(),
                                    BASS_BOOST_STRENGTH_DEFAULT);
                            setParameterInt(context, packageName,
                                    audioSession, Key.bb_strength, bBStrength);
                        }
                        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
                        if (equalizerEffect != null) {
                            equalizerEffect.setEnabled(prefs.getBoolean(Key.eq_enabled.toString(),
                                    EQUALIZER_ENABLED_DEFAULT));
                            final int[] bandLevels = getParameterIntArray(context,
                                    packageName, audioSession, Key.eq_band_level);
                            final int len = bandLevels.length;
                            for (short band = 0; band < len; band++) {
                                final int level = bandLevels[band];
                                setParameterInt(context, packageName,
                                        audioSession, Key.eq_band_level, level, band);
                            }
                        }
                        // XXX: Preset Reverb not used for the moment, so commented out the effect
                        // creation to not use MIPS
                        // final PresetReverb presetReverbEffect =
                        // getPresetReverbEffect(audioSession);
                        // if (presetReverbEffect != null) {
                        // presetReverbEffect.setEnabled(prefs.getBoolean(
                        // Key.pr_enabled.toString(), PRESET_REVERB_ENABLED_DEFAULT));
                        // }
                    }

                    processingEnabled = true;
                    Log.v(TAG, "processingEnabled=" + processingEnabled);

                } else {
                    // disable all
                    if (controlMode == ControlMode.CONTROL_EFFECTS) {
                        final Virtualizer virtualizerEffect = getVirtualizerEffectNoCreate(audioSession);
                        if (virtualizerEffect != null) {
                            mVirtualizerInstances.remove(audioSession, virtualizerEffect);
                            virtualizerEffect.setEnabled(false);
                            virtualizerEffect.release();
                        }
                        final BassBoost bassBoostEffect = getBassBoostEffectNoCreate(audioSession);
                        if (bassBoostEffect != null) {
                            mBassBoostInstances.remove(audioSession, bassBoostEffect);
                            bassBoostEffect.setEnabled(false);
                            bassBoostEffect.release();
                        }
                        final Equalizer equalizerEffect = getEqualizerEffectNoCreate(audioSession);
                        if (equalizerEffect != null) {
                            mEQInstances.remove(audioSession, equalizerEffect);
                            equalizerEffect.setEnabled(false);
                            equalizerEffect.release();
                        }
                        // XXX: Preset Reverb not used for the moment, so commented out the effect
                        // creation to not use MIPS
                        // final PresetReverb presetReverbEffect =
                        // getPresetReverbEffect(audioSession);
                        // if (presetReverbEffect != null) {
                        // presetReverbEffect.setEnabled(false);
                        // }
                    }

                    processingEnabled = false;
                    Log.v(TAG, "processingEnabled=" + processingEnabled);
                }
                enabled = processingEnabled;
            } else if (controlMode == ControlMode.CONTROL_EFFECTS) {
                final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
                        GLOBAL_ENABLED_DEFAULT);
                if (isGlobalEnabled == true) {
                    // Set effect parameters
                    switch (key) {

                    case global_enabled:
                        // Global, already handled, to get out error free
                        break;

                    // Virtualizer
                    case virt_enabled:
                        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
                        if (virtualizerEffect != null) {
                            virtualizerEffect.setEnabled(value);
                            enabled = virtualizerEffect.getEnabled();
                        }
                        break;

                    // BassBoost
                    case bb_enabled:
                        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
                        if (bassBoostEffect != null) {
                            bassBoostEffect.setEnabled(value);
                            enabled = bassBoostEffect.getEnabled();
                        }
                        break;

                    // Equalizer
                    case eq_enabled:
                        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
                        if (equalizerEffect != null) {
                            equalizerEffect.setEnabled(value);
                            enabled = equalizerEffect.getEnabled();
                        }
                        break;

                    // PresetReverb
                    case pr_enabled:
                        // XXX: Preset Reverb not used for the moment, so commented out the effect
                        // creation to not use MIPS
                        // final PresetReverb presetReverbEffect =
                        // getPresetReverbEffect(audioSession);
                        // if (presetReverbEffect != null) {
                        // presetReverbEffect.setEnabled(value);
                        // enabled = presetReverbEffect.getEnabled();
                        // }
                        break;

                    default:
                        Log.e(TAG, "Unknown/unsupported key " + key);
                        return;
                    }
                }

            }

            // Set preferences
            final SharedPreferences.Editor editor = prefs.edit();
            editor.putBoolean(key.toString(), enabled);
            editor.commit();

        } catch (final RuntimeException e) {
            Log.e(TAG, "setParameterBoolean: " + key + "; " + value + "; " + e);
        }
    }

    /**
     * Gets boolean parameter for given key
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value
     */
    public static Boolean getParameterBoolean(final Context context, final String packageName,
            final int audioSession, final Key key) {
        final SharedPreferences prefs = context.getSharedPreferences(packageName,
                Context.MODE_PRIVATE);
        boolean value = false;

        try {
            value = prefs.getBoolean(key.toString(), value);
        } catch (final RuntimeException e) {
            Log.e(TAG, "getParameterBoolean: " + key + "; " + value + "; " + e);
        }

        return value;

    }

    /**
     * Sets int parameter for given key and value arg0, arg1
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @param arg0
     * @param arg1
     */
    public static void setParameterInt(final Context context, final String packageName,
            final int audioSession, final Key key, final int arg0, final int arg1) {
        String strKey = key.toString();
        int value = arg0;

        try {
            final SharedPreferences prefs = context.getSharedPreferences(packageName,
                    Context.MODE_PRIVATE);
            final SharedPreferences.Editor editor = prefs.edit();
            final ControlMode controlMode = getControlMode(audioSession);

            // Set effect parameters
            if (controlMode == ControlMode.CONTROL_EFFECTS) {

                switch (key) {

                // Virtualizer
                case virt_strength: {
                    final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
                    if (virtualizerEffect != null) {
                        virtualizerEffect.setStrength((short) value);
                        value = virtualizerEffect.getRoundedStrength();
                    }
                    break;
                }
                    // BassBoost
                case bb_strength: {
                    final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
                    if (bassBoostEffect != null) {
                        bassBoostEffect.setStrength((short) value);
                        value = bassBoostEffect.getRoundedStrength();
                    }
                    break;
                }
                    // Equalizer
                case eq_band_level: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = strKey + band;
                    final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
                    if (equalizerEffect != null) {
                        equalizerEffect.setBandLevel(band, (short) value);
                        value = equalizerEffect.getBandLevel(band);
                        // save band level in User preset
                        editor.putInt(Key.eq_preset_user_band_level.toString() + band, value);
                    }
                    break;
                }
                case eq_current_preset: {
                    final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
                    if (equalizerEffect != null) {
                        final short preset = (short) value;
                        final int numBands = prefs.getInt(Key.eq_num_bands.toString(),
                                EQUALIZER_NUMBER_BANDS_DEFAULT);
                        final int numPresets = prefs.getInt(Key.eq_num_presets.toString(),
                                EQUALIZER_NUMBER_PRESETS_DEFAULT);

                        if (preset < numPresets) {
                            // OpenSL ES EQ Effect presets
                            equalizerEffect.usePreset(preset);
                            value = equalizerEffect.getCurrentPreset();
                        } else {
                            final short[] eQPresetCIExtremeBandLevelDefault = Arrays.copyOf(
                                    EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, numBands);
                            final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
                                    EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, numBands);
                            // Set the band levels manually for custom presets
                            for (short band = 0; band < numBands; band++) {
                                short bandLevel = 0;
                                if (preset == numPresets) {
                                    // CI EXTREME
                                    bandLevel = (short) prefs.getInt(
                                            Key.eq_preset_ci_extreme_band_level.toString() + band,
                                            eQPresetCIExtremeBandLevelDefault[band]);
                                } else {
                                    // User
                                    bandLevel = (short) prefs.getInt(
                                            Key.eq_preset_user_band_level.toString() + band,
                                            eQPresetUserBandLevelDefault[band]);
                                }
                                equalizerEffect.setBandLevel(band, bandLevel);
                            }
                        }

                        // update band levels
                        for (short band = 0; band < numBands; band++) {
                            final short level = equalizerEffect.getBandLevel(band);
                            editor.putInt(Key.eq_band_level.toString() + band, level);
                        }
                    }
                    break;
                }
                case eq_preset_user_band_level:
                    // Fall through
                case eq_preset_user_band_level_default:
                    // Fall through
                case eq_preset_ci_extreme_band_level: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = strKey + band;
                    break;
                }
                case pr_current_preset:
                    // XXX: Preset Reverb not used for the moment, so commented out the effect
                    // creation to not use MIPS
                    // final PresetReverb presetReverbEffect = getPresetReverbEffect(audioSession);
                    // if (presetReverbEffect != null) {
                    // presetReverbEffect.setPreset((short) value);
                    // value = presetReverbEffect.getPreset();
                    // }
                    break;
                default:
                    Log.e(TAG, "setParameterInt: Unknown/unsupported key " + key);
                    return;
                }
            } else {
                switch (key) {
                // Virtualizer
                case virt_strength:
                    // Do nothing
                    break;
                case virt_type:
                    // Do nothing
                    break;

                // BassBoost
                case bb_strength:
                    // Do nothing
                    break;

                // Equalizer
                case eq_band_level: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = strKey + band;

                    editor.putInt(Key.eq_preset_user_band_level.toString() + band, value);
                    break;
                }
                case eq_current_preset: {
                    final short preset = (short) value;
                    final int numBands = prefs.getInt(Key.eq_num_bands.toString(),
                            EQUALIZER_NUMBER_BANDS_DEFAULT);
                    final int numPresets = prefs.getInt(Key.eq_num_presets.toString(),
                            EQUALIZER_NUMBER_PRESETS_DEFAULT);

                    final short[][] eQPresetOpenSLESBandLevelDefault = Arrays.copyOf(
                            EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT, numBands);
                    final short[] eQPresetCIExtremeBandLevelDefault = Arrays.copyOf(
                            EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, numBands);
                    final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
                            EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, numBands);
                    for (short band = 0; band < numBands; band++) {
                        short bandLevel = 0;
                        if (preset < numPresets) {
                            // OpenSL ES EQ Effect presets
                            bandLevel = (short) prefs.getInt(
                                    Key.eq_preset_opensl_es_band_level.toString() + preset + "_"
                                            + band, eQPresetOpenSLESBandLevelDefault[preset][band]);
                        } else if (preset == numPresets) {
                            // CI EXTREME
                            bandLevel = (short) prefs.getInt(
                                    Key.eq_preset_ci_extreme_band_level.toString() + band,
                                    eQPresetCIExtremeBandLevelDefault[band]);
                        } else {
                            // User
                            bandLevel = (short) prefs.getInt(
                                    Key.eq_preset_user_band_level.toString() + band,
                                    eQPresetUserBandLevelDefault[band]);
                        }
                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel);
                    }
                    break;
                }
                case eq_preset_user_band_level:
                    // Fall through
                case eq_preset_user_band_level_default:
                    // Fall through
                case eq_preset_ci_extreme_band_level: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = strKey + band;
                    break;
                }
                case pr_current_preset:
                    // Do nothing
                    break;
                default:
                    Log.e(TAG, "setParameterInt: Unknown/unsupported key " + key);
                    return;
                }
            }

            // Set preferences
            editor.putInt(strKey, value);
            editor.commit();

        } catch (final RuntimeException e) {
            Log.e(TAG, "setParameterInt: " + key + "; " + arg0 + "; " + arg1 + "; " + e);
        }

    }

    /**
     * Sets int parameter for given key and value arg
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @param arg
     */
    public static void setParameterInt(final Context context, final String packageName,
            final int audioSession, final Key key, final int arg) {
        setParameterInt(context, packageName, audioSession, key, arg, DUMMY_ARGUMENT);
    }

    /**
     * Gets int parameter given key
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value
     */
    public static int getParameterInt(final Context context, final String packageName,
            final int audioSession, final String key) {
        int value = 0;

        try {
            final SharedPreferences prefs = context.getSharedPreferences(packageName,
                    Context.MODE_PRIVATE);
            value = prefs.getInt(key, value);
        } catch (final RuntimeException e) {
            Log.e(TAG, "getParameterInt: " + key + "; " + e);
        }

        return value;
    }

    /**
     * Gets int parameter given key
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value
     */
    public static int getParameterInt(final Context context, final String packageName,
            final int audioSession, final Key key) {
        return getParameterInt(context, packageName, audioSession, key.toString());
    }

    /**
     * Gets int parameter given key and arg
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param audioSession
     * @param key
     * @param arg
     * @return parameter value
     */
    public static int getParameterInt(final Context context, final String packageName,
            final int audioSession, final Key key, final int arg) {
        return getParameterInt(context, packageName, audioSession, key.toString() + arg);
    }

    /**
     * Gets int parameter given key, arg0 and arg1
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param audioSession
     * @param key
     * @param arg0
     * @param arg1
     * @return parameter value
     */
    public static int getParameterInt(final Context context, final String packageName,
            final int audioSession, final Key key, final int arg0, final int arg1) {
        return getParameterInt(context, packageName, audioSession, key.toString() + arg0 + "_"
                + arg1);
    }

    /**
     * Gets integer array parameter given key. Returns null if not found.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value array
     */
    public static int[] getParameterIntArray(final Context context, final String packageName,
            final int audioSession, final Key key) {
        final SharedPreferences prefs = context.getSharedPreferences(packageName,
                Context.MODE_PRIVATE);

        int[] intArray = null;
        try {
            // Get effect parameters
            switch (key) {
            case eq_level_range: {
                intArray = new int[2];
                break;
            }
            case eq_center_freq:
                // Fall through
            case eq_band_level:
                // Fall through
            case eq_preset_user_band_level:
                // Fall through
            case eq_preset_user_band_level_default:
                // Fall through
            case eq_preset_ci_extreme_band_level: {
                final int numBands = prefs.getInt(Key.eq_num_bands.toString(), 0);
                intArray = new int[numBands];
                break;
            }
            default:
                Log.e(TAG, "getParameterIntArray: Unknown/unsupported key " + key);
                return null;
            }

            for (int i = 0; i < intArray.length; i++) {
                intArray[i] = prefs.getInt(key.toString() + i, 0);
            }

        } catch (final RuntimeException e) {
            Log.e(TAG, "getParameterIntArray: " + key + "; " + e);
        }

        return intArray;
    }

    /**
     * Gets string parameter given key. Returns empty string if not found.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value
     */
    public static String getParameterString(final Context context, final String packageName,
            final int audioSession, final String key) {
        String value = "";
        try {
            final SharedPreferences prefs = context.getSharedPreferences(packageName,
                    Context.MODE_PRIVATE);

            // Get effect parameters
            value = prefs.getString(key, value);

        } catch (final RuntimeException e) {
            Log.e(TAG, "getParameterString: " + key + "; " + e);
        }

        return value;
    }

    /**
     * Gets string parameter given key.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param key
     * @return parameter value
     */
    public static String getParameterString(final Context context, final String packageName,
            final int audioSession, final Key key) {
        return getParameterString(context, packageName, audioSession, key.toString());
    }

    /**
     * Gets string parameter given key and arg.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param args
     * @return parameter value
     */
    public static String getParameterString(final Context context, final String packageName,
            final int audioSession, final Key key, final int arg) {
        return getParameterString(context, packageName, audioSession, key.toString() + arg);
    }

    /**
     * Opens/initializes the effects session for the given audio session with preferences linked to
     * the given package name and context.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     */
    public static void openSession(final Context context, final String packageName,
            final int audioSession) {
        Log.v(TAG, "openSession(" + context + ", " + packageName + ", " + audioSession + ")");
        final String methodTag = "openSession: ";

        // init preferences
        final SharedPreferences prefs = context.getSharedPreferences(packageName,
                Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = prefs.edit();

        final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
                GLOBAL_ENABLED_DEFAULT);
        editor.putBoolean(Key.global_enabled.toString(), isGlobalEnabled);

        if (!isGlobalEnabled) {
            return;
        }

        // Manage audioSession information

        // Retrieve AudioSession Id from map
        boolean isExistingAudioSession = false;

        try {
            final Integer currentAudioSession = mPackageSessions.putIfAbsent(packageName,
                    audioSession);
            if (currentAudioSession != null) {
                // Compare with passed argument
                if (currentAudioSession == audioSession) {
                    // FIXME: Normally, we should exit the function here
                    // BUT: we have to take care of the virtualizer because of
                    // a bug in the Android Effects Framework
                    // editor.commit();
                    // return;
                    isExistingAudioSession = true;
                } else {
                    closeSession(context, packageName, currentAudioSession);
                }
            }
        } catch (final NullPointerException e) {
            Log.e(TAG, methodTag + e);
            editor.commit();
            return;
        }

        // Because the audioSession is new, get effects & settings from shared preferences

        // Virtualizer
        // create effect
        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
        {
            final String errorTag = methodTag + "Virtualizer error: ";

            try {
                // read parameters
                final boolean isEnabled = prefs.getBoolean(Key.virt_enabled.toString(),
                        VIRTUALIZER_ENABLED_DEFAULT);
                final int strength = prefs.getInt(Key.virt_strength.toString(),
                        VIRTUALIZER_STRENGTH_DEFAULT);
                // init settings
                Virtualizer.Settings settings = new Virtualizer.Settings("Virtualizer;strength="
                        + strength);

                virtualizerEffect.setProperties(settings);

                // set parameters
                if (isGlobalEnabled == true) {
                    virtualizerEffect.setEnabled(isEnabled);
                } else {
                    virtualizerEffect.setEnabled(false);
                }

                // get parameters
                settings = virtualizerEffect.getProperties();
                Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);

                // update preferences
                editor.putBoolean(Key.virt_enabled.toString(), isEnabled);
                editor.putInt(Key.virt_strength.toString(), settings.strength);
            } catch (final RuntimeException e) {
                Log.e(TAG, errorTag + e);
            }
        }

        // In case of an existing audio session
        // Exit after the virtualizer has been re-enabled

        if (isExistingAudioSession) {
            editor.commit();
            return;
        }

        // BassBoost
        // create effect
        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
        {
            final String errorTag = methodTag + "BassBoost error: ";

            try {
                // read parameters
                final boolean isEnabled = prefs.getBoolean(Key.bb_enabled.toString(),
                        BASS_BOOST_ENABLED_DEFAULT);
                final int strength = prefs.getInt(Key.bb_strength.toString(),
                        BASS_BOOST_STRENGTH_DEFAULT);

                // init settings
                BassBoost.Settings settings = new BassBoost.Settings("BassBoost;strength="
                        + strength);

                bassBoostEffect.setProperties(settings);

                // set parameters
                if (isGlobalEnabled == true) {
                    bassBoostEffect.setEnabled(isEnabled);
                } else {
                    bassBoostEffect.setEnabled(false);
                }

                // get parameters
                settings = bassBoostEffect.getProperties();
                Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);

                // update preferences
                editor.putBoolean(Key.bb_enabled.toString(), isEnabled);
                editor.putInt(Key.bb_strength.toString(), settings.strength);
            } catch (final RuntimeException e) {
                Log.e(TAG, errorTag + e);
            }
        }

        // Equalizer
        // create effect
        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
        {
            final String errorTag = methodTag + "Equalizer error: ";

            try {
                final short eQNumBands;
                final short[] bandLevel;
                final int[] eQCenterFreq;
                final short eQNumPresets;
                final String[] eQPresetNames;
                short eQPreset;
                synchronized (mEQInitLock) {
                    // read parameters
                    mEQBandLevelRange = equalizerEffect.getBandLevelRange();
                    mEQNumBands = equalizerEffect.getNumberOfBands();
                    mEQCenterFreq = new int[mEQNumBands];
                    mEQNumPresets = equalizerEffect.getNumberOfPresets();
                    mEQPresetNames = new String[mEQNumPresets];

                    for (short preset = 0; preset < mEQNumPresets; preset++) {
                        mEQPresetNames[preset] = equalizerEffect.getPresetName(preset);
                        editor.putString(Key.eq_preset_name.toString() + preset,
                                mEQPresetNames[preset]);
                    }

                    editor.putInt(Key.eq_level_range.toString() + 0, mEQBandLevelRange[0]);
                    editor.putInt(Key.eq_level_range.toString() + 1, mEQBandLevelRange[1]);
                    editor.putInt(Key.eq_num_bands.toString(), mEQNumBands);
                    editor.putInt(Key.eq_num_presets.toString(), mEQNumPresets);
                    // Resetting the EQ arrays depending on the real # bands with defaults if band <
                    // default size else 0 by copying default arrays over new ones
                    final short[] eQPresetCIExtremeBandLevel = Arrays.copyOf(
                            EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, mEQNumBands);
                    final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
                            EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, mEQNumBands);
                    // If no preset prefs set use CI EXTREME (= numPresets)
                    eQPreset = (short) prefs
                            .getInt(Key.eq_current_preset.toString(), mEQNumPresets);
                    if (eQPreset < mEQNumPresets) {
                        // OpenSL ES effect presets
                        equalizerEffect.usePreset(eQPreset);
                        eQPreset = equalizerEffect.getCurrentPreset();
                    } else {
                        for (short band = 0; band < mEQNumBands; band++) {
                            short level = 0;
                            if (eQPreset == mEQNumPresets) {
                                // CI EXTREME
                                level = eQPresetCIExtremeBandLevel[band];
                            } else {
                                // User
                                level = (short) prefs.getInt(
                                        Key.eq_preset_user_band_level.toString() + band,
                                        eQPresetUserBandLevelDefault[band]);
                            }
                            equalizerEffect.setBandLevel(band, level);
                        }
                    }
                    editor.putInt(Key.eq_current_preset.toString(), eQPreset);

                    bandLevel = new short[mEQNumBands];
                    for (short band = 0; band < mEQNumBands; band++) {
                        mEQCenterFreq[band] = equalizerEffect.getCenterFreq(band);
                        bandLevel[band] = equalizerEffect.getBandLevel(band);

                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel[band]);
                        editor.putInt(Key.eq_center_freq.toString() + band, mEQCenterFreq[band]);
                        editor.putInt(Key.eq_preset_ci_extreme_band_level.toString() + band,
                                eQPresetCIExtremeBandLevel[band]);
                        editor.putInt(Key.eq_preset_user_band_level_default.toString() + band,
                                eQPresetUserBandLevelDefault[band]);
                    }

                    eQNumBands = mEQNumBands;
                    eQCenterFreq = mEQCenterFreq;
                    eQNumPresets = mEQNumPresets;
                    eQPresetNames = mEQPresetNames;
                }

                final boolean isEnabled = prefs.getBoolean(Key.eq_enabled.toString(),
                        EQUALIZER_ENABLED_DEFAULT);
                editor.putBoolean(Key.eq_enabled.toString(), isEnabled);
                if (isGlobalEnabled == true) {
                    equalizerEffect.setEnabled(isEnabled);
                } else {
                    equalizerEffect.setEnabled(false);
                }

                // dump
                Log.v(TAG, "Parameters: Equalizer");
                Log.v(TAG, "bands=" + eQNumBands);
                String str = "levels=";
                for (short band = 0; band < eQNumBands; band++) {
                    str = str + bandLevel[band] + "; ";
                }
                Log.v(TAG, str);
                str = "center=";
                for (short band = 0; band < eQNumBands; band++) {
                    str = str + eQCenterFreq[band] + "; ";
                }
                Log.v(TAG, str);
                str = "presets=";
                for (short preset = 0; preset < eQNumPresets; preset++) {
                    str = str + eQPresetNames[preset] + "; ";
                }
                Log.v(TAG, str);
                Log.v(TAG, "current=" + eQPreset);
            } catch (final RuntimeException e) {
                Log.e(TAG, errorTag + e);
            }
        }

        // XXX: Preset Reverb not used for the moment, so commented out the effect creation to not
        // use MIPS left in the code for (future) reference.
        // Preset reverb
        // create effect
        // final PresetReverb presetReverbEffect = getPresetReverbEffect(audioSession);
        // {
        // final String errorTag = methodTag + "PresetReverb error: ";
        //
        // try {
        // // read parameters
        // final boolean isEnabled = prefs.getBoolean(Key.pr_enabled.toString(),
        // PRESET_REVERB_ENABLED_DEFAULT);
        // final short preset = (short) prefs.getInt(Key.pr_current_preset.toString(),
        // PRESET_REVERB_CURRENT_PRESET_DEFAULT);
        //
        // // init settings
        // PresetReverb.Settings settings = new PresetReverb.Settings("PresetReverb;preset="
        // + preset);
        //
        // // read/update preferences
        // presetReverbEffect.setProperties(settings);
        //
        // // set parameters
        // if (isGlobalEnabled == true) {
        // presetReverbEffect.setEnabled(isEnabled);
        // } else {
        // presetReverbEffect.setEnabled(false);
        // }
        //
        // // get parameters
        // settings = presetReverbEffect.getProperties();
        // Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);
        //
        // // update preferences
        // editor.putBoolean(Key.pr_enabled.toString(), isEnabled);
        // editor.putInt(Key.pr_current_preset.toString(), settings.preset);
        // } catch (final RuntimeException e) {
        // Log.e(TAG, errorTag + e);
        // }
        // }
        editor.commit();
    }

    /**
     * Closes the audio session (release effects) for the given session
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     */
    public static void closeSession(final Context context, final String packageName,
            final int audioSession) {
        Log.v(TAG, "closeSession(" + context + ", " + packageName + ", " + audioSession + ")");

        // PresetReverb
        final PresetReverb presetReverb = mPresetReverbInstances.remove(audioSession);
        if (presetReverb != null) {
            presetReverb.release();
        }
        // Equalizer
        final Equalizer equalizer = mEQInstances.remove(audioSession);
        if (equalizer != null) {
            equalizer.release();
        }
        // BassBoost
        final BassBoost bassBoost = mBassBoostInstances.remove(audioSession);
        if (bassBoost != null) {
            bassBoost.release();
        }
        // Virtualizer
        final Virtualizer virtualizer = mVirtualizerInstances.remove(audioSession);
        if (virtualizer != null) {
            virtualizer.release();
        }

        mPackageSessions.remove(packageName);
    }

    /**
     * Enables or disables all effects (global enable/disable) for a given context, package name and
     * audio session. It sets/inits the control mode and preferences and then sets the global
     * enabled parameter.
     *
     * @param context
     * @param packageName
     * @param audioSession
     *            System wide unique audio session identifier.
     * @param enabled
     */
    public static void setEnabledAll(final Context context, final String packageName,
            final int audioSession, final boolean enabled) {
        initEffectsPreferences(context, packageName, audioSession);
        setParameterBoolean(context, packageName, audioSession, Key.global_enabled, enabled);
    }

    /**
     * Gets the virtualizer effect for the given audio session. If the effect on the session doesn't
     * exist yet, create it and add to collection.
     *
     * @param audioSession
     *            System wide unique audio session identifier.
     * @return virtualizerEffect
     */
    private static Virtualizer getVirtualizerEffectNoCreate(final int audioSession) {
        return mVirtualizerInstances.get(audioSession);
    }
    private static Virtualizer getVirtualizerEffect(final int audioSession) {
        Virtualizer virtualizerEffect = getVirtualizerEffectNoCreate(audioSession);
        if (virtualizerEffect == null) {
            try {
                final Virtualizer newVirtualizerEffect = new Virtualizer(PRIORITY, audioSession);
                virtualizerEffect = mVirtualizerInstances.putIfAbsent(audioSession,
                        newVirtualizerEffect);
                if (virtualizerEffect == null) {
                    // put succeeded, use new value
                    virtualizerEffect = newVirtualizerEffect;
                }
            } catch (final IllegalArgumentException e) {
                Log.e(TAG, "Virtualizer: " + e);
            } catch (final UnsupportedOperationException e) {
                Log.e(TAG, "Virtualizer: " + e);
            } catch (final RuntimeException e) {
                Log.e(TAG, "Virtualizer: " + e);
            }
        }
        return virtualizerEffect;
    }

    /**
     * Gets the bass boost effect for the given audio session. If the effect on the session doesn't
     * exist yet, create it and add to collection.
     *
     * @param audioSession
     *            System wide unique audio session identifier.
     * @return bassBoostEffect
     */
    private static BassBoost getBassBoostEffectNoCreate(final int audioSession) {
        return mBassBoostInstances.get(audioSession);
    }
    private static BassBoost getBassBoostEffect(final int audioSession) {

        BassBoost bassBoostEffect = getBassBoostEffectNoCreate(audioSession);
        if (bassBoostEffect == null) {
            try {
                final BassBoost newBassBoostEffect = new BassBoost(PRIORITY, audioSession);
                bassBoostEffect = mBassBoostInstances.putIfAbsent(audioSession, newBassBoostEffect);
                if (bassBoostEffect == null) {
                    // put succeeded, use new value
                    bassBoostEffect = newBassBoostEffect;
                }
            } catch (final IllegalArgumentException e) {
                Log.e(TAG, "BassBoost: " + e);
            } catch (final UnsupportedOperationException e) {
                Log.e(TAG, "BassBoost: " + e);
            } catch (final RuntimeException e) {
                Log.e(TAG, "BassBoost: " + e);
            }
        }
        return bassBoostEffect;
    }

    /**
     * Gets the equalizer effect for the given audio session. If the effect on the session doesn't
     * exist yet, create it and add to collection.
     *
     * @param audioSession
     *            System wide unique audio session identifier.
     * @return equalizerEffect
     */
    private static Equalizer getEqualizerEffectNoCreate(final int audioSession) {
        return mEQInstances.get(audioSession);
    }
    private static Equalizer getEqualizerEffect(final int audioSession) {
        Equalizer equalizerEffect = getEqualizerEffectNoCreate(audioSession);
        if (equalizerEffect == null) {
            try {
                final Equalizer newEqualizerEffect = new Equalizer(PRIORITY, audioSession);
                equalizerEffect = mEQInstances.putIfAbsent(audioSession, newEqualizerEffect);
                if (equalizerEffect == null) {
                    // put succeeded, use new value
                    equalizerEffect = newEqualizerEffect;
                }
            } catch (final IllegalArgumentException e) {
                Log.e(TAG, "Equalizer: " + e);
            } catch (final UnsupportedOperationException e) {
                Log.e(TAG, "Equalizer: " + e);
            } catch (final RuntimeException e) {
                Log.e(TAG, "Equalizer: " + e);
            }
        }
        return equalizerEffect;
    }

    // XXX: Preset Reverb not used for the moment, so commented out the effect creation to not
    // use MIPS
    // /**
    // * Gets the preset reverb effect for the given audio session. If the effect on the session
    // * doesn't exist yet, create it and add to collection.
    // *
    // * @param audioSession
    // * System wide unique audio session identifier.
    // * @return presetReverbEffect
    // */
    // private static PresetReverb getPresetReverbEffect(final int audioSession) {
    // PresetReverb presetReverbEffect = mPresetReverbInstances.get(audioSession);
    // if (presetReverbEffect == null) {
    // try {
    // final PresetReverb newPresetReverbEffect = new PresetReverb(PRIORITY, audioSession);
    // presetReverbEffect = mPresetReverbInstances.putIfAbsent(audioSession,
    // newPresetReverbEffect);
    // if (presetReverbEffect == null) {
    // // put succeeded, use new value
    // presetReverbEffect = newPresetReverbEffect;
    // }
    // } catch (final IllegalArgumentException e) {
    // Log.e(TAG, "PresetReverb: " + e);
    // } catch (final UnsupportedOperationException e) {
    // Log.e(TAG, "PresetReverb: " + e);
    // } catch (final RuntimeException e) {
    // Log.e(TAG, "PresetReverb: " + e);
    // }
    // }
    // return presetReverbEffect;
    // }
}
