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