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