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 = 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 unused. Used for method
144      * overloading.
145      */
146     private final static int UNUSED_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 placeholder 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 "placeholder" 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 placeholder 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 placeholder 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 placeholder 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      */
getControlMode(final int audioSession)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      */
setParameterBoolean(final Context context, final String packageName, final int audioSession, final Key key, final boolean value)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      */
getParameterBoolean(final Context context, final String packageName, final int audioSession, final Key key)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      */
setParameterInt(final Context context, final String packageName, final int audioSession, final Key key, final int arg0, final int arg1)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 == UNUSED_ARGUMENT) {
591                         throw new IllegalArgumentException("Unused 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 == UNUSED_ARGUMENT) {
654                         throw new IllegalArgumentException("Unused 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 == UNUSED_ARGUMENT) {
691                         throw new IllegalArgumentException("Unused 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 == UNUSED_ARGUMENT) {
740                         throw new IllegalArgumentException("Unused 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      */
setParameterInt(final Context context, final String packageName, final int audioSession, final Key key, final int arg)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, UNUSED_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      */
getParameterInt(final Context context, final String packageName, final int audioSession, final String key)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      */
getParameterInt(final Context context, final String packageName, final int audioSession, final Key key)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      */
getParameterInt(final Context context, final String packageName, final int audioSession, final Key key, final int arg)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      */
getParameterInt(final Context context, final String packageName, final int audioSession, final Key key, final int arg0, final int arg1)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      */
getParameterIntArray(final Context context, final String packageName, final int audioSession, final Key key)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      */
getParameterString(final Context context, final String packageName, final int audioSession, final String key)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      */
getParameterString(final Context context, final String packageName, final int audioSession, final Key key)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      */
getParameterString(final Context context, final String packageName, final int audioSession, final Key key, final int arg)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      */
openSession(final Context context, final String packageName, final int audioSession)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      */
closeSession(final Context context, final String packageName, final int audioSession)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      */
setEnabledAll(final Context context, final String packageName, final int audioSession, final boolean enabled)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      */
getVirtualizerEffectNoCreate(final int audioSession)1322     private static Virtualizer getVirtualizerEffectNoCreate(final int audioSession) {
1323         return mVirtualizerInstances.get(audioSession);
1324     }
getVirtualizerEffect(final int audioSession)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      */
getBassBoostEffectNoCreate(final int audioSession)1355     private static BassBoost getBassBoostEffectNoCreate(final int audioSession) {
1356         return mBassBoostInstances.get(audioSession);
1357     }
getBassBoostEffect(final int audioSession)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      */
getEqualizerEffectNoCreate(final int audioSession)1388     private static Equalizer getEqualizerEffectNoCreate(final int audioSession) {
1389         return mEQInstances.get(audioSession);
1390     }
getEqualizerEffect(final int audioSession)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