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