summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-04-23 05:27:03 -0700
committerSteve Kondik <steve@cyngn.com>2016-04-27 00:29:17 -0700
commit2e67e76357265b32b9c3293c63373acaf5288588 (patch)
tree6910be603df405f0d549f772d6d6d35d4d2b6c88
parent73f209aad49859a5da51e5c806b3b3dd3be3960d (diff)
downloadandroid_packages_apps_AudioFX-2e67e76357265b32b9c3293c63373acaf5288588.tar.gz
android_packages_apps_AudioFX-2e67e76357265b32b9c3293c63373acaf5288588.tar.bz2
android_packages_apps_AudioFX-2e67e76357265b32b9c3293c63373acaf5288588.zip
audiofx: Use CMAudioService for session callbacks
* Also get rid of the dynamic receiver and register everything we want to receive in the manifest so that we can be sure that our service starts when audio sessions are being created. Change-Id: I9880c0277ba7688095c236ad38a3d98824870776
-rw-r--r--Android.mk9
-rw-r--r--AndroidManifest.xml11
-rw-r--r--src/org/cyanogenmod/audiofx/HeadsetService.java130
-rw-r--r--src/org/cyanogenmod/audiofx/ServiceDispatcher.java55
4 files changed, 147 insertions, 58 deletions
diff --git a/Android.mk b/Android.mk
index 5e45112..7b18e38 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,18 +1,13 @@
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
+include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
-
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
LOCAL_JAVA_LIBRARIES := framework
-
+LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.sdk
LOCAL_OVERRIDES_PACKAGES := DSPManager
-
LOCAL_PACKAGE_NAME := AudioFX
-
LOCAL_PRIVILEGED_MODULE := true
-
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 60a82fe..3d87d52 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -39,6 +39,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+ <uses-permission android:name="cyanogenmod.permission.OBSERVE_AUDIO_SESSIONS" />
<application
android:icon="@mipmap/ic_launcher_audiofx"
@@ -107,5 +108,15 @@
</intent-filter>
</receiver>
+ <receiver android:name=".ServiceDispatcher">
+ <intent-filter>
+ <action android:name="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION"/>
+ <action android:name="android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION"/>
+ <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
+ <action android:name="cyanogenmod.intent.action.ACTION_AUDIO_SESSIONS_CHANGED" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </receiver>
+
</application>
</manifest>
diff --git a/src/org/cyanogenmod/audiofx/HeadsetService.java b/src/org/cyanogenmod/audiofx/HeadsetService.java
index 6528465..98bf20e 100644
--- a/src/org/cyanogenmod/audiofx/HeadsetService.java
+++ b/src/org/cyanogenmod/audiofx/HeadsetService.java
@@ -37,6 +37,9 @@ import android.util.SparseArray;
import java.util.Arrays;
+import cyanogenmod.media.AudioSessionInfo;
+import cyanogenmod.media.CMAudioManager;
+
/**
* <p>This calls listen to events that affect DSP function and responds to them.</p>
* <ol>
@@ -193,7 +196,6 @@ 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 void addSession(int sessionId) {
if (sessionId == 0) {
@@ -223,31 +225,27 @@ public class HeadsetService extends Service {
}
}
- private class FxSessionCallback implements AudioSystem.EffectSessionCallback {
-
- @Override
- public void onSessionAdded(int stream, int sessionId, int flags,
- int channelMask, int uid) {
- if (stream == AudioManager.STREAM_MUSIC &&
- (flags < 0 || (flags & 0x8) > 0 || (flags & 0x10) > 0) &&
- (channelMask < 0 || channelMask > 1)) {
-
- // Never auto-attach is someone is recording! We don't want to interfere with any sort of
- // loopback mechanisms.
- final boolean recording = AudioSystem.isSourceActive(0) || AudioSystem.isSourceActive(6);
- if (recording) {
- Log.w(TAG, "Recording in progress, not performing auto-attach!");
- return;
- }
- addSession(sessionId);
+ public void addSession(AudioSessionInfo info) {
+ if (info.getStream() == AudioManager.STREAM_MUSIC &&
+ (info.getFlags() < 0 || (info.getFlags() & 0x8) > 0 || (info.getFlags() & 0x10) > 0) &&
+ (info.getChannelMask() < 0 || info.getChannelMask() > 1)) {
+
+ // Never auto-attach is someone is recording! We don't want to
+ // interfere with any sort of
+ // loopback mechanisms.
+ final boolean recording = AudioSystem.isSourceActive(0)
+ || AudioSystem.isSourceActive(6);
+ if (recording) {
+ Log.w(TAG, "Recording in progress, not performing auto-attach!");
+ return;
}
+ addSession(info.getSessionId());
}
+ }
- @Override
- public void onSessionRemoved(int stream, int sessionId) {
- if (stream == AudioManager.STREAM_MUSIC) {
- removeSession(sessionId);
- }
+ public void removeSession(AudioSessionInfo info) {
+ if (info.getStream() == AudioManager.STREAM_MUSIC) {
+ removeSession(info.getSessionId());
}
}
@@ -272,23 +270,6 @@ public class HeadsetService extends Service {
private float[] mOverriddenEqualizerLevels;
/**
- * Receive new broadcast intents for adding DSP to session
- */
- private final BroadcastReceiver mAudioSessionReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- int sessionId = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, 0);
- if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)) {
- addSession(sessionId);
- }
- if (action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
- removeSession(sessionId);
- }
- }
- };
-
- /**
* Update audio parameters when preferences have been updated.
*/
private final BroadcastReceiver mPreferenceUpdateReceiver = new BroadcastReceiver() {
@@ -399,26 +380,75 @@ public class HeadsetService extends Service {
super.onCreate();
Log.i(TAG, "Starting service.");
- IntentFilter audioFilter = new IntentFilter();
- audioFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
- audioFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
- audioFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- registerReceiver(mAudioSessionReceiver, audioFilter);
-
registerReceiver(mPreferenceUpdateReceiver,
new IntentFilter(ACTION_UPDATE_PREFERENCES));
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.registerAudioPortUpdateListener(mAudioPortListener = new AudioPortListener(this));
- mSessionCallback = new FxSessionCallback();
- AudioSystem.setEffectSessionCallback(mSessionCallback);
-
saveDefaults();
}
+
+ /**
+ * maps {@link AudioEffect#EXTRA_CONTENT_TYPE} to an AudioManager.STREAM_* item
+ */
+ private static int mapContentTypeToStream(int contentType) {
+ switch (contentType) {
+ case AudioEffect.CONTENT_TYPE_VOICE:
+ return AudioManager.STREAM_VOICE_CALL;
+ case AudioEffect.CONTENT_TYPE_GAME:
+ // explicitly don't support game effects right now
+ return -1;
+ case AudioEffect.CONTENT_TYPE_MOVIE:
+ case AudioEffect.CONTENT_TYPE_MUSIC:
+ default:
+ return AudioManager.STREAM_MUSIC;
+ }
+ }
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null && intent.getAction() != null) {
+ if (DEBUG) {
+ Log.i(TAG, "onStartCommand() called with " + "intent = [" + intent + "], flags = ["
+ + flags + "], startId = [" + startId + "], extras = [" +
+ (intent.getExtras() == null ? "null" : intent.getExtras().toString())
+ + "]");
+ }
+ String action = intent.getAction();
+ int sessionId = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, 0);
+ String pkg = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
+ int stream = mapContentTypeToStream(
+ intent.getIntExtra(AudioEffect.EXTRA_CONTENT_TYPE,
+ AudioEffect.CONTENT_TYPE_MUSIC));
+
+ if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)) {
+ if (DEBUG) {
+ Log.i(TAG, String.format("New audio session: %d package: %s contentType=%d",
+ sessionId, pkg, stream));
+ }
+ addSession(sessionId);
+
+ } else if (action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
+
+ removeSession(sessionId);
+
+ } else if (action.equals(CMAudioManager.ACTION_AUDIO_SESSIONS_CHANGED)) {
+
+ final AudioSessionInfo info = (AudioSessionInfo) intent.getParcelableExtra(
+ CMAudioManager.EXTRA_SESSION_INFO);
+ if (info != null && info.getSessionId() > 0) {
+ boolean added = intent.getBooleanExtra(CMAudioManager.EXTRA_SESSION_ADDED,
+ false);
+ if (added) {
+ addSession(info);
+ } else {
+ removeSession(info);
+ }
+ }
+ }
+ }
return START_STICKY;
}
@@ -427,9 +457,7 @@ public class HeadsetService extends Service {
super.onDestroy();
Log.i(TAG, "Stopping service.");
- unregisterReceiver(mAudioSessionReceiver);
unregisterReceiver(mPreferenceUpdateReceiver);
- AudioSystem.setEffectSessionCallback(null);
}
@Override
diff --git a/src/org/cyanogenmod/audiofx/ServiceDispatcher.java b/src/org/cyanogenmod/audiofx/ServiceDispatcher.java
new file mode 100644
index 0000000..7a838b1
--- /dev/null
+++ b/src/org/cyanogenmod/audiofx/ServiceDispatcher.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.cyanogenmod.audiofx;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.media.audiofx.AudioEffect;
+import android.util.Log;
+
+import cyanogenmod.media.AudioSessionInfo;
+import cyanogenmod.media.CMAudioManager;
+
+public class ServiceDispatcher extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ Intent service = new Intent(context.getApplicationContext(), HeadsetService.class);
+ String action = intent.getAction();
+
+ // We can also get AUDIO_BECOMING_NOISY, which means a device change is
+ // coming and we should wake up to handle it.
+ if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
+ action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
+ int sessionId = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, 0);
+ String pkg = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
+ service.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
+ service.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, pkg);
+ } else if (action.equals(CMAudioManager.ACTION_AUDIO_SESSIONS_CHANGED)) {
+
+ // callback from CMAudioService
+ final AudioSessionInfo info = (AudioSessionInfo)intent.getParcelableExtra(
+ CMAudioManager.EXTRA_SESSION_INFO);
+ boolean added = intent.getBooleanExtra(CMAudioManager.EXTRA_SESSION_ADDED, false);
+ service.putExtra(CMAudioManager.EXTRA_SESSION_INFO, info);
+ service.putExtra(CMAudioManager.EXTRA_SESSION_ADDED, added);
+ }
+
+ service.setAction(action);
+ context.startService(service);
+ }
+}