ControlPanelEffect.java revision 024018a9804a4fcd3f8c660d32336e96e39bda8e
1/*
2 * Copyright (C) 2010-2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.musicfx;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.media.MediaPlayer;
22import android.media.audiofx.AudioEffect;
23import android.media.audiofx.BassBoost;
24import android.media.audiofx.Equalizer;
25import android.media.audiofx.PresetReverb;
26import android.media.audiofx.Virtualizer;
27import android.util.Log;
28
29import java.util.Arrays;
30import java.util.concurrent.ConcurrentHashMap;
31
32/**
33 * The Common class defines constants to be used by the control panels.
34 */
35public class ControlPanelEffect {
36
37    private final static String TAG = "MusicFXControlPanelEffect";
38
39    /**
40     * Audio session priority
41     */
42    private static final int PRIORITY = 0;
43
44    /**
45     * The control mode specifies if control panel updates effects and preferences or only
46     * preferences.
47     */
48    static enum ControlMode {
49        /**
50         * Control panel updates effects and preferences. Applicable when audio session is delivered
51         * by user.
52         */
53        CONTROL_EFFECTS,
54        /**
55         * Control panel only updates preferences. Applicable when there was no audio or invalid
56         * session provided by user.
57         */
58        CONTROL_PREFERENCES
59    }
60
61    static enum Key {
62        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
63    }
64
65    // Effect/audio session Mappings
66    /**
67     * Hashmap initial capacity
68     */
69    private static final int HASHMAP_INITIAL_CAPACITY = 16;
70    /**
71     * Hashmap load factor
72     */
73    private static final float HASHMAP_LOAD_FACTOR = 0.75f;
74    /**
75     * ConcurrentHashMap concurrency level
76     */
77    private static final int HASHMAP_CONCURRENCY_LEVEL = 2;
78
79    /**
80     * Map containing the Virtualizer audio session, effect mappings.
81     */
82    private static final ConcurrentHashMap<Integer, Virtualizer> mVirtualizerInstances = new ConcurrentHashMap<Integer, Virtualizer>(
83            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
84    /**
85     * Map containing the BB audio session, effect mappings.
86     */
87    private static final ConcurrentHashMap<Integer, BassBoost> mBassBoostInstances = new ConcurrentHashMap<Integer, BassBoost>(
88            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
89    /**
90     * Map containing the EQ audio session, effect mappings.
91     */
92    private static final ConcurrentHashMap<Integer, Equalizer> mEQInstances = new ConcurrentHashMap<Integer, Equalizer>(
93            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
94    /**
95     * Map containing the PR audio session, effect mappings.
96     */
97    private static final ConcurrentHashMap<Integer, PresetReverb> mPresetReverbInstances = new ConcurrentHashMap<Integer, PresetReverb>(
98            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
99
100    /**
101     * Map containing the package name, audio session mappings.
102     */
103    private static final ConcurrentHashMap<String, Integer> mPackageSessions = new ConcurrentHashMap<String, Integer>(
104            HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, HASHMAP_CONCURRENCY_LEVEL);
105
106    // Defaults
107    final static boolean GLOBAL_ENABLED_DEFAULT = false;
108    private final static boolean VIRTUALIZER_ENABLED_DEFAULT = true;
109    private final static int VIRTUALIZER_STRENGTH_DEFAULT = 1000;
110    private final static boolean BASS_BOOST_ENABLED_DEFAULT = true;
111    private final static int BASS_BOOST_STRENGTH_DEFAULT = 667;
112    private final static boolean PRESET_REVERB_ENABLED_DEFAULT = false;
113    private final static int PRESET_REVERB_CURRENT_PRESET_DEFAULT = 0; // None
114
115    // EQ defaults
116    private final static boolean EQUALIZER_ENABLED_DEFAULT = true;
117    private final static String EQUALIZER_PRESET_NAME_DEFAULT = "Preset";
118    private final static short EQUALIZER_NUMBER_BANDS_DEFAULT = 5;
119    private final static short EQUALIZER_NUMBER_PRESETS_DEFAULT = 0;
120    private final static short[] EQUALIZER_BAND_LEVEL_RANGE_DEFAULT = { -1500, 1500 };
121    private final static int[] EQUALIZER_CENTER_FREQ_DEFAULT = { 60000, 230000, 910000, 3600000,
122            14000000 };
123    private final static short[] EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL = { 0, 800, 400, 100, 1000 };
124    private final static short[] EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT = { 0, 0, 0, 0, 0 };
125    private final static short[][] EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT = new short[EQUALIZER_NUMBER_PRESETS_DEFAULT][EQUALIZER_NUMBER_BANDS_DEFAULT];
126
127    // EQ effect properties which are invariable over all EQ effects sessions
128    private static short[] mEQBandLevelRange = EQUALIZER_BAND_LEVEL_RANGE_DEFAULT;
129    private static short mEQNumBands = EQUALIZER_NUMBER_BANDS_DEFAULT;
130    private static int[] mEQCenterFreq = EQUALIZER_CENTER_FREQ_DEFAULT;
131    private static short mEQNumPresets = EQUALIZER_NUMBER_PRESETS_DEFAULT;
132    private static short[][] mEQPresetOpenSLESBandLevel = EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT;
133    private static String[] mEQPresetNames;
134    private static boolean mIsEQInitialized = false;
135    private final static Object mEQInitLock = new Object();
136
137    /**
138     * Default int argument used in methods to see that the arg is a dummy. Used for method
139     * overloading.
140     */
141    private final static int DUMMY_ARGUMENT = -1;
142
143    /**
144     * Inits effects preferences for the given context and package name in the control panel. If
145     * preferences for the given package name don't exist, they are created and initialized.
146     *
147     * @param context
148     * @param packageName
149     * @param audioSession
150     *            System wide unique audio session identifier.
151     */
152    public static void initEffectsPreferences(final Context context, final String packageName,
153            final int audioSession) {
154        final SharedPreferences prefs = context.getSharedPreferences(packageName,
155                Context.MODE_PRIVATE);
156        final SharedPreferences.Editor editor = prefs.edit();
157        final ControlMode controlMode = getControlMode(audioSession);
158
159        // init preferences
160        try {
161            // init global on/off switch
162            final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
163                    GLOBAL_ENABLED_DEFAULT);
164            editor.putBoolean(Key.global_enabled.toString(), isGlobalEnabled);
165            Log.v(TAG, "isGlobalEnabled = " + isGlobalEnabled);
166
167            // Virtualizer
168            final boolean isVIEnabled = prefs.getBoolean(Key.virt_enabled.toString(),
169                    VIRTUALIZER_ENABLED_DEFAULT);
170            final int vIStrength = prefs.getInt(Key.virt_strength.toString(),
171                    VIRTUALIZER_STRENGTH_DEFAULT);
172            editor.putBoolean(Key.virt_enabled.toString(), isVIEnabled);
173            editor.putInt(Key.virt_strength.toString(), vIStrength);
174            // BassBoost
175            final boolean isBBEnabled = prefs.getBoolean(Key.bb_enabled.toString(),
176                    BASS_BOOST_ENABLED_DEFAULT);
177            final int bBStrength = prefs.getInt(Key.bb_strength.toString(),
178                    BASS_BOOST_STRENGTH_DEFAULT);
179            editor.putBoolean(Key.bb_enabled.toString(), isBBEnabled);
180            editor.putInt(Key.bb_strength.toString(), bBStrength);
181            // Equalizer
182            synchronized (mEQInitLock) {
183                // If EQ is not initialized already create "dummy" audio session created by
184                // MediaPlayer and create effect on it to retrieve the invariable EQ properties
185                if (!mIsEQInitialized) {
186                    final MediaPlayer mediaPlayer = new MediaPlayer();
187                    final int session = mediaPlayer.getAudioSessionId();
188                    Equalizer equalizerEffect = null;
189                    try {
190                        Log.d(TAG, "Creating dummy EQ effect");
191                        equalizerEffect = new Equalizer(PRIORITY, session);
192
193                        mEQBandLevelRange = equalizerEffect.getBandLevelRange();
194                        mEQNumBands = equalizerEffect.getNumberOfBands();
195                        mEQCenterFreq = new int[mEQNumBands];
196                        for (short band = 0; band < mEQNumBands; band++) {
197                            mEQCenterFreq[band] = equalizerEffect.getCenterFreq(band);
198                        }
199                        mEQNumPresets = equalizerEffect.getNumberOfPresets();
200                        mEQPresetNames = new String[mEQNumPresets];
201                        mEQPresetOpenSLESBandLevel = new short[mEQNumPresets][mEQNumBands];
202                        for (short preset = 0; preset < mEQNumPresets; preset++) {
203                            mEQPresetNames[preset] = equalizerEffect.getPresetName(preset);
204                            equalizerEffect.usePreset(preset);
205                            for (short band = 0; band < mEQNumBands; band++) {
206                                mEQPresetOpenSLESBandLevel[preset][band] = equalizerEffect
207                                        .getBandLevel(band);
208                            }
209                        }
210
211                        mIsEQInitialized = true;
212                    } catch (final IllegalStateException e) {
213                        Log.e(TAG, "Equalizer: " + e);
214                    } catch (final IllegalArgumentException e) {
215                        Log.e(TAG, "Equalizer: " + e);
216                    } catch (final UnsupportedOperationException e) {
217                        Log.e(TAG, "Equalizer: " + e);
218                    } catch (final RuntimeException e) {
219                        Log.e(TAG, "Equalizer: " + e);
220                    } finally {
221                        if (equalizerEffect != null) {
222                            equalizerEffect.release();
223                        }
224                        mediaPlayer.release();
225
226                        // When there was a failure set some good defaults
227                        if (!mIsEQInitialized) {
228                            mEQPresetOpenSLESBandLevel = new short[mEQNumPresets][mEQNumBands];
229                            for (short preset = 0; preset < mEQNumPresets; preset++) {
230                                // Init preset names to a dummy name
231                                mEQPresetNames[preset] = prefs.getString(
232                                        Key.eq_preset_name.toString() + preset,
233                                        EQUALIZER_PRESET_NAME_DEFAULT + preset);
234                                if (preset < EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT.length) {
235                                    mEQPresetOpenSLESBandLevel[preset] = Arrays.copyOf(
236                                            EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT[preset],
237                                            mEQNumBands);
238                                }
239                            }
240                        }
241                    }
242                }
243                editor.putInt(Key.eq_level_range.toString() + 0, mEQBandLevelRange[0]);
244                editor.putInt(Key.eq_level_range.toString() + 1, mEQBandLevelRange[1]);
245                editor.putInt(Key.eq_num_bands.toString(), mEQNumBands);
246                editor.putInt(Key.eq_num_presets.toString(), mEQNumPresets);
247                // Resetting the EQ arrays depending on the real # bands with defaults if
248                // band < default size else 0 by copying default arrays over new ones
249                final short[] eQPresetCIExtremeBandLevel = Arrays.copyOf(
250                        EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, mEQNumBands);
251                final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
252                        EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, mEQNumBands);
253                // If no preset prefs set use CI EXTREME (= numPresets)
254                final short eQPreset = (short) prefs.getInt(Key.eq_current_preset.toString(),
255                        mEQNumPresets);
256                editor.putInt(Key.eq_current_preset.toString(), eQPreset);
257                final short[] bandLevel = new short[mEQNumBands];
258                for (short band = 0; band < mEQNumBands; band++) {
259                    if (controlMode == ControlMode.CONTROL_PREFERENCES) {
260                        if (eQPreset < mEQNumPresets) {
261                            // OpenSL ES effect presets
262                            bandLevel[band] = mEQPresetOpenSLESBandLevel[eQPreset][band];
263                        } else if (eQPreset == mEQNumPresets) {
264                            // CI EXTREME
265                            bandLevel[band] = eQPresetCIExtremeBandLevel[band];
266                        } else {
267                            // User
268                            bandLevel[band] = (short) prefs.getInt(
269                                    Key.eq_preset_user_band_level.toString() + band,
270                                    eQPresetUserBandLevelDefault[band]);
271                        }
272                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel[band]);
273                    }
274                    editor.putInt(Key.eq_center_freq.toString() + band, mEQCenterFreq[band]);
275                    editor.putInt(Key.eq_preset_ci_extreme_band_level.toString() + band,
276                            eQPresetCIExtremeBandLevel[band]);
277                    editor.putInt(Key.eq_preset_user_band_level_default.toString() + band,
278                            eQPresetUserBandLevelDefault[band]);
279                }
280                for (short preset = 0; preset < mEQNumPresets; preset++) {
281                    editor.putString(Key.eq_preset_name.toString() + preset, mEQPresetNames[preset]);
282                    for (short band = 0; band < mEQNumBands; band++) {
283                        editor.putInt(Key.eq_preset_opensl_es_band_level.toString() + preset + "_"
284                                + band, mEQPresetOpenSLESBandLevel[preset][band]);
285                    }
286                }
287            }
288            final boolean isEQEnabled = prefs.getBoolean(Key.eq_enabled.toString(),
289                    EQUALIZER_ENABLED_DEFAULT);
290            editor.putBoolean(Key.eq_enabled.toString(), isEQEnabled);
291
292            // Preset reverb
293            final boolean isEnabledPR = prefs.getBoolean(Key.pr_enabled.toString(),
294                    PRESET_REVERB_ENABLED_DEFAULT);
295            final short presetPR = (short) prefs.getInt(Key.pr_current_preset.toString(),
296                    PRESET_REVERB_CURRENT_PRESET_DEFAULT);
297            editor.putBoolean(Key.pr_enabled.toString(), isEnabledPR);
298            editor.putInt(Key.pr_current_preset.toString(), presetPR);
299
300            editor.commit();
301        } catch (final RuntimeException e) {
302            Log.e(TAG, "initEffectsPreferences: processingEnabled: " + e);
303        }
304    }
305
306    /**
307     * Gets the effect control mode based on the given audio session in the control panel. Control
308     * mode defines if the control panel is controlling effects and/or preferences
309     *
310     * @param audioSession
311     *            System wide unique audio session identifier.
312     * @return effect control mode
313     */
314    public static ControlMode getControlMode(final int audioSession) {
315        if (audioSession == AudioEffect.ERROR_BAD_VALUE) {
316            return ControlMode.CONTROL_PREFERENCES;
317        }
318        return ControlMode.CONTROL_EFFECTS;
319    }
320
321    /**
322     * Sets boolean parameter to value for given key
323     *
324     * @param context
325     * @param packageName
326     * @param audioSession
327     *            System wide unique audio session identifier.
328     * @param key
329     * @param value
330     */
331    public static void setParameterBoolean(final Context context, final String packageName,
332            final int audioSession, final Key key, final boolean value) {
333        try {
334            final SharedPreferences prefs = context.getSharedPreferences(packageName,
335                    Context.MODE_PRIVATE);
336            final ControlMode controlMode = getControlMode(audioSession);
337            boolean enabled = value;
338
339            // Global on/off
340            if (key == Key.global_enabled) {
341                boolean processingEnabled = false;
342                if (value == true) {
343                    // enable all with respect to preferences
344                    if (controlMode == ControlMode.CONTROL_EFFECTS) {
345                        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
346                        if (virtualizerEffect != null) {
347                            virtualizerEffect.setEnabled(prefs.getBoolean(
348                                    Key.virt_enabled.toString(), VIRTUALIZER_ENABLED_DEFAULT));
349                        }
350                        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
351                        if (bassBoostEffect != null) {
352                            bassBoostEffect.setEnabled(prefs.getBoolean(Key.bb_enabled.toString(),
353                                    BASS_BOOST_ENABLED_DEFAULT));
354                        }
355                        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
356                        if (equalizerEffect != null) {
357                            equalizerEffect.setEnabled(prefs.getBoolean(Key.eq_enabled.toString(),
358                                    EQUALIZER_ENABLED_DEFAULT));
359                        }
360                        // XXX: Preset Reverb not used for the moment, so commented out the effect
361                        // creation to not use MIPS
362                        // final PresetReverb presetReverbEffect =
363                        // getPresetReverbEffect(audioSession);
364                        // if (presetReverbEffect != null) {
365                        // presetReverbEffect.setEnabled(prefs.getBoolean(
366                        // Key.pr_enabled.toString(), PRESET_REVERB_ENABLED_DEFAULT));
367                        // }
368                    }
369
370                    processingEnabled = true;
371                    Log.v(TAG, "processingEnabled=" + processingEnabled);
372
373                } else {
374                    // disable all
375                    if (controlMode == ControlMode.CONTROL_EFFECTS) {
376                        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
377                        if (virtualizerEffect != null) {
378                            virtualizerEffect.setEnabled(false);
379                        }
380                        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
381                        if (bassBoostEffect != null) {
382                            bassBoostEffect.setEnabled(false);
383                        }
384                        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
385                        if (equalizerEffect != null) {
386                            equalizerEffect.setEnabled(false);
387                        }
388                        // XXX: Preset Reverb not used for the moment, so commented out the effect
389                        // creation to not use MIPS
390                        // final PresetReverb presetReverbEffect =
391                        // getPresetReverbEffect(audioSession);
392                        // if (presetReverbEffect != null) {
393                        // presetReverbEffect.setEnabled(false);
394                        // }
395                    }
396
397                    processingEnabled = false;
398                    Log.v(TAG, "processingEnabled=" + processingEnabled);
399                }
400                enabled = processingEnabled;
401            } else if (controlMode == ControlMode.CONTROL_EFFECTS) {
402                final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
403                        GLOBAL_ENABLED_DEFAULT);
404                if (isGlobalEnabled == true) {
405                    // Set effect parameters
406                    switch (key) {
407
408                    case global_enabled:
409                        // Global, already handled, to get out error free
410                        break;
411
412                    // Virtualizer
413                    case virt_enabled:
414                        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
415                        if (virtualizerEffect != null) {
416                            virtualizerEffect.setEnabled(value);
417                            enabled = virtualizerEffect.getEnabled();
418                        }
419                        break;
420
421                    // BassBoost
422                    case bb_enabled:
423                        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
424                        if (bassBoostEffect != null) {
425                            bassBoostEffect.setEnabled(value);
426                            enabled = bassBoostEffect.getEnabled();
427                        }
428                        break;
429
430                    // Equalizer
431                    case eq_enabled:
432                        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
433                        if (equalizerEffect != null) {
434                            equalizerEffect.setEnabled(value);
435                            enabled = equalizerEffect.getEnabled();
436                        }
437                        break;
438
439                    // PresetReverb
440                    case pr_enabled:
441                        // XXX: Preset Reverb not used for the moment, so commented out the effect
442                        // creation to not use MIPS
443                        // final PresetReverb presetReverbEffect =
444                        // getPresetReverbEffect(audioSession);
445                        // if (presetReverbEffect != null) {
446                        // presetReverbEffect.setEnabled(value);
447                        // enabled = presetReverbEffect.getEnabled();
448                        // }
449                        break;
450
451                    default:
452                        Log.e(TAG, "Unknown/unsupported key " + key);
453                        return;
454                    }
455                }
456
457            }
458
459            // Set preferences
460            final SharedPreferences.Editor editor = prefs.edit();
461            editor.putBoolean(key.toString(), enabled);
462            editor.commit();
463
464        } catch (final RuntimeException e) {
465            Log.e(TAG, "setParameterBoolean: " + key + "; " + value + "; " + e);
466        }
467    }
468
469    /**
470     * Gets boolean parameter for given key
471     *
472     * @param context
473     * @param packageName
474     * @param audioSession
475     *            System wide unique audio session identifier.
476     * @param key
477     * @return parameter value
478     */
479    public static Boolean getParameterBoolean(final Context context, final String packageName,
480            final int audioSession, final Key key) {
481        final SharedPreferences prefs = context.getSharedPreferences(packageName,
482                Context.MODE_PRIVATE);
483        boolean value = false;
484
485        try {
486            value = prefs.getBoolean(key.toString(), value);
487        } catch (final RuntimeException e) {
488            Log.e(TAG, "getParameterBoolean: " + key + "; " + value + "; " + e);
489        }
490
491        return value;
492
493    }
494
495    /**
496     * Sets int parameter for given key and value arg0, arg1
497     *
498     * @param context
499     * @param packageName
500     * @param audioSession
501     *            System wide unique audio session identifier.
502     * @param key
503     * @param arg0
504     * @param arg1
505     */
506    public static void setParameterInt(final Context context, final String packageName,
507            final int audioSession, final Key key, final int arg0, final int arg1) {
508        String strKey = key.toString();
509        int value = arg0;
510
511        try {
512            final SharedPreferences prefs = context.getSharedPreferences(packageName,
513                    Context.MODE_PRIVATE);
514            final SharedPreferences.Editor editor = prefs.edit();
515            final ControlMode controlMode = getControlMode(audioSession);
516
517            // Set effect parameters
518            if (controlMode == ControlMode.CONTROL_EFFECTS) {
519
520                switch (key) {
521
522                // Virtualizer
523                case virt_strength: {
524                    final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
525                    if (virtualizerEffect != null) {
526                        virtualizerEffect.setStrength((short) value);
527                        value = virtualizerEffect.getRoundedStrength();
528                    }
529                    break;
530                }
531                    // BassBoost
532                case bb_strength: {
533                    final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
534                    if (bassBoostEffect != null) {
535                        bassBoostEffect.setStrength((short) value);
536                        value = bassBoostEffect.getRoundedStrength();
537                    }
538                    break;
539                }
540                    // Equalizer
541                case eq_band_level: {
542                    if (arg1 == DUMMY_ARGUMENT) {
543                        throw new IllegalArgumentException("Dummy arg passed.");
544                    }
545                    final short band = (short) arg1;
546                    strKey = strKey + band;
547                    final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
548                    if (equalizerEffect != null) {
549                        equalizerEffect.setBandLevel(band, (short) value);
550                        value = equalizerEffect.getBandLevel(band);
551                        // save band level in User preset
552                        editor.putInt(Key.eq_preset_user_band_level.toString() + band, value);
553                    }
554                    break;
555                }
556                case eq_current_preset: {
557                    final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
558                    if (equalizerEffect != null) {
559                        final short preset = (short) value;
560                        final int numBands = prefs.getInt(Key.eq_num_bands.toString(),
561                                EQUALIZER_NUMBER_BANDS_DEFAULT);
562                        final int numPresets = prefs.getInt(Key.eq_num_presets.toString(),
563                                EQUALIZER_NUMBER_PRESETS_DEFAULT);
564
565                        if (preset < numPresets) {
566                            // OpenSL ES EQ Effect presets
567                            equalizerEffect.usePreset(preset);
568                            value = equalizerEffect.getCurrentPreset();
569                        } else {
570                            final short[] eQPresetCIExtremeBandLevelDefault = Arrays.copyOf(
571                                    EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, numBands);
572                            final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
573                                    EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, numBands);
574                            // Set the band levels manually for custom presets
575                            for (short band = 0; band < numBands; band++) {
576                                short bandLevel = 0;
577                                if (preset == numPresets) {
578                                    // CI EXTREME
579                                    bandLevel = (short) prefs.getInt(
580                                            Key.eq_preset_ci_extreme_band_level.toString() + band,
581                                            eQPresetCIExtremeBandLevelDefault[band]);
582                                } else {
583                                    // User
584                                    bandLevel = (short) prefs.getInt(
585                                            Key.eq_preset_user_band_level.toString() + band,
586                                            eQPresetUserBandLevelDefault[band]);
587                                }
588                                equalizerEffect.setBandLevel(band, bandLevel);
589                            }
590                        }
591
592                        // update band levels
593                        for (short band = 0; band < numBands; band++) {
594                            final short level = equalizerEffect.getBandLevel(band);
595                            editor.putInt(Key.eq_band_level.toString() + band, level);
596                        }
597                    }
598                    break;
599                }
600                case eq_preset_user_band_level:
601                    // Fall through
602                case eq_preset_user_band_level_default:
603                    // Fall through
604                case eq_preset_ci_extreme_band_level: {
605                    if (arg1 == DUMMY_ARGUMENT) {
606                        throw new IllegalArgumentException("Dummy arg passed.");
607                    }
608                    final short band = (short) arg1;
609                    strKey = strKey + band;
610                    break;
611                }
612                case pr_current_preset:
613                    // XXX: Preset Reverb not used for the moment, so commented out the effect
614                    // creation to not use MIPS
615                    // final PresetReverb presetReverbEffect = getPresetReverbEffect(audioSession);
616                    // if (presetReverbEffect != null) {
617                    // presetReverbEffect.setPreset((short) value);
618                    // value = presetReverbEffect.getPreset();
619                    // }
620                    break;
621                default:
622                    Log.e(TAG, "setParameterInt: Unknown/unsupported key " + key);
623                    return;
624                }
625            } else {
626                switch (key) {
627                // Virtualizer
628                case virt_strength:
629                    // Do nothing
630                    break;
631                case virt_type:
632                    // Do nothing
633                    break;
634
635                // BassBoost
636                case bb_strength:
637                    // Do nothing
638                    break;
639
640                // Equalizer
641                case eq_band_level: {
642                    if (arg1 == DUMMY_ARGUMENT) {
643                        throw new IllegalArgumentException("Dummy arg passed.");
644                    }
645                    final short band = (short) arg1;
646                    strKey = strKey + band;
647
648                    editor.putInt(Key.eq_preset_user_band_level.toString() + band, value);
649                    break;
650                }
651                case eq_current_preset: {
652                    final short preset = (short) value;
653                    final int numBands = prefs.getInt(Key.eq_num_bands.toString(),
654                            EQUALIZER_NUMBER_BANDS_DEFAULT);
655                    final int numPresets = prefs.getInt(Key.eq_num_presets.toString(),
656                            EQUALIZER_NUMBER_PRESETS_DEFAULT);
657
658                    final short[][] eQPresetOpenSLESBandLevelDefault = Arrays.copyOf(
659                            EQUALIZER_PRESET_OPENSL_ES_BAND_LEVEL_DEFAULT, numBands);
660                    final short[] eQPresetCIExtremeBandLevelDefault = Arrays.copyOf(
661                            EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, numBands);
662                    final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
663                            EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, numBands);
664                    for (short band = 0; band < numBands; band++) {
665                        short bandLevel = 0;
666                        if (preset < numPresets) {
667                            // OpenSL ES EQ Effect presets
668                            bandLevel = (short) prefs.getInt(
669                                    Key.eq_preset_opensl_es_band_level.toString() + preset + "_"
670                                            + band, eQPresetOpenSLESBandLevelDefault[preset][band]);
671                        } else if (preset == numPresets) {
672                            // CI EXTREME
673                            bandLevel = (short) prefs.getInt(
674                                    Key.eq_preset_ci_extreme_band_level.toString() + band,
675                                    eQPresetCIExtremeBandLevelDefault[band]);
676                        } else {
677                            // User
678                            bandLevel = (short) prefs.getInt(
679                                    Key.eq_preset_user_band_level.toString() + band,
680                                    eQPresetUserBandLevelDefault[band]);
681                        }
682                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel);
683                    }
684                    break;
685                }
686                case eq_preset_user_band_level:
687                    // Fall through
688                case eq_preset_user_band_level_default:
689                    // Fall through
690                case eq_preset_ci_extreme_band_level: {
691                    if (arg1 == DUMMY_ARGUMENT) {
692                        throw new IllegalArgumentException("Dummy arg passed.");
693                    }
694                    final short band = (short) arg1;
695                    strKey = strKey + band;
696                    break;
697                }
698                case pr_current_preset:
699                    // Do nothing
700                    break;
701                default:
702                    Log.e(TAG, "setParameterInt: Unknown/unsupported key " + key);
703                    return;
704                }
705            }
706
707            // Set preferences
708            editor.putInt(strKey, value);
709            editor.commit();
710
711        } catch (final RuntimeException e) {
712            Log.e(TAG, "setParameterInt: " + key + "; " + arg0 + "; " + arg1 + "; " + e);
713        }
714
715    }
716
717    /**
718     * Sets int parameter for given key and value arg
719     *
720     * @param context
721     * @param packageName
722     * @param audioSession
723     *            System wide unique audio session identifier.
724     * @param key
725     * @param arg
726     */
727    public static void setParameterInt(final Context context, final String packageName,
728            final int audioSession, final Key key, final int arg) {
729        setParameterInt(context, packageName, audioSession, key, arg, DUMMY_ARGUMENT);
730    }
731
732    /**
733     * Gets int parameter given key
734     *
735     * @param context
736     * @param packageName
737     * @param audioSession
738     *            System wide unique audio session identifier.
739     * @param key
740     * @return parameter value
741     */
742    public static int getParameterInt(final Context context, final String packageName,
743            final int audioSession, final String key) {
744        int value = 0;
745
746        try {
747            final SharedPreferences prefs = context.getSharedPreferences(packageName,
748                    Context.MODE_PRIVATE);
749            value = prefs.getInt(key, value);
750        } catch (final RuntimeException e) {
751            Log.e(TAG, "getParameterInt: " + key + "; " + e);
752        }
753
754        return value;
755    }
756
757    /**
758     * Gets int parameter given key
759     *
760     * @param context
761     * @param packageName
762     * @param audioSession
763     *            System wide unique audio session identifier.
764     * @param key
765     * @return parameter value
766     */
767    public static int getParameterInt(final Context context, final String packageName,
768            final int audioSession, final Key key) {
769        return getParameterInt(context, packageName, audioSession, key.toString());
770    }
771
772    /**
773     * Gets int parameter given key and arg
774     *
775     * @param context
776     * @param packageName
777     * @param audioSession
778     *            System wide unique audio session identifier.
779     * @param audioSession
780     * @param key
781     * @param arg
782     * @return parameter value
783     */
784    public static int getParameterInt(final Context context, final String packageName,
785            final int audioSession, final Key key, final int arg) {
786        return getParameterInt(context, packageName, audioSession, key.toString() + arg);
787    }
788
789    /**
790     * Gets int parameter given key, arg0 and arg1
791     *
792     * @param context
793     * @param packageName
794     * @param audioSession
795     *            System wide unique audio session identifier.
796     * @param audioSession
797     * @param key
798     * @param arg0
799     * @param arg1
800     * @return parameter value
801     */
802    public static int getParameterInt(final Context context, final String packageName,
803            final int audioSession, final Key key, final int arg0, final int arg1) {
804        return getParameterInt(context, packageName, audioSession, key.toString() + arg0 + "_"
805                + arg1);
806    }
807
808    /**
809     * Gets integer array parameter given key. Returns null if not found.
810     *
811     * @param context
812     * @param packageName
813     * @param audioSession
814     *            System wide unique audio session identifier.
815     * @param key
816     * @return parameter value array
817     */
818    public static int[] getParameterIntArray(final Context context, final String packageName,
819            final int audioSession, final Key key) {
820        final SharedPreferences prefs = context.getSharedPreferences(packageName,
821                Context.MODE_PRIVATE);
822
823        int[] intArray = null;
824        try {
825            // Get effect parameters
826            switch (key) {
827            case eq_level_range: {
828                intArray = new int[2];
829                break;
830            }
831            case eq_center_freq:
832                // Fall through
833            case eq_band_level:
834                // Fall through
835            case eq_preset_user_band_level:
836                // Fall through
837            case eq_preset_user_band_level_default:
838                // Fall through
839            case eq_preset_ci_extreme_band_level: {
840                final int numBands = prefs.getInt(Key.eq_num_bands.toString(), 0);
841                intArray = new int[numBands];
842                break;
843            }
844            default:
845                Log.e(TAG, "getParameterIntArray: Unknown/unsupported key " + key);
846                return null;
847            }
848
849            for (int i = 0; i < intArray.length; i++) {
850                intArray[i] = prefs.getInt(key.toString() + i, 0);
851            }
852
853        } catch (final RuntimeException e) {
854            Log.e(TAG, "getParameterIntArray: " + key + "; " + e);
855        }
856
857        return intArray;
858    }
859
860    /**
861     * Gets string parameter given key. Returns empty string if not found.
862     *
863     * @param context
864     * @param packageName
865     * @param audioSession
866     *            System wide unique audio session identifier.
867     * @param key
868     * @return parameter value
869     */
870    public static String getParameterString(final Context context, final String packageName,
871            final int audioSession, final String key) {
872        String value = "";
873        try {
874            final SharedPreferences prefs = context.getSharedPreferences(packageName,
875                    Context.MODE_PRIVATE);
876
877            // Get effect parameters
878            value = prefs.getString(key, value);
879
880        } catch (final RuntimeException e) {
881            Log.e(TAG, "getParameterString: " + key + "; " + e);
882        }
883
884        return value;
885    }
886
887    /**
888     * Gets string parameter given key.
889     *
890     * @param context
891     * @param packageName
892     * @param audioSession
893     *            System wide unique audio session identifier.
894     * @param key
895     * @return parameter value
896     */
897    public static String getParameterString(final Context context, final String packageName,
898            final int audioSession, final Key key) {
899        return getParameterString(context, packageName, audioSession, key.toString());
900    }
901
902    /**
903     * Gets string parameter given key and arg.
904     *
905     * @param context
906     * @param packageName
907     * @param audioSession
908     *            System wide unique audio session identifier.
909     * @param args
910     * @return parameter value
911     */
912    public static String getParameterString(final Context context, final String packageName,
913            final int audioSession, final Key key, final int arg) {
914        return getParameterString(context, packageName, audioSession, key.toString() + arg);
915    }
916
917    /**
918     * Opens/initializes the effects session for the given audio session with preferences linked to
919     * the given package name and context.
920     *
921     * @param context
922     * @param packageName
923     * @param audioSession
924     *            System wide unique audio session identifier.
925     */
926    public static void openSession(final Context context, final String packageName,
927            final int audioSession) {
928        Log.v(TAG, "openSession(" + context + ", " + packageName + ", " + audioSession + ")");
929        final String methodTag = "openSession: ";
930
931        // init preferences
932        final SharedPreferences prefs = context.getSharedPreferences(packageName,
933                Context.MODE_PRIVATE);
934        final SharedPreferences.Editor editor = prefs.edit();
935
936        final boolean isGlobalEnabled = prefs.getBoolean(Key.global_enabled.toString(),
937                GLOBAL_ENABLED_DEFAULT);
938        editor.putBoolean(Key.global_enabled.toString(), isGlobalEnabled);
939
940        // Manage audioSession information
941
942        // Retrieve AudioSession Id from map
943        boolean isExistingAudioSession = false;
944
945        try {
946            final Integer currentAudioSession = mPackageSessions.putIfAbsent(packageName,
947                    audioSession);
948            if (currentAudioSession != null) {
949                // Compare with passed argument
950                if (currentAudioSession == audioSession) {
951                    // FIXME: Normally, we should exit the function here
952                    // BUT: we have to take care of the virtualizer because of
953                    // a bug in the Android Effects Framework
954                    // editor.commit();
955                    // return;
956                    isExistingAudioSession = true;
957                } else {
958                    closeSession(context, packageName, currentAudioSession);
959                }
960            }
961        } catch (final NullPointerException e) {
962            Log.e(TAG, methodTag + e);
963            editor.commit();
964            return;
965        }
966
967        // Because the audioSession is new, get effects & settings from shared preferences
968
969        // Virtualizer
970        // create effect
971        final Virtualizer virtualizerEffect = getVirtualizerEffect(audioSession);
972        {
973            final String errorTag = methodTag + "Virtualizer error: ";
974
975            try {
976                // read parameters
977                final boolean isEnabled = prefs.getBoolean(Key.virt_enabled.toString(),
978                        VIRTUALIZER_ENABLED_DEFAULT);
979                final int strength = prefs.getInt(Key.virt_strength.toString(),
980                        VIRTUALIZER_STRENGTH_DEFAULT);
981                // init settings
982                Virtualizer.Settings settings = new Virtualizer.Settings("Virtualizer;strength="
983                        + strength);
984
985                virtualizerEffect.setProperties(settings);
986
987                // set parameters
988                if (isGlobalEnabled == true) {
989                    virtualizerEffect.setEnabled(isEnabled);
990                } else {
991                    virtualizerEffect.setEnabled(false);
992                }
993
994                // get parameters
995                settings = virtualizerEffect.getProperties();
996                Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);
997
998                // update preferences
999                editor.putBoolean(Key.virt_enabled.toString(), isEnabled);
1000                editor.putInt(Key.virt_strength.toString(), settings.strength);
1001            } catch (final RuntimeException e) {
1002                Log.e(TAG, errorTag + e);
1003            }
1004        }
1005
1006        // In case of an existing audio session
1007        // Exit after the virtualizer has been re-enabled
1008
1009        if (isExistingAudioSession) {
1010            editor.commit();
1011            return;
1012        }
1013
1014        // BassBoost
1015        // create effect
1016        final BassBoost bassBoostEffect = getBassBoostEffect(audioSession);
1017        {
1018            final String errorTag = methodTag + "BassBoost error: ";
1019
1020            try {
1021                // read parameters
1022                final boolean isEnabled = prefs.getBoolean(Key.bb_enabled.toString(),
1023                        BASS_BOOST_ENABLED_DEFAULT);
1024                final int strength = prefs.getInt(Key.bb_strength.toString(),
1025                        BASS_BOOST_STRENGTH_DEFAULT);
1026
1027                // init settings
1028                BassBoost.Settings settings = new BassBoost.Settings("BassBoost;strength="
1029                        + strength);
1030
1031                bassBoostEffect.setProperties(settings);
1032
1033                // set parameters
1034                if (isGlobalEnabled == true) {
1035                    bassBoostEffect.setEnabled(isEnabled);
1036                } else {
1037                    bassBoostEffect.setEnabled(false);
1038                }
1039
1040                // get parameters
1041                settings = bassBoostEffect.getProperties();
1042                Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);
1043
1044                // update preferences
1045                editor.putBoolean(Key.bb_enabled.toString(), isEnabled);
1046                editor.putInt(Key.bb_strength.toString(), settings.strength);
1047            } catch (final RuntimeException e) {
1048                Log.e(TAG, errorTag + e);
1049            }
1050        }
1051
1052        // Equalizer
1053        // create effect
1054        final Equalizer equalizerEffect = getEqualizerEffect(audioSession);
1055        {
1056            final String errorTag = methodTag + "Equalizer error: ";
1057
1058            try {
1059                final short eQNumBands;
1060                final short[] bandLevel;
1061                final int[] eQCenterFreq;
1062                final short eQNumPresets;
1063                final String[] eQPresetNames;
1064                short eQPreset;
1065                synchronized (mEQInitLock) {
1066                    // read parameters
1067                    mEQBandLevelRange = equalizerEffect.getBandLevelRange();
1068                    mEQNumBands = equalizerEffect.getNumberOfBands();
1069                    mEQCenterFreq = new int[mEQNumBands];
1070                    mEQNumPresets = equalizerEffect.getNumberOfPresets();
1071                    mEQPresetNames = new String[mEQNumPresets];
1072
1073                    for (short preset = 0; preset < mEQNumPresets; preset++) {
1074                        mEQPresetNames[preset] = equalizerEffect.getPresetName(preset);
1075                        editor.putString(Key.eq_preset_name.toString() + preset,
1076                                mEQPresetNames[preset]);
1077                    }
1078
1079                    editor.putInt(Key.eq_level_range.toString() + 0, mEQBandLevelRange[0]);
1080                    editor.putInt(Key.eq_level_range.toString() + 1, mEQBandLevelRange[1]);
1081                    editor.putInt(Key.eq_num_bands.toString(), mEQNumBands);
1082                    editor.putInt(Key.eq_num_presets.toString(), mEQNumPresets);
1083                    // Resetting the EQ arrays depending on the real # bands with defaults if band <
1084                    // default size else 0 by copying default arrays over new ones
1085                    final short[] eQPresetCIExtremeBandLevel = Arrays.copyOf(
1086                            EQUALIZER_PRESET_CIEXTREME_BAND_LEVEL, mEQNumBands);
1087                    final short[] eQPresetUserBandLevelDefault = Arrays.copyOf(
1088                            EQUALIZER_PRESET_USER_BAND_LEVEL_DEFAULT, mEQNumBands);
1089                    // If no preset prefs set use CI EXTREME (= numPresets)
1090                    eQPreset = (short) prefs
1091                            .getInt(Key.eq_current_preset.toString(), mEQNumPresets);
1092                    if (eQPreset < mEQNumPresets) {
1093                        // OpenSL ES effect presets
1094                        equalizerEffect.usePreset(eQPreset);
1095                        eQPreset = equalizerEffect.getCurrentPreset();
1096                    } else {
1097                        for (short band = 0; band < mEQNumBands; band++) {
1098                            short level = 0;
1099                            if (eQPreset == mEQNumPresets) {
1100                                // CI EXTREME
1101                                level = eQPresetCIExtremeBandLevel[band];
1102                            } else {
1103                                // User
1104                                level = (short) prefs.getInt(
1105                                        Key.eq_preset_user_band_level.toString() + band,
1106                                        eQPresetUserBandLevelDefault[band]);
1107                            }
1108                            equalizerEffect.setBandLevel(band, level);
1109                        }
1110                    }
1111                    editor.putInt(Key.eq_current_preset.toString(), eQPreset);
1112
1113                    bandLevel = new short[mEQNumBands];
1114                    for (short band = 0; band < mEQNumBands; band++) {
1115                        mEQCenterFreq[band] = equalizerEffect.getCenterFreq(band);
1116                        bandLevel[band] = equalizerEffect.getBandLevel(band);
1117
1118                        editor.putInt(Key.eq_band_level.toString() + band, bandLevel[band]);
1119                        editor.putInt(Key.eq_center_freq.toString() + band, mEQCenterFreq[band]);
1120                        editor.putInt(Key.eq_preset_ci_extreme_band_level.toString() + band,
1121                                eQPresetCIExtremeBandLevel[band]);
1122                        editor.putInt(Key.eq_preset_user_band_level_default.toString() + band,
1123                                eQPresetUserBandLevelDefault[band]);
1124                    }
1125
1126                    eQNumBands = mEQNumBands;
1127                    eQCenterFreq = mEQCenterFreq;
1128                    eQNumPresets = mEQNumPresets;
1129                    eQPresetNames = mEQPresetNames;
1130                }
1131
1132                final boolean isEnabled = prefs.getBoolean(Key.eq_enabled.toString(),
1133                        EQUALIZER_ENABLED_DEFAULT);
1134                editor.putBoolean(Key.eq_enabled.toString(), isEnabled);
1135                if (isGlobalEnabled == true) {
1136                    equalizerEffect.setEnabled(isEnabled);
1137                } else {
1138                    equalizerEffect.setEnabled(false);
1139                }
1140
1141                // dump
1142                Log.v(TAG, "Parameters: Equalizer");
1143                Log.v(TAG, "bands=" + eQNumBands);
1144                String str = "levels=";
1145                for (short band = 0; band < eQNumBands; band++) {
1146                    str = str + bandLevel[band] + "; ";
1147                }
1148                Log.v(TAG, str);
1149                str = "center=";
1150                for (short band = 0; band < eQNumBands; band++) {
1151                    str = str + eQCenterFreq[band] + "; ";
1152                }
1153                Log.v(TAG, str);
1154                str = "presets=";
1155                for (short preset = 0; preset < eQNumPresets; preset++) {
1156                    str = str + eQPresetNames[preset] + "; ";
1157                }
1158                Log.v(TAG, str);
1159                Log.v(TAG, "current=" + eQPreset);
1160            } catch (final RuntimeException e) {
1161                Log.e(TAG, errorTag + e);
1162            }
1163        }
1164
1165        // XXX: Preset Reverb not used for the moment, so commented out the effect creation to not
1166        // use MIPS left in the code for (future) reference.
1167        // Preset reverb
1168        // create effect
1169        // final PresetReverb presetReverbEffect = getPresetReverbEffect(audioSession);
1170        // {
1171        // final String errorTag = methodTag + "PresetReverb error: ";
1172        //
1173        // try {
1174        // // read parameters
1175        // final boolean isEnabled = prefs.getBoolean(Key.pr_enabled.toString(),
1176        // PRESET_REVERB_ENABLED_DEFAULT);
1177        // final short preset = (short) prefs.getInt(Key.pr_current_preset.toString(),
1178        // PRESET_REVERB_CURRENT_PRESET_DEFAULT);
1179        //
1180        // // init settings
1181        // PresetReverb.Settings settings = new PresetReverb.Settings("PresetReverb;preset="
1182        // + preset);
1183        //
1184        // // read/update preferences
1185        // presetReverbEffect.setProperties(settings);
1186        //
1187        // // set parameters
1188        // if (isGlobalEnabled == true) {
1189        // presetReverbEffect.setEnabled(isEnabled);
1190        // } else {
1191        // presetReverbEffect.setEnabled(false);
1192        // }
1193        //
1194        // // get parameters
1195        // settings = presetReverbEffect.getProperties();
1196        // Log.v(TAG, "Parameters: " + settings.toString() + ";enabled=" + isEnabled);
1197        //
1198        // // update preferences
1199        // editor.putBoolean(Key.pr_enabled.toString(), isEnabled);
1200        // editor.putInt(Key.pr_current_preset.toString(), settings.preset);
1201        // } catch (final RuntimeException e) {
1202        // Log.e(TAG, errorTag + e);
1203        // }
1204        // }
1205        editor.commit();
1206    }
1207
1208    /**
1209     * Closes the audio session (release effects) for the given session
1210     *
1211     * @param context
1212     * @param packageName
1213     * @param audioSession
1214     *            System wide unique audio session identifier.
1215     */
1216    public static void closeSession(final Context context, final String packageName,
1217            final int audioSession) {
1218        Log.v(TAG, "closeSession(" + context + ", " + packageName + ", " + audioSession + ")");
1219
1220        // PresetReverb
1221        final PresetReverb presetReverb = mPresetReverbInstances.remove(audioSession);
1222        if (presetReverb != null) {
1223            presetReverb.release();
1224        }
1225        // Equalizer
1226        final Equalizer equalizer = mEQInstances.remove(audioSession);
1227        if (equalizer != null) {
1228            equalizer.release();
1229        }
1230        // BassBoost
1231        final BassBoost bassBoost = mBassBoostInstances.remove(audioSession);
1232        if (bassBoost != null) {
1233            bassBoost.release();
1234        }
1235        // Virtualizer
1236        final Virtualizer virtualizer = mVirtualizerInstances.remove(audioSession);
1237        if (virtualizer != null) {
1238            virtualizer.release();
1239        }
1240
1241        mPackageSessions.remove(packageName);
1242    }
1243
1244    /**
1245     * Enables or disables all effects (global enable/disable) for a given context, package name and
1246     * audio session. It sets/inits the control mode and preferences and then sets the global
1247     * enabled parameter.
1248     *
1249     * @param context
1250     * @param packageName
1251     * @param audioSession
1252     *            System wide unique audio session identifier.
1253     * @param enabled
1254     */
1255    public static void setEnabledAll(final Context context, final String packageName,
1256            final int audioSession, final boolean enabled) {
1257        initEffectsPreferences(context, packageName, audioSession);
1258        setParameterBoolean(context, packageName, audioSession, Key.global_enabled, enabled);
1259    }
1260
1261    /**
1262     * Gets the virtualizer effect for the given audio session. If the effect on the session doesn't
1263     * exist yet, create it and add to collection.
1264     *
1265     * @param audioSession
1266     *            System wide unique audio session identifier.
1267     * @return virtualizerEffect
1268     */
1269    private static Virtualizer getVirtualizerEffect(final int audioSession) {
1270        Virtualizer virtualizerEffect = mVirtualizerInstances.get(audioSession);
1271        if (virtualizerEffect == null) {
1272            try {
1273                final Virtualizer newVirtualizerEffect = new Virtualizer(PRIORITY, audioSession);
1274                virtualizerEffect = mVirtualizerInstances.putIfAbsent(audioSession,
1275                        newVirtualizerEffect);
1276                if (virtualizerEffect == null) {
1277                    // put succeeded, use new value
1278                    virtualizerEffect = newVirtualizerEffect;
1279                }
1280            } catch (final IllegalArgumentException e) {
1281                Log.e(TAG, "Virtualizer: " + e);
1282            } catch (final UnsupportedOperationException e) {
1283                Log.e(TAG, "Virtualizer: " + e);
1284            } catch (final RuntimeException e) {
1285                Log.e(TAG, "Virtualizer: " + e);
1286            }
1287        }
1288        return virtualizerEffect;
1289    }
1290
1291    /**
1292     * Gets the bass boost effect for the given audio session. If the effect on the session doesn't
1293     * exist yet, create it and add to collection.
1294     *
1295     * @param audioSession
1296     *            System wide unique audio session identifier.
1297     * @return bassBoostEffect
1298     */
1299    private static BassBoost getBassBoostEffect(final int audioSession) {
1300        BassBoost bassBoostEffect = mBassBoostInstances.get(audioSession);
1301        if (bassBoostEffect == null) {
1302            try {
1303                final BassBoost newBassBoostEffect = new BassBoost(PRIORITY, audioSession);
1304                bassBoostEffect = mBassBoostInstances.putIfAbsent(audioSession, newBassBoostEffect);
1305                if (bassBoostEffect == null) {
1306                    // put succeeded, use new value
1307                    bassBoostEffect = newBassBoostEffect;
1308                }
1309            } catch (final IllegalArgumentException e) {
1310                Log.e(TAG, "BassBoost: " + e);
1311            } catch (final UnsupportedOperationException e) {
1312                Log.e(TAG, "BassBoost: " + e);
1313            } catch (final RuntimeException e) {
1314                Log.e(TAG, "BassBoost: " + e);
1315            }
1316        }
1317        return bassBoostEffect;
1318    }
1319
1320    /**
1321     * Gets the equalizer effect for the given audio session. If the effect on the session doesn't
1322     * exist yet, create it and add to collection.
1323     *
1324     * @param audioSession
1325     *            System wide unique audio session identifier.
1326     * @return equalizerEffect
1327     */
1328    private static Equalizer getEqualizerEffect(final int audioSession) {
1329        Equalizer equalizerEffect = mEQInstances.get(audioSession);
1330        if (equalizerEffect == null) {
1331            try {
1332                final Equalizer newEqualizerEffect = new Equalizer(PRIORITY, audioSession);
1333                equalizerEffect = mEQInstances.putIfAbsent(audioSession, newEqualizerEffect);
1334                if (equalizerEffect == null) {
1335                    // put succeeded, use new value
1336                    equalizerEffect = newEqualizerEffect;
1337                }
1338            } catch (final IllegalArgumentException e) {
1339                Log.e(TAG, "Equalizer: " + e);
1340            } catch (final UnsupportedOperationException e) {
1341                Log.e(TAG, "Equalizer: " + e);
1342            } catch (final RuntimeException e) {
1343                Log.e(TAG, "Equalizer: " + e);
1344            }
1345        }
1346        return equalizerEffect;
1347    }
1348
1349    // XXX: Preset Reverb not used for the moment, so commented out the effect creation to not
1350    // use MIPS
1351    // /**
1352    // * Gets the preset reverb effect for the given audio session. If the effect on the session
1353    // * doesn't exist yet, create it and add to collection.
1354    // *
1355    // * @param audioSession
1356    // * System wide unique audio session identifier.
1357    // * @return presetReverbEffect
1358    // */
1359    // private static PresetReverb getPresetReverbEffect(final int audioSession) {
1360    // PresetReverb presetReverbEffect = mPresetReverbInstances.get(audioSession);
1361    // if (presetReverbEffect == null) {
1362    // try {
1363    // final PresetReverb newPresetReverbEffect = new PresetReverb(PRIORITY, audioSession);
1364    // presetReverbEffect = mPresetReverbInstances.putIfAbsent(audioSession,
1365    // newPresetReverbEffect);
1366    // if (presetReverbEffect == null) {
1367    // // put succeeded, use new value
1368    // presetReverbEffect = newPresetReverbEffect;
1369    // }
1370    // } catch (final IllegalArgumentException e) {
1371    // Log.e(TAG, "PresetReverb: " + e);
1372    // } catch (final UnsupportedOperationException e) {
1373    // Log.e(TAG, "PresetReverb: " + e);
1374    // } catch (final RuntimeException e) {
1375    // Log.e(TAG, "PresetReverb: " + e);
1376    // }
1377    // }
1378    // return presetReverbEffect;
1379    // }
1380}
1381