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