summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-04-01 21:06:58 -0700
committerRoman Birg <roman@cyngn.com>2016-04-05 20:38:37 +0000
commit672ccc8e0f4427bd6a3a19b5db0c9a056bfbf3bc (patch)
treef8aa685d4e5888dbabfe12402ac667c69e00477b /src
parent70f9b012d9200faf044395570f7fea9b06b0e306 (diff)
downloadandroid_packages_apps_AudioFX-672ccc8e0f4427bd6a3a19b5db0c9a056bfbf3bc.tar.gz
android_packages_apps_AudioFX-672ccc8e0f4427bd6a3a19b5db0c9a056bfbf3bc.tar.bz2
android_packages_apps_AudioFX-672ccc8e0f4427bd6a3a19b5db0c9a056bfbf3bc.zip
audiofx: A big pile of fixes.
* Fix MaxxAudio device selection. Use WAVESFX commands to do this ourselves. * Ditch parameter caching. It's overkill. * Clean up locking across the board. * Fix lost messages in the queue. * Make parameter setting transactional. * Add device changed and lifecycle callbacks to the backend. * Turn the Waves effect on all the time and add some defaults. Change-Id: Ia3e6bfd4010840189169db9037cb925811a6cbc4
Diffstat (limited to 'src')
-rw-r--r--src/com/cyngn/audiofx/Constants.java5
-rw-r--r--src/com/cyngn/audiofx/activity/MasterConfigControl.java13
-rw-r--r--src/com/cyngn/audiofx/backends/AndroidEffects.java60
-rw-r--r--src/com/cyngn/audiofx/backends/EffectSet.java131
-rw-r--r--src/com/cyngn/audiofx/backends/EffectSetWithAndroidEq.java58
-rw-r--r--src/com/cyngn/audiofx/backends/EffectsFactory.java10
-rw-r--r--src/com/cyngn/audiofx/service/AudioFxService.java305
7 files changed, 362 insertions, 220 deletions
diff --git a/src/com/cyngn/audiofx/Constants.java b/src/com/cyngn/audiofx/Constants.java
index 61d53cc..bf9d6ba 100644
--- a/src/com/cyngn/audiofx/Constants.java
+++ b/src/com/cyngn/audiofx/Constants.java
@@ -28,7 +28,12 @@ public class Constants {
// global settings
public static final String AUDIOFX_GLOBAL_FILE = "global";
+
public static final String DEVICE_SPEAKER = "speaker";
+ public static final String DEVICE_HEADSET = "headset";
+ public static final String DEVICE_USB = "usb";
+ public static final String DEVICE_CAST = "wireless";
+ public static final String DEVICE_BLUETOOTH = "bluetooth";
public static final String SAVED_DEFAULTS = "saved_defaults";
diff --git a/src/com/cyngn/audiofx/activity/MasterConfigControl.java b/src/com/cyngn/audiofx/activity/MasterConfigControl.java
index fc67dbc..7f0806f 100644
--- a/src/com/cyngn/audiofx/activity/MasterConfigControl.java
+++ b/src/com/cyngn/audiofx/activity/MasterConfigControl.java
@@ -328,22 +328,23 @@ public class MasterConfigControl {
switch (type) {
case TYPE_WIRED_HEADSET:
case TYPE_WIRED_HEADPHONES:
- return "headset";
+ return Constants.DEVICE_HEADSET;
case TYPE_LINE_ANALOG:
case TYPE_LINE_DIGITAL:
// FIXME: support line-out
- return "headset";
+ return Constants.DEVICE_HEADSET;
case TYPE_BLUETOOTH_SCO:
case TYPE_BLUETOOTH_A2DP:
- return "bluetooth";
+ // FIXME: include dev info
+ return Constants.DEVICE_BLUETOOTH;
case TYPE_USB_DEVICE:
case TYPE_USB_ACCESSORY:
case TYPE_DOCK:
- return "usb";
+ return Constants.DEVICE_USB;
case TYPE_IP:
- return "wireless";
+ return Constants.DEVICE_CAST;
default:
- return "speaker";
+ return Constants.DEVICE_SPEAKER;
}
}
diff --git a/src/com/cyngn/audiofx/backends/AndroidEffects.java b/src/com/cyngn/audiofx/backends/AndroidEffects.java
index 7e2811c..780bd63 100644
--- a/src/com/cyngn/audiofx/backends/AndroidEffects.java
+++ b/src/com/cyngn/audiofx/backends/AndroidEffects.java
@@ -1,19 +1,17 @@
package com.cyngn.audiofx.backends;
+import android.media.AudioDeviceInfo;
import android.media.audiofx.AudioEffect;
import android.media.audiofx.BassBoost;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.Virtualizer;
import android.util.Log;
-import android.util.SparseArray;
/**
* EffectSet which comprises standard Android effects
*/
class AndroidEffects extends EffectSetWithAndroidEq {
- private final SparseArray<Short> mCache = new SparseArray<Short>();
-
/**
* Session-specific bassboost
*/
@@ -29,15 +27,13 @@ class AndroidEffects extends EffectSetWithAndroidEq {
*/
private final PresetReverb mPresetReverb;
- public AndroidEffects(int sessionId) {
- super(sessionId);
+ public AndroidEffects(int sessionId, AudioDeviceInfo deviceInfo) {
+ super(sessionId, deviceInfo);
try {
mBassBoost = new BassBoost(1000, sessionId);
mVirtualizer = new Virtualizer(1000, sessionId);
mPresetReverb = new PresetReverb(1000, sessionId);
-
- addEffects(mBassBoost, mVirtualizer, mPresetReverb);
} catch (Exception e) {
release();
throw e;
@@ -45,6 +41,40 @@ class AndroidEffects extends EffectSetWithAndroidEq {
}
@Override
+ public void release() {
+ super.release();
+ mBassBoost.release();
+ mVirtualizer.release();
+ mPresetReverb.release();
+ }
+
+ @Override
+ public void setGlobalEnabled(boolean globalEnabled) {
+ if (globalEnabled != isGlobalEnabled()) {
+ if (!globalEnabled) {
+ // disable everything. it will get explictly enabled
+ // individually when necessary.
+ try {
+ mVirtualizer.setEnabled(false);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to disable virtualizer!", e);
+ }
+ try {
+ mBassBoost.setEnabled(false);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to disable bass boost!", e);
+ }
+ try {
+ mPresetReverb.setEnabled(false);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to disable reverb!", e);
+ }
+ }
+ }
+ super.setGlobalEnabled(globalEnabled);
+ }
+
+ @Override
public boolean hasVirtualizer() {
return mVirtualizer.getStrengthSupported();
}
@@ -56,9 +86,6 @@ class AndroidEffects extends EffectSetWithAndroidEq {
@Override
public void enableBassBoost(boolean enable) {
- if (enable == mBassBoost.getEnabled()) {
- return;
- }
try {
mBassBoost.setEnabled(enable);
} catch (Exception e) {
@@ -73,9 +100,6 @@ class AndroidEffects extends EffectSetWithAndroidEq {
@Override
public void enableVirtualizer(boolean enable) {
- if (enable == mVirtualizer.getEnabled()) {
- return;
- }
try {
mVirtualizer.setEnabled(enable);
} catch (Exception e) {
@@ -90,14 +114,12 @@ class AndroidEffects extends EffectSetWithAndroidEq {
@Override
public void enableReverb(boolean enable) {
- if (enable == mPresetReverb.getEnabled()) {
- return;
- }
try {
mPresetReverb.setEnabled(enable);
} catch (Exception e) {
Log.e(TAG, "Unable to " + (enable ? "enable" : "disable") + " preset reverb!", e);
}
+
}
@Override
@@ -110,16 +132,12 @@ class AndroidEffects extends EffectSetWithAndroidEq {
return EffectsFactory.ANDROID;
}
- private synchronized void setParameterSafe(AudioEffect e, int p, short v) {
- if (mCache.indexOfKey(p) >= 0 && v == mCache.get(p)) {
- return;
- }
+ private void setParameterSafe(AudioEffect e, int p, short v) {
if (!e.hasControl()) {
return;
}
try {
e.setParameter(p, v);
- mCache.put(p, v);
} catch (Exception ex) {
Log.e(TAG, "Failed to set param " + p + " for effect " + e.getDescriptor().name, ex);
}
diff --git a/src/com/cyngn/audiofx/backends/EffectSet.java b/src/com/cyngn/audiofx/backends/EffectSet.java
index 248dc01..a999819 100644
--- a/src/com/cyngn/audiofx/backends/EffectSet.java
+++ b/src/com/cyngn/audiofx/backends/EffectSet.java
@@ -1,10 +1,6 @@
package com.cyngn.audiofx.backends;
-import android.media.audiofx.AudioEffect;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
+import android.media.AudioDeviceInfo;
/**
* Helper class representing the full complement of effects attached to one
@@ -16,12 +12,98 @@ public abstract class EffectSet {
protected final int mSessionId;
- protected final ArrayList<AudioEffect> mEffects = new ArrayList<AudioEffect>();
+ protected boolean mGlobalEnabled;
+
+ private AudioDeviceInfo mDeviceInfo;
- public EffectSet(int sessionId) {
+ public EffectSet(int sessionId, AudioDeviceInfo deviceInfo) {
mSessionId = sessionId;
+ mDeviceInfo = deviceInfo;
+ onCreate();
+ }
+
+ /**
+ * Called to do subclass-first initialization in case
+ * an implementation has ordering restrictions.
+ */
+ protected void onCreate() { }
+
+ /**
+ * Destroy all effects in this set.
+ *
+ * Attempting to use this object after calling release is
+ * undefined behavior.
+ */
+ public void release() { }
+
+ /**
+ * Returns the enumerated brand of this implementation
+ * @return brandId
+ */
+ public abstract int getBrand();
+
+ /**
+ * Called when the user toggles the engine on or off. If the
+ * implementation has a built-in bypass mode, this is where
+ * to use it.
+ *
+ * @param globalEnabled
+ */
+ public void setGlobalEnabled(boolean globalEnabled) {
+ mGlobalEnabled = globalEnabled;
+ }
+
+ public boolean isGlobalEnabled() {
+ return mGlobalEnabled;
+ }
+
+ /**
+ * Called when the output device has changed. All cached
+ * data should be cleared at this point.
+ *
+ * @param deviceInfo
+ */
+ public void setDevice(AudioDeviceInfo deviceInfo) {
+ mDeviceInfo = deviceInfo;
}
+ /**
+ * Return the current active output device
+ * @return deviceInfo
+ */
+ public AudioDeviceInfo getDevice() {
+ return mDeviceInfo;
+ }
+
+ /**
+ * Begin bulk-update of parameters. This can be used if the
+ * implementation supports operation in a transactional/atomic
+ * manner. Parameter changes will immediately follow this call
+ * and should be committed to the backend when the subsequent
+ * commitUpdate() is called.
+ *
+ * Optional.
+ *
+ * @return status - false on failure
+ */
+ public boolean beginUpdate() { return true; }
+
+ /**
+ * Commit accumulated updates to the backend. See above.
+ *
+ * begin/commit are used when a large number of parameters need
+ * to be sent to the backend, such as in the case of a device
+ * switch or preset change. This can increase performance and
+ * reduce click/pop issues.
+ *
+ * Optional.
+ *
+ * @return status - false on failure
+ */
+ public boolean commitUpdate() { return true; }
+
+ /* ---- Top level effects begin here ---- */
+
// required effects
public abstract boolean hasVirtualizer();
@@ -110,39 +192,4 @@ public abstract class EffectSet {
public void enableVolumeBoost(boolean enable) {
return;
}
-
- public synchronized void release() {
- for (AudioEffect e : mEffects) {
- Log.d(TAG, "releasing effect: " + e.getDescriptor().name);
- try {
- e.release();
- } catch (Exception ex) {
- Log.e(TAG, ex.getMessage(), ex);
- }
- }
- mEffects.clear();
- }
-
- public boolean isActive() {
- return mEffects.size() > 0;
- }
-
- public abstract int getBrand();
-
- public void setGlobalEnabled(boolean globalEnabled) {
- if (globalEnabled) {
- return;
- }
- for (AudioEffect e : mEffects) {
- try {
- e.setEnabled(false);
- } catch (Exception ex) {
- Log.e(TAG, ex.getMessage(), ex);
- }
- }
- }
-
- protected void addEffects(AudioEffect... effects) {
- mEffects.addAll(Arrays.asList(effects));
- }
}
diff --git a/src/com/cyngn/audiofx/backends/EffectSetWithAndroidEq.java b/src/com/cyngn/audiofx/backends/EffectSetWithAndroidEq.java
index b1248b2..330b544 100644
--- a/src/com/cyngn/audiofx/backends/EffectSetWithAndroidEq.java
+++ b/src/com/cyngn/audiofx/backends/EffectSetWithAndroidEq.java
@@ -1,8 +1,8 @@
package com.cyngn.audiofx.backends;
+import android.media.AudioDeviceInfo;
import android.media.audiofx.Equalizer;
import android.util.Log;
-import android.util.SparseArray;
import com.cyngn.audiofx.eq.EqUtils;
@@ -13,30 +13,45 @@ public abstract class EffectSetWithAndroidEq extends EffectSet {
/**
* Session-specific equalizer
*/
- private final Equalizer mEqualizer;
+ private Equalizer mEqualizer;
private short mEqNumPresets = -1;
private short mEqNumBands = -1;
- private final SparseArray<Short> mLevelCache = new SparseArray<Short>();
+ public EffectSetWithAndroidEq(int sessionId, AudioDeviceInfo deviceInfo) {
+ super(sessionId, deviceInfo);
+ }
- public EffectSetWithAndroidEq(int sessionId) {
- super(sessionId);
- try {
- mEqualizer = new Equalizer(1000, sessionId);
+ @Override
+ protected void onCreate() {
+ mEqualizer = new Equalizer(1000, mSessionId);
+ super.onCreate();
- addEffects(mEqualizer);
- } catch (Exception e) {
- release();
- throw e;
+ }
+
+ @Override
+ public synchronized void release() {
+ super.release();
+ if (mEqualizer != null) {
+ mEqualizer.release();
+ mEqualizer = null;
}
}
+ @Override
+ public void setGlobalEnabled(boolean globalEnabled) {
+ if (isGlobalEnabled() != globalEnabled) {
+ // disable it if needed. it will be explicitly enabled
+ // in a subsequent call if necessary.
+ if (!globalEnabled) {
+ mEqualizer.setEnabled(false);
+ }
+ }
+ super.setGlobalEnabled(globalEnabled);
+ }
+ @Override
public void enableEqualizer(boolean enable) {
- if (enable == mEqualizer.getEnabled()) {
- return;
- }
try {
mEqualizer.setEnabled(enable);
} catch (Exception e) {
@@ -52,6 +67,7 @@ public abstract class EffectSetWithAndroidEq extends EffectSet {
}
}
+ @Override
public short getNumEqualizerBands() {
if (mEqNumBands < 0) {
mEqNumBands = mEqualizer.getNumberOfBands();
@@ -64,42 +80,42 @@ public abstract class EffectSetWithAndroidEq extends EffectSet {
setBandLevelSafe(band, (short)level);
}
+ @Override
public int getEqualizerBandLevel(short band) {
return mEqualizer.getBandLevel(band);
}
+ @Override
public String getEqualizerPresetName(short preset) {
return mEqualizer.getPresetName(preset);
}
+ @Override
public void useEqualizerPreset(short preset) {
mEqualizer.usePreset(preset);
}
+ @Override
public short getNumEqualizerPresets() {
if (mEqNumPresets < 0) {
mEqNumPresets = mEqualizer.getNumberOfPresets();
}
return mEqNumPresets;
}
+
+ @Override
public short[] getEqualizerBandLevelRange() {
return mEqualizer.getBandLevelRange();
}
+ @Override
public int getCenterFrequency(short band) {
return mEqualizer.getCenterFreq(band);
}
private synchronized void setBandLevelSafe(short band, short level) {
- if (!mEqualizer.hasControl()) {
- return;
- }
- if (mLevelCache.indexOfKey((int)band) >= 0 && level == mLevelCache.get((int)band)) {
- return;
- }
try {
mEqualizer.setBandLevel(band, level);
- mLevelCache.put((int)band, level);
} catch (Exception e) {
Log.e(TAG, "Unable to set eq band=" + band + " level=" + level, e);
}
diff --git a/src/com/cyngn/audiofx/backends/EffectsFactory.java b/src/com/cyngn/audiofx/backends/EffectsFactory.java
index 6534e83..90e601d 100644
--- a/src/com/cyngn/audiofx/backends/EffectsFactory.java
+++ b/src/com/cyngn/audiofx/backends/EffectsFactory.java
@@ -1,6 +1,7 @@
package com.cyngn.audiofx.backends;
import android.content.Context;
+import android.media.AudioDeviceInfo;
import android.util.Log;
import java.io.File;
@@ -20,7 +21,8 @@ public class EffectsFactory {
public static final int DTS = 3;
- public static EffectSet createEffectSet(Context context, int sessionId) {
+ public static EffectSet createEffectSet(Context context, int sessionId,
+ AudioDeviceInfo deviceInfo) {
EffectSet effects = null;
int brand = getBrand();
@@ -28,7 +30,7 @@ public class EffectsFactory {
// dts?
if (brand == DTS) {
try {
- effects = new DtsEffects(context, sessionId);
+ effects = new DtsEffects(context, sessionId, deviceInfo);
} catch (Exception e) {
Log.e(TAG, "Unable to create DTS effects!", e);
effects = null;
@@ -36,7 +38,7 @@ public class EffectsFactory {
} else if (brand == MAXXAUDIO) {
// try MaxxAudio next, this will throw an exception if unavailable
try {
- effects = new MaxxAudioEffects(sessionId);
+ effects = new MaxxAudioEffects(sessionId, deviceInfo);
} catch (Exception e) {
Log.e(TAG, "Unable to create MaxxAudio effects!", e);
effects = null;
@@ -47,7 +49,7 @@ public class EffectsFactory {
// if this throws, we're screwed, don't bother to recover. these
// are the standard effects that every android device must have,
// and if they don't exist we have bigger problems.
- effects = new AndroidEffects(sessionId);
+ effects = new AndroidEffects(sessionId, deviceInfo);
}
return effects;
diff --git a/src/com/cyngn/audiofx/service/AudioFxService.java b/src/com/cyngn/audiofx/service/AudioFxService.java
index 3e0b959..7688f3e 100644
--- a/src/com/cyngn/audiofx/service/AudioFxService.java
+++ b/src/com/cyngn/audiofx/service/AudioFxService.java
@@ -36,6 +36,7 @@ import static com.cyngn.audiofx.Constants.DEVICE_AUDIOFX_TREBLE_STRENGTH;
import static com.cyngn.audiofx.Constants.DEVICE_AUDIOFX_VIRTUALIZER_ENABLE;
import static com.cyngn.audiofx.Constants.DEVICE_AUDIOFX_VIRTUALIZER_STRENGTH;
import static com.cyngn.audiofx.Constants.DEVICE_DEFAULT_GLOBAL_ENABLE;
+import static com.cyngn.audiofx.Constants.DEVICE_HEADSET;
import static com.cyngn.audiofx.Constants.DEVICE_SPEAKER;
import static com.cyngn.audiofx.Constants.EQUALIZER_BAND_LEVEL_RANGE;
import static com.cyngn.audiofx.Constants.EQUALIZER_CENTER_FREQS;
@@ -63,6 +64,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.v4.content.LocalBroadcastManager;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -79,6 +81,7 @@ import cyanogenmod.app.CustomTile;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -224,11 +227,9 @@ public class AudioFxService extends Service {
@Override
public void onSessionAdded(int stream, int sessionId) {
- if (stream == AudioManager.STREAM_MUSIC) {
- if (DEBUG) {
- Log.i(TAG, String.format("New audio session: %d", sessionId));
- }
-
+ if (stream == AudioManager.STREAM_MUSIC &&
+ !mHandler.hasMessages(MSG_ADD_SESSION, sessionId)) {
+ if (DEBUG) Log.i(TAG, String.format("New audio session: %d", sessionId));
mHandler.sendMessageAtFrontOfQueue(Message.obtain(mHandler, MSG_ADD_SESSION,
sessionId));
}
@@ -236,13 +237,12 @@ public class AudioFxService extends Service {
@Override
public void onSessionRemoved(int stream, int sessionId) {
- if (stream == AudioManager.STREAM_MUSIC) {
- if (DEBUG) {
- Log.i(TAG, String.format("Audio session queued for removal: %d", sessionId));
- }
+ if (stream == AudioManager.STREAM_MUSIC &&
+ !mHandler.hasMessages(MSG_REMOVE_SESSION, sessionId)) {
+ if (DEBUG) Log.i(TAG, String.format("Audio session queued for removal: %d", sessionId));
- mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_REMOVE_SESSION, sessionId),
- REMOVE_SESSIONS_DELAY);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler,
+ MSG_REMOVE_SESSION, sessionId), REMOVE_SESSIONS_DELAY);
}
}
}
@@ -251,33 +251,36 @@ public class AudioFxService extends Service {
@Override
public boolean handleMessage(Message msg) {
- EffectSet session;
- Integer sessionId;
+ EffectSet session = null;
+ Integer sessionId = 0;
+ int flags = 0;
+
switch (msg.what) {
case MSG_ADD_SESSION:
/**
* msg.obj = sessionId
*/
sessionId = (Integer) msg.obj;
- if (sessionId == 0) {
+ if (sessionId <= 0) {
break;
}
+
+ // Do the whole thing inside the lock when creating a new session so
+ // it's ready to go as fast as possible
synchronized (mAudioSessionsL) {
- mHandler.removeMessages(MSG_REMOVE_SESSION, sessionId);
- mHandler.removeMessages(MSG_UPDATE_FOR_SESSION, sessionId);
if (mAudioSessionsL.indexOfKey(sessionId) < 0) {
+ mHandler.removeMessages(MSG_REMOVE_SESSION, sessionId);
try {
- session = EffectsFactory.createEffectSet(getApplicationContext(), sessionId);
+ session = EffectsFactory.createEffectSet(getApplicationContext(),
+ sessionId, mCurrentDevice);
} catch (Exception e) {
- Log.e(TAG, "couldn't create effects for session id: " + sessionId,
- e);
+ Log.e(TAG, "couldn't create effects for session id: " + sessionId, e);
break;
}
mAudioSessionsL.put(sessionId, session);
if (DEBUG) Log.w(TAG, "added new EffectSet for sessionId=" + sessionId);
}
- mHandler.sendMessageAtFrontOfQueue(Message.obtain(mHandler, MSG_UPDATE_FOR_SESSION,
- ALL_CHANGED, 0, sessionId));
+ updateBackend(ALL_CHANGED, getSharedPreferences(getCurrentDeviceIdentifier(), 0), session);
}
break;
@@ -286,38 +289,39 @@ public class AudioFxService extends Service {
* msg.obj = sessionId
*/
sessionId = (Integer) msg.obj;
- if (sessionId == 0) {
+ if (sessionId <= 0) {
break;
}
synchronized (mAudioSessionsL) {
mHandler.removeMessages(MSG_UPDATE_FOR_SESSION, sessionId);
+
if (mAudioSessionsL.indexOfKey(sessionId) > -1) {
- final EffectSet effectSet = mAudioSessionsL.removeReturnOld(sessionId);
- if (effectSet != null && effectSet.isActive()) {
- effectSet.release();
- if (DEBUG) Log.w(TAG, "removed and released sessionId=" + sessionId);
- }
+ session = mAudioSessionsL.removeReturnOld(sessionId);
}
}
+ if (session != null) {
+ session.release();
+ if (DEBUG) Log.w(TAG, "removed and released sessionId=" + sessionId);
+ }
+
break;
case MSG_UPDATE_DSP:
/**
* msg.arg1 = update what flags
*/
+ flags = msg.arg1;
+
final String mode = getCurrentDeviceIdentifier();
if (DEBUG) Log.i(TAG, "Updating to configuration: " + mode);
// cancel updates for other effects, let them go through on the last call
synchronized (mAudioSessionsL) {
- mHandler.removeMessages(MSG_UPDATE_FOR_SESSION);
final int N = mAudioSessionsL.size();
for (int i = 0; i < N; i++) {
- final int sessionIdKey = mAudioSessionsL.keyAt(i);
- if (!mHandler.hasMessages(MSG_REMOVE_SESSION, sessionIdKey)) {
- Message.obtain(mHandler, MSG_UPDATE_FOR_SESSION, msg.arg1, 0, sessionIdKey)
- .sendToTarget();
- }
+ sessionId = mAudioSessionsL.keyAt(i);
+ Message.obtain(mHandler, MSG_UPDATE_FOR_SESSION, flags, 0, sessionId)
+ .sendToTarget();
}
}
break;
@@ -328,23 +332,29 @@ public class AudioFxService extends Service {
* msg.arg2 = unused
* msg.obj = session id integer (for consistency)
*/
- String device = getCurrentDeviceIdentifier();
sessionId = (Integer) msg.obj;
- if (DEBUG) {
- Log.i(TAG, "updating DSP for sessionId=" + sessionId + ", device=" + device);
+ flags = msg.arg1;
+
+ if (sessionId <= 0) {
+ break;
}
+
+ String device = getCurrentDeviceIdentifier();
+ if (DEBUG) Log.i(TAG, "updating DSP for sessionId=" + sessionId +
+ ", device=" + device + " flags=" + flags);
+
synchronized (mAudioSessionsL) {
session = mAudioSessionsL.get(sessionId);
-
- if (!mHandler.hasMessages(MSG_REMOVE_SESSION, sessionId)) {
- updateDsp(msg.arg1, getSharedPreferences(device, 0), session);
+ if (session != null) {
+ updateBackend(flags, getSharedPreferences(device, 0), session);
}
}
break;
case MSG_SELF_DESTRUCT:
- mHandler.removeMessages(MSG_SELF_DESTRUCT);
synchronized (mAudioSessionsL) {
+ mHandler.removeMessages(MSG_SELF_DESTRUCT);
+
if (mAudioSessionsL.size() == 0) {
stopSelf();
Log.w(TAG, "self destructing, no sessions active and nothing to do.");
@@ -365,7 +375,23 @@ public class AudioFxService extends Service {
mPreviousDevice = mCurrentDevice;
mCurrentDevice = outputDevice;
- update(ALL_CHANGED);
+ synchronized (mAudioSessionsL) {
+ // Update all the sessions for this output which are moving
+ final int N = mAudioSessionsL.size();
+ for (int i = 0; i < N; i++) {
+ sessionId = mAudioSessionsL.keyAt(i);
+ session = mAudioSessionsL.valueAt(i);
+ if (DEBUG) Log.d(TAG, "UPDATE_DEVICE prev=" +
+ (mPreviousDevice == null ? "none" : mPreviousDevice.getType()) +
+ " new=" + (mCurrentDevice == null ? "none" : mCurrentDevice.getType() +
+ " session=" + sessionId + " session-device=" +
+ (session.getDevice() == null ? "none" : session.getDevice().getType())));
+
+ session.setDevice(mCurrentDevice);
+ updateBackend(ALL_CHANGED, getSharedPreferences(getCurrentDeviceIdentifier(), 0), session);
+ }
+ }
+
Intent intent = new Intent(ACTION_DEVICE_OUTPUT_CHANGED);
intent.putExtra("device", mCurrentDevice.getId());
LocalBroadcastManager.getInstance(AudioFxService.this).sendBroadcast(intent);
@@ -557,7 +583,7 @@ public class AudioFxService extends Service {
// ======== DSP UPDATE METHODS BELOW ============= //
/**
- * Temporarily override a band level. {@link #updateDsp(int flags, SharedPreferences, EffectSet)} will take
+ * Temporarily override a band level. {@link #updateBackend(int flags, SharedPreferences, EffectSet)} will take
* care of overriding the preset value when a preset is selected
*/
private void updateEqBand(short band, float level, EffectSet effectSet) {
@@ -573,18 +599,16 @@ public class AudioFxService extends Service {
if (mHandler == null) {
return;
}
- if (!mHandler.hasMessages(MSG_UPDATE_DSP)) {
- mHandler.sendMessage(Message.obtain(mHandler, MSG_UPDATE_DSP, flags, 0));
+ mHandler.sendMessage(Message.obtain(mHandler, MSG_UPDATE_DSP, flags, 0));
- }
if ((flags & ALL_CHANGED) == ALL_CHANGED) {
updateQsTile();
}
}
- private void updateDsp(int flags, SharedPreferences prefs, EffectSet session) {
+ private synchronized void updateBackend(int flags, SharedPreferences prefs, EffectSet session) {
if (DEBUG) {
- Log.i(TAG, "updateDsp() called with " + "prefs = [" + prefs
+ Log.i(TAG, "updateBackend() called with " + "prefs = [" + prefs
+ "], session = [" + session + "]");
}
if (session == null) {
@@ -593,15 +617,35 @@ public class AudioFxService extends Service {
final boolean globalEnabled = prefs.getBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE,
DEVICE_DEFAULT_GLOBAL_ENABLE);
+
+ // global bypass toggle
session.setGlobalEnabled(globalEnabled);
+ // if we're bypassed, we can gtfo
+ if (!globalEnabled) {
+ return;
+ }
+
+ // tell the backend it's time to party
+ session.beginUpdate();
+
+ // Volume boost extended effect first
+ try {
+ if ((flags & VOLUME_BOOST_CHANGED) > 0 && session.hasVolumeBoost()) {
+ // maxx volume
+ session.enableVolumeBoost(prefs.getBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, false));
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error enabling volume boost!", e);
+ }
+
// bass
try {
if ((flags & BASS_BOOST_CHANGED) > 0) {
- session.enableBassBoost(globalEnabled
- && prefs.getBoolean(DEVICE_AUDIOFX_BASS_ENABLE, false));
+ boolean enable = prefs.getBoolean(DEVICE_AUDIOFX_BASS_ENABLE, false);
+ session.enableBassBoost(enable);
session.setBassBoostStrength(Short.valueOf(prefs
- .getString(DEVICE_AUDIOFX_BASS_STRENGTH, "0")));
+ .getString(DEVICE_AUDIOFX_BASS_STRENGTH, "0")));
}
} catch (Exception e) {
Log.e(TAG, "Error enabling bass boost!", e);
@@ -612,7 +656,7 @@ public class AudioFxService extends Service {
if ((flags & REVERB_CHANGED) > 0) {
short preset = Short.decode(prefs.getString(DEVICE_AUDIOFX_REVERB_PRESET,
String.valueOf(PresetReverb.PRESET_NONE)));
- session.enableReverb(globalEnabled && (preset > 0));
+ session.enableReverb(preset > 0);
session.setReverbPreset(preset);
}
} catch (Exception e) {
@@ -622,8 +666,8 @@ public class AudioFxService extends Service {
try {
if ((flags & EQ_CHANGED) > 0) {
- session.enableEqualizer(globalEnabled);
-
+ // equalizer is always on unless bypassed
+ session.enableEqualizer(true);
String savedPreset = prefs.getString(DEVICE_AUDIOFX_EQ_PRESET_LEVELS, null);
if (savedPreset != null) {
session.setEqualizerLevelsDecibels(EqUtils.stringBandsToFloats(savedPreset));
@@ -635,8 +679,8 @@ public class AudioFxService extends Service {
try {
if ((flags & VIRTUALIZER_CHANGED) > 0) {
- session.enableVirtualizer(globalEnabled
- && prefs.getBoolean(DEVICE_AUDIOFX_VIRTUALIZER_ENABLE, false));
+ boolean enable = prefs.getBoolean(DEVICE_AUDIOFX_VIRTUALIZER_ENABLE, false);
+ session.enableVirtualizer(enable);
session.setVirtualizerStrength(Short.valueOf(prefs.getString(
DEVICE_AUDIOFX_VIRTUALIZER_STRENGTH, "0")));
}
@@ -648,8 +692,8 @@ public class AudioFxService extends Service {
try {
if ((flags & TREBLE_BOOST_CHANGED) > 0 && session.hasTrebleBoost()) {
// treble
- session.enableTrebleBoost(
- globalEnabled && prefs.getBoolean(DEVICE_AUDIOFX_TREBLE_ENABLE, false));
+ boolean enable = prefs.getBoolean(DEVICE_AUDIOFX_TREBLE_ENABLE, false);
+ session.enableTrebleBoost(enable);
session.setTrebleBoostStrength(Short.valueOf(
prefs.getString(DEVICE_AUDIOFX_TREBLE_STRENGTH, "0")));
}
@@ -657,15 +701,8 @@ public class AudioFxService extends Service {
Log.e(TAG, "Error enabling treble boost!", e);
}
- try {
- if ((flags & VOLUME_BOOST_CHANGED) > 0 && session.hasVolumeBoost()) {
- // maxx volume
- session.enableVolumeBoost(
- globalEnabled && prefs.getBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, false));
- }
- } catch (Exception e) {
- Log.e(TAG, "Error enabling volume boost!", e);
- }
+ // mic drop
+ session.commitUpdate();
}
/**
@@ -696,7 +733,7 @@ public class AudioFxService extends Service {
}
return;
}
- EffectSet temp = EffectsFactory.createEffectSet(getApplicationContext(), 0);
+ EffectSet temp = EffectsFactory.createEffectSet(getApplicationContext(), 0, null);
final int numBands = temp.getNumEqualizerBands();
final int numPresets = temp.getNumEqualizerPresets();
@@ -761,6 +798,14 @@ public class AudioFxService extends Service {
.commit();
}
+ private int findInList(String needle, List<String> haystack) {
+ for (int i = 0; i < haystack.size(); i++) {
+ if (haystack.get(i).equalsIgnoreCase(needle)) {
+ return i;
+ }
+ }
+ return -1;
+ }
/**
* This method sets up some *persisted* defaults.
@@ -770,68 +815,76 @@ public class AudioFxService extends Service {
if (DEBUG) {
Log.d(TAG, "applyDefaults() called with overridePrevious = [" + overridePrevious + "]");
}
+
+ if (!(overridePrevious || !getSharedPrefsFile(DEVICE_SPEAKER).exists() ||
+ !getSharedPrefsFile(AUDIOFX_GLOBAL_FILE).exists())) {
+ return;
+ }
+
final SharedPreferences globalPrefs = getSharedPreferences(AUDIOFX_GLOBAL_FILE, 0);
- if (globalPrefs.getBoolean(AUDIOFX_GLOBAL_HAS_MAXXAUDIO, false)) {
- // Maxx Audio defaults:
- // enable speaker by default, enable maxx volume, set preset to the first index,
- // which should be flat
- if (!getSharedPrefsFile(DEVICE_SPEAKER).exists() || overridePrevious) {
- getSharedPreferences(DEVICE_SPEAKER, 0)
- .edit()
- .putBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE, true)
- .putString(DEVICE_AUDIOFX_EQ_PRESET, "0")
- .putBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, true)
- .commit();
- }
- } else if (globalPrefs.getBoolean(AUDIOFX_GLOBAL_HAS_DTS, false)) {
- // do nothing for DTS
- } else {
- // apply defaults for all others
- if (Integer.parseInt(globalPrefs.getString(EQUALIZER_NUMBER_OF_BANDS, "0")) == 5) {
-
- // for 5 band configs, let's add a `Small Speaker` configuration if one
- // doesn't exist ( from oss AudioFX: -170;270;50;-220;200 )
- int currentPresets = Integer.parseInt(
- globalPrefs.getString(EQUALIZER_NUMBER_OF_PRESETS, "0"));
-
- final String currentPresetNames = globalPrefs.getString(EQUALIZER_PRESET_NAMES, "");
-
- // we use the name as keys - get the english string so its consistent with the
- // others even if user has changed locale
- final String smallSpeakerPresetName
- = getNonLocalizedString(R.string.small_speakers);
-
- // sanity check
- if (currentPresetNames.toLowerCase().contains(smallSpeakerPresetName)) {
- // nothing to do!
- return;
- }
- // append new preset identifier
- String newPresetNames = currentPresetNames
- + (currentPresets > 0 ? "|" : "")
- + smallSpeakerPresetName;
-
- // set this new preset as the default and enable it for speaker
- if (!getSharedPrefsFile(DEVICE_SPEAKER).exists() || overridePrevious) {
- getSharedPreferences(DEVICE_SPEAKER, 0)
- .edit()
- .putBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE, true)
- .putString(DEVICE_AUDIOFX_EQ_PRESET, Integer.toString(currentPresets))
- .commit();
- }
+ // Nothing to see here for DTS
+ if (globalPrefs.getBoolean(AUDIOFX_GLOBAL_HAS_DTS, false)) {
+ return;
+ }
- // currentPresets is incremented below
- if (!getSharedPrefsFile(AUDIOFX_GLOBAL_FILE).exists() || overridePrevious) {
- globalPrefs
- .edit()
- .putString(EQUALIZER_PRESET + currentPresets, "-170;270;50;-220;200")
- .putString(EQUALIZER_PRESET_NAMES, newPresetNames)
- .putString(EQUALIZER_NUMBER_OF_PRESETS,
- Integer.toString(++currentPresets))
- .commit();
- }
- }
+ // set up the builtin speaker configuration
+ final String smallSpeakers = getNonLocalizedString(R.string.small_speakers);
+ final List<String> presetNames = Arrays.asList(
+ globalPrefs.getString(EQUALIZER_PRESET_NAMES, "").split("\\|"));
+ final SharedPreferences speakerPrefs = getSharedPreferences(DEVICE_SPEAKER, 0);
+
+ if (globalPrefs.getBoolean(AUDIOFX_GLOBAL_HAS_MAXXAUDIO, false)) {
+ // MaxxAudio defaults for builtin speaker:
+ // maxxvolume: on maxxbass: 40% maxxtreble: 32%
+ speakerPrefs.edit()
+ .putBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE, true)
+ .putBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, true)
+ .putBoolean(DEVICE_AUDIOFX_BASS_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_BASS_STRENGTH, "400")
+ .putBoolean(DEVICE_AUDIOFX_TREBLE_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_TREBLE_STRENGTH, "32")
+ .commit();
+
+ // Defaults for headphones
+ // maxxvolume: on maxxbass: 20% maxxtreble: 40% maxxspace: 20%
+ getSharedPreferences(DEVICE_HEADSET, 0).edit()
+ .putBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE, true)
+ .putBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, true)
+ .putBoolean(DEVICE_AUDIOFX_BASS_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_BASS_STRENGTH, "200")
+ .putBoolean(DEVICE_AUDIOFX_TREBLE_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_TREBLE_STRENGTH, "40")
+ .putBoolean(DEVICE_AUDIOFX_VIRTUALIZER_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_VIRTUALIZER_STRENGTH, "200")
+ .commit();
+ }
+
+ // for 5 band configs, let's add a `Small Speaker` configuration if one
+ // doesn't exist ( from oss AudioFX: -170;270;50;-220;200 )
+ if (Integer.parseInt(globalPrefs.getString(EQUALIZER_NUMBER_OF_BANDS, "0")) == 5 &&
+ findInList(smallSpeakers, presetNames) < 0) {
+
+ int currentPresets = Integer.parseInt(
+ globalPrefs.getString(EQUALIZER_NUMBER_OF_PRESETS, "0"));
+
+ presetNames.add(smallSpeakers);
+ String newPresetNames = TextUtils.join("|", presetNames);
+ globalPrefs.edit()
+ .putString(EQUALIZER_PRESET + currentPresets, "-170;270;50;-220;200")
+ .putString(EQUALIZER_PRESET_NAMES, newPresetNames)
+ .putString(EQUALIZER_NUMBER_OF_PRESETS, Integer.toString(++currentPresets))
+ .commit();
+
+ }
+
+ // set the small speakers preset as the default
+ int idx = findInList(smallSpeakers, presetNames);
+ if (idx >= 0) {
+ speakerPrefs.edit()
+ .putBoolean(DEVICE_AUDIOFX_GLOBAL_ENABLE, true)
+ .putString(DEVICE_AUDIOFX_EQ_PRESET, String.valueOf(idx))
+ .commit();
}
}