/*
 * 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_supported, 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_band_level_no_save, 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 };

    // 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 =
            new short[EQUALIZER_NUMBER_PRESETS_DEFAULT][EQUALIZER_NUMBER_BANDS_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 Virtualizer virt = new Virtualizer(0, audioSession);
            final int vIStrength = prefs.getInt(Key.virt_strength.toString(),
                    virt.getRoundedStrength());
            virt.release();
            editor.putBoolean(Key.virt_enabled.toString(), isVIEnabled);
            editor.putInt(Key.virt_strength.toString(), vIStrength);
            {
                final MediaPlayer mediaPlayer = new MediaPlayer();
                final int session = mediaPlayer.getAudioSessionId();
                Virtualizer virtualizerEffect = null;
                try {
                    virtualizerEffect = new Virtualizer(PRIORITY, session);
                    editor.putBoolean(Key.virt_strength_supported.toString(),
                            virtualizerEffect.getStrengthSupported());
                } finally {
                    if (virtualizerEffect != null) {
                        Log.d(TAG, "Releasing dummy Virtualizer effect");
                        virtualizerEffect.release();
                    }
                    mediaPlayer.release();
                }
            }

            // 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) {
                            Log.e(TAG, "Error retrieving default EQ values, setting all presets"
                                    + " to flat response");
                            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);
                                mEQPresetOpenSLESBandLevel[preset] = Arrays.copyOf(
                                        EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, 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));
                            int defaultstrength = virtualizerEffect.getRoundedStrength();
                            final int vIStrength = prefs.getInt(Key.virt_strength.toString(),
                                    defaultstrength);
                            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_no_save, 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;
                }
                // Same as eq_band_level except won't save band level in User preset
                case eq_band_level_no_save: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = Key.eq_band_level.toString() + band;
                    final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
                    if (equalizerEffect != null) {
                        equalizerEffect.setBandLevel(band, (short) 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;
                }
                // Same as eq_band_level except won't save band level in User preset
                case eq_band_level_no_save: {
                    if (arg1 == DUMMY_ARGUMENT) {
                        throw new IllegalArgumentException("Dummy arg passed.");
                    }
                    final short band = (short) arg1;
                    strKey = Key.eq_band_level.toString() + band;
                    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(
                            mEQPresetOpenSLESBandLevel, numPresets);
                    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.apply();

        } 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);
                int defaultstrength = isExistingAudioSession ? VIRTUALIZER_STRENGTH_DEFAULT :
                    virtualizerEffect.getRoundedStrength();
                final int strength = prefs.getInt(Key.virt_strength.toString(), defaultstrength);
                // 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.apply();
            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;
    // }
}
