summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-01-14 02:46:40 -0800
committerSteve Kondik <shade@chemlab.org>2016-03-08 17:34:16 -0800
commit0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa (patch)
tree6ad8d2cd4abd2f7f2fe6beb8348fd696426f76b2 /services/audiopolicy
parent51aee1e55bee9cf8e4fd30ecf19fccd7ab7bfc15 (diff)
downloadframeworks_av-0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa.zip
frameworks_av-0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa.tar.gz
frameworks_av-0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa.tar.bz2
audiopolicy: Add notification when default effects are updated
* In M, we now have the ability to define a default set of audio effect on a per-stream basis. This allows us to get around the problem of apps not sending the control intents so we can implement smart global effects for specific media types. * We still need a session id in order to get a handle and configure them from an app like AudioFX, so we'll need to add some plumbing in order to send an event to interested applications. * This patch implements the native side of this. The Java layer will call down thru AudioSystem and register a callback which will be invoked by the audio policy when default effects are updated on a stream. This callback will receive both the stream type as well as the session id. * Attaching this listener requires that the caller hold the MODIFY_AUDIO_ROUTING permission. Change-Id: I142b15f2585ffca6a953c3e828e2a7c07b24f56c
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h3
-rw-r--r--services/audiopolicy/service/AudioPolicyClientImpl.cpp6
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.cpp7
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.h6
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp82
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h27
6 files changed, 125 insertions, 6 deletions
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index c1e7bc0..a5edc14 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -331,6 +331,9 @@ public:
virtual audio_unique_id_t newAudioUniqueId() = 0;
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
+
+ virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 489a9be..d71daa4 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -219,6 +219,12 @@ void AudioPolicyService::AudioPolicyClient::onDynamicPolicyMixStateUpdate(
mAudioPolicyService->onDynamicPolicyMixStateUpdate(regId, state);
}
+void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, sessionId, added);
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
{
return AudioSystem::newAudioUniqueId();
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 26857b1..d72e255 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -28,6 +28,7 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
#include <cutils/config_utils.h>
+#include "AudioPolicyService.h"
#include "AudioPolicyEffects.h"
#include "ServiceUtilities.h"
@@ -37,7 +38,8 @@ namespace android {
// AudioPolicyEffects Implementation
// ----------------------------------------------------------------------------
-AudioPolicyEffects::AudioPolicyEffects()
+AudioPolicyEffects::AudioPolicyEffects(AudioPolicyService *audioPolicyService) :
+ mAudioPolicyService(audioPolicyService)
{
// load automatic audio effect modules
if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE2, R_OK) == 0) {
@@ -244,6 +246,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
if (idx < 0) {
procDesc = new EffectVector(audioSession);
mOutputSessions.add(audioSession, procDesc);
+
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, true);
} else {
// EffectVector is existing and we just need to increase ref count
procDesc = mOutputSessions.valueAt(idx);
@@ -299,6 +303,7 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false);
ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
audioSession);
}
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 3845050..2023784 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -31,6 +31,8 @@
namespace android {
+class AudioPolicyService;
+
// ----------------------------------------------------------------------------
// AudioPolicyEffects class
@@ -44,7 +46,7 @@ public:
// The constructor will parse audio_effects.conf
// First it will look whether vendor specific file exists,
// otherwise it will parse the system default file.
- AudioPolicyEffects();
+ AudioPolicyEffects(AudioPolicyService *audioPolicyService);
virtual ~AudioPolicyEffects();
// NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -192,6 +194,8 @@ private:
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
// Automatic output effects are unique for audiosession ID
KeyedVector< int32_t, EffectVector* > mOutputSessions;
+
+ AudioPolicyService *mAudioPolicyService;
};
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 12cca65..dbeed80 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -116,7 +116,7 @@ void AudioPolicyService::onFirstRef()
#endif
}
// load audio processing modules
- sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
+ sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(this);
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
@@ -177,6 +177,23 @@ void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled)
mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled);
}
+status_t AudioPolicyService::setEffectSessionCallbacksEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (mNotificationClients.indexOfKey(uid) < 0) {
+ return NO_INIT;
+ }
+ if (!modifyAudioRoutingAllowed()) {
+ ALOGE("setEffectSessionCallbacksEnabled requires MODIFY_AUDIO_ROUTING");
+ return PERMISSION_DENIED;
+ }
+ mNotificationClients.valueFor(uid)->setEffectSessionCallbacksEnabled(enabled);
+ return OK;
+}
+
+
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid)
{
@@ -254,11 +271,31 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
+void AudioPolicyService::onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ bool added)
+{
+ ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ stream, sessionId, added);
+ mOutputCommandThread->effectSessionUpdateCommand(stream, sessionId, added);
+}
+
+void AudioPolicyService::doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ bool added)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ }
+}
+
AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
const sp<IAudioPolicyServiceClient>& client,
uid_t uid)
: mService(service), mUid(uid), mAudioPolicyServiceClient(client),
- mAudioPortCallbacksEnabled(false)
+ mAudioPortCallbacksEnabled(false),
+ mEffectSessionCallbacksEnabled(false)
{
}
@@ -289,6 +326,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
}
}
+void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ if (mAudioPolicyServiceClient != 0 && mEffectSessionCallbacksEnabled) {
+ mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ }
+}
+
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
String8 regId, int32_t state)
{
@@ -302,6 +347,10 @@ void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool e
mAudioPortCallbacksEnabled = enabled;
}
+void AudioPolicyService::NotificationClient::setEffectSessionCallbacksEnabled(bool enabled)
+{
+ mEffectSessionCallbacksEnabled = enabled;
+}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
@@ -579,6 +628,20 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState);
mLock.lock();
} break;
+ case EFFECT_SESSION_UPDATE: {
+ EffectSessionUpdateData *data =
+ (EffectSessionUpdateData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing effect session update %d %d %d",
+ data->mStream, data->mSessionId, data->mAdded);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded);
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -851,6 +914,21 @@ void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand(
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = EFFECT_SESSION_UPDATE;
+ EffectSessionUpdateData *data = new EffectSessionUpdateData();
+ data->mStream = stream;
+ data->mSessionId = sessionId;
+ data->mAdded = added;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)",
+ stream, sessionId, added);
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d11294b..27a62f4 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -202,6 +202,8 @@ public:
audio_io_handle_t *handle);
virtual status_t stopAudioSource(audio_io_handle_t handle);
+ virtual status_t setEffectSessionCallbacksEnabled(bool enabled);
+
status_t doStartOutput(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session);
@@ -229,6 +231,11 @@ public:
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
+ void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+ void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -260,7 +267,8 @@ private:
UPDATE_AUDIOPORT_LIST,
UPDATE_AUDIOPATCH_LIST,
SET_AUDIOPORT_CONFIG,
- DYN_POLICY_MIX_STATE_UPDATE
+ DYN_POLICY_MIX_STATE_UPDATE,
+ EFFECT_SESSION_UPDATE
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -303,6 +311,8 @@ private:
int delayMs);
void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
+ void effectSessionUpdateCommand(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
private:
class AudioCommandData;
@@ -399,6 +409,13 @@ private:
int32_t mState;
};
+ class EffectSessionUpdateData : public AudioCommandData {
+ public:
+ audio_stream_type_t mStream;
+ audio_unique_id_t mSessionId;
+ bool mAdded;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -508,6 +525,9 @@ private:
virtual audio_unique_id_t newAudioUniqueId();
+ virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+
private:
AudioPolicyService *mAudioPolicyService;
};
@@ -524,7 +544,9 @@ private:
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void setAudioPortCallbacksEnabled(bool enabled);
-
+ void setEffectSessionCallbacksEnabled(bool enabled);
+ void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
@@ -536,6 +558,7 @@ private:
const uid_t mUid;
const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
bool mAudioPortCallbacksEnabled;
+ bool mEffectSessionCallbacksEnabled;
};
// Internal dump utilities.