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