summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <shade@chemlab.org>2016-03-22 18:42:55 -0700
committerSteve Kondik <shade@chemlab.org>2016-03-23 16:52:01 -0700
commitbf30e5b1e50d33ae82ab73a691b89f5393eb6c21 (patch)
tree8301688cb440a2b1a469d6f9d5aa90471ac9cc02
parent22e31f3e3f6651f1538d4cd904faa4a01e07aa0b (diff)
downloadandroid_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.java94
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));
}
}