diff options
author | Steve Kondik <shade@chemlab.org> | 2016-03-22 18:42:55 -0700 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2016-03-23 16:52:01 -0700 |
commit | bf30e5b1e50d33ae82ab73a691b89f5393eb6c21 (patch) | |
tree | 8301688cb440a2b1a469d6f9d5aa90471ac9cc02 | |
parent | 22e31f3e3f6651f1538d4cd904faa4a01e07aa0b (diff) | |
download | android_packages_apps_AudioFX-bf30e5b1e50d33ae82ab73a691b89f5393eb6c21.tar.gz android_packages_apps_AudioFX-bf30e5b1e50d33ae82ab73a691b89f5393eb6c21.tar.bz2 android_packages_apps_AudioFX-bf30e5b1e50d33ae82ab73a691b89f5393eb6c21.zip |
audiofx: Add support for session callback API
* I recently introduced a new API which allows an application to
receive callbacks when the default postprocessing effects are
attached to a stream. This patch adds support to the OSS
version for these callbacks.
* The list of default effects needs to be configured in the device's
audio_effects.conf for this to actually fire. Care should be
taken that the default effects can be offloaded (if required), and
that no audible clicks or pops are produced when they are attached.
* Also tightened up the locking around the session list so that we
stay consistent even if both callbacks as well as intents get fired.
Change-Id: I580f1d7426c02a7806ffeecd97d5233b96aedbd8
-rw-r--r-- | src/org/cyanogenmod/audiofx/HeadsetService.java | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/src/org/cyanogenmod/audiofx/HeadsetService.java b/src/org/cyanogenmod/audiofx/HeadsetService.java index 17f6282..af43692 100644 --- a/src/org/cyanogenmod/audiofx/HeadsetService.java +++ b/src/org/cyanogenmod/audiofx/HeadsetService.java @@ -16,23 +16,26 @@ package org.cyanogenmod.audiofx; import android.app.Service; -import android.bluetooth.BluetoothA2dp; -import android.content.*; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; import android.media.AudioManager; import android.media.AudioPatch; import android.media.AudioPort; -import android.media.audiofx.*; -import android.net.NetworkInfo; -import android.net.wifi.p2p.WifiP2pManager; +import android.media.AudioSystem; +import android.media.audiofx.AudioEffect; +import android.media.audiofx.BassBoost; +import android.media.audiofx.Equalizer; +import android.media.audiofx.PresetReverb; +import android.media.audiofx.Virtualizer; import android.os.Binder; import android.os.IBinder; import android.util.Log; +import android.util.SparseArray; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; /** * <p>This calls listen to events that affect DSP function and responds to them.</p> @@ -190,6 +193,45 @@ public class HeadsetService extends Service { protected static final String TAG = HeadsetService.class.getSimpleName(); public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private FxSessionCallback mSessionCallback; + + private class FxSessionCallback implements AudioSystem.EffectSessionCallback { + + @Override + public void onSessionAdded(int stream, int sessionId) { + if (stream == AudioManager.STREAM_MUSIC) { + if (sessionId == 0) { + return; + } + if (DEBUG) Log.i(TAG, String.format("New audio session: %d", sessionId)); + + synchronized (mAudioSessionsL) { + if (mAudioSessionsL.indexOfKey(sessionId) < 0) { + mAudioSessionsL.put(sessionId, new EffectSet(sessionId)); + } + updateLocked(); + } + } + } + + @Override + public void onSessionRemoved(int stream, int sessionId) { + if (stream == AudioManager.STREAM_MUSIC) { + if (sessionId == 0) { + return; + } + if (DEBUG) Log.i(TAG, String.format("Audio session removed: %d", sessionId)); + + synchronized (mAudioSessionsL) { + EffectSet gone = mAudioSessionsL.removeReturnOld(sessionId); + if (gone != null) { + gone.release(); + } + } + } + } + } + public class LocalBinder extends Binder { public HeadsetService getService() { return HeadsetService.this; @@ -201,7 +243,7 @@ public class HeadsetService extends Service { /** * Known audio sessions and their associated audioeffect suites. */ - protected final ConcurrentHashMap<Integer, EffectSet> mAudioSessions = new ConcurrentHashMap<Integer, EffectSet>(); + private final SparseArray<EffectSet> mAudioSessionsL = new SparseArray<EffectSet>(); AudioPortListener mAudioPortListener; @@ -219,19 +261,11 @@ public class HeadsetService extends Service { String action = intent.getAction(); int sessionId = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, 0); if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)) { - Log.i(TAG, String.format("New audio session: %d", sessionId)); - if (!mAudioSessions.containsKey(sessionId)) { - mAudioSessions.put(sessionId, new EffectSet(sessionId)); - } + mSessionCallback.onSessionAdded(AudioManager.STREAM_MUSIC, sessionId); } if (action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) { - Log.i(TAG, String.format("Audio session removed: %d", sessionId)); - EffectSet gone = mAudioSessions.remove(sessionId); - if (gone != null) { - gone.release(); - } + mSessionCallback.onSessionRemoved(AudioManager.STREAM_MUSIC, sessionId); } - update(); } }; @@ -348,6 +382,9 @@ public class HeadsetService extends Service { AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); am.registerAudioPortUpdateListener(mAudioPortListener = new AudioPortListener(this)); + mSessionCallback = new FxSessionCallback(); + AudioSystem.setEffectSessionCallback(mSessionCallback); + saveDefaults(); } @@ -363,6 +400,7 @@ public class HeadsetService extends Service { unregisterReceiver(mAudioSessionReceiver); unregisterReceiver(mPreferenceUpdateReceiver); + AudioSystem.setEffectSessionCallback(null); } @Override @@ -415,7 +453,9 @@ public class HeadsetService extends Service { } public EffectSet getEffects(int session) { - return mAudioSessions.get(session); + synchronized (mAudioSessionsL) { + return mAudioSessionsL.get(session); + } } private void saveDefaults() { @@ -511,15 +551,21 @@ public class HeadsetService extends Service { /** * Push new configuration to audio stack. */ - protected synchronized void update() { + void update() { + synchronized (mAudioSessionsL) { + updateLocked(); + } + } + + private void updateLocked() { final String mode = getAudioOutputRouting(); SharedPreferences preferences = getSharedPreferences( mode, 0); if (DEBUG) Log.i(TAG, "Selected configuration: " + mode); - for (Integer sessionId : mAudioSessions.keySet()) { - updateDsp(preferences, mAudioSessions.get(sessionId)); + for (int i = 0; i < mAudioSessionsL.size(); i++) { + updateDsp(preferences, mAudioSessionsL.valueAt(i)); } } |