summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-03-07 03:43:14 -0800
committerSteve Kondik <shade@chemlab.org>2016-03-08 17:34:54 -0800
commit47f8c7303c9e2054f1492b02b6c7472385c52dc9 (patch)
tree99179985590f64d6c01051365deaa59552d1d582 /services/audiopolicy
parent0479d7c79a7fd6f112e8dc7e45c009cf6602dbaa (diff)
downloadframeworks_av-47f8c7303c9e2054f1492b02b6c7472385c52dc9.zip
frameworks_av-47f8c7303c9e2054f1492b02b6c7472385c52dc9.tar.gz
frameworks_av-47f8c7303c9e2054f1492b02b6c7472385c52dc9.tar.bz2
audiopolicy: Defer release of output session effects
* Some effects modules are racy and don't tolerate being destroyed and immediately resurrected on the same session. This is the common case when switching tracks, and the use of default output effects makes the problem even worse. Certain apps which handle gapless in a sloppy way are also to blame. * Instead of immediately nuking the entire descriptor with the stream, just decrease the refcount and defer it for 10 seconds. If it needs resurrected, the refcount will be increased and the delayed release command will not shoot it in the face. Change-Id: I068dd72c4180023a74eb9ccbe8a180f6f0683dbf
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.cpp35
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.h6
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp39
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h18
4 files changed, 96 insertions, 2 deletions
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index d72e255..f2d7f6f 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -295,16 +295,49 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
}
EffectVector *procDesc = mOutputSessions.valueAt(index);
+
+ // just in case it already has a death wish
+ if (procDesc->mRefCount == 0) {
+ return NO_ERROR;
+ }
+
procDesc->mRefCount--;
ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
audioSession, procDesc->mRefCount);
+
+ if (procDesc->mRefCount == 0) {
+ mAudioPolicyService->releaseOutputSessionEffectsDelayed(
+ output, stream, audioSession, 10000);
+ }
+
+ return status;
+}
+
+status_t AudioPolicyEffects::doReleaseOutputSessionEffects(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession)
+{
+ status_t status = NO_ERROR;
+ (void) output; // argument not used for now
+
+ Mutex::Autolock _l(mLock);
+ ssize_t index = mOutputSessions.indexOfKey(audioSession);
+ if (index < 0) {
+ ALOGV("doReleaseOutputSessionEffects: no output processing was attached to this stream");
+ return NO_ERROR;
+ }
+
+ EffectVector *procDesc = mOutputSessions.valueAt(index);
+ ALOGV("doReleaseOutputSessionEffects(): session: %d, refCount: %d",
+ audioSession, procDesc->mRefCount);
+
if (procDesc->mRefCount == 0) {
procDesc->setProcessorEnabled(false);
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false);
- ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
+ ALOGV("doReleaseOutputSessionEffects(): output processing released from session: %d",
audioSession);
}
return status;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 2023784..7988515 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -86,6 +86,12 @@ public:
audio_stream_type_t stream,
int audioSession);
+ // For deferred release
+ status_t doReleaseOutputSessionEffects(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession);
+
+
private:
// class to store the description of an effects and its parameters
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index dbeed80..58cfe37 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -357,6 +357,13 @@ void AudioPolicyService::binderDied(const wp<IBinder>& who) {
IPCThreadState::self()->getCallingPid());
}
+void AudioPolicyService::releaseOutputSessionEffectsDelayed(
+ audio_io_handle_t output, audio_stream_type_t stream,
+ audio_unique_id_t sessionId, int delayMs)
+{
+ mAudioCommandThread->releaseOutputSessionEffectsCommand(output, stream, sessionId, delayMs);
+}
+
static bool tryLock(Mutex& mutex)
{
bool locked = false;
@@ -641,6 +648,21 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded);
mLock.lock();
} break;
+ case RELEASE_OUTPUT_SESSION_EFFECTS: {
+ ReleaseOutputSessionEffectsData *data =
+ (ReleaseOutputSessionEffectsData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing release output session effects %d %d %d",
+ data->mOutput, data->mStream, data->mSessionId);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->mAudioPolicyEffects->doReleaseOutputSessionEffects(
+ data->mOutput, data->mStream, data->mSessionId);
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -929,6 +951,23 @@ void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::releaseOutputSessionEffectsCommand(
+ audio_io_handle_t output, audio_stream_type_t stream,
+ audio_unique_id_t sessionId, int delayMs)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = RELEASE_OUTPUT_SESSION_EFFECTS;
+ ReleaseOutputSessionEffectsData *data = new ReleaseOutputSessionEffectsData();
+ data->mOutput = output;
+ data->mStream = stream;
+ data->mSessionId = sessionId;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending release output session effects (id=%d) for stream %d",
+ sessionId, stream);
+ sendCommand(command, delayMs);
+}
+
+
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 27a62f4..9b17a26 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -235,6 +235,10 @@ public:
audio_unique_id_t sessionId, bool added);
void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
audio_unique_id_t sessionId, bool added);
+ void releaseOutputSessionEffectsDelayed(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ int delayMs);
private:
AudioPolicyService() ANDROID_API;
@@ -268,7 +272,8 @@ private:
UPDATE_AUDIOPATCH_LIST,
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
- EFFECT_SESSION_UPDATE
+ EFFECT_SESSION_UPDATE,
+ RELEASE_OUTPUT_SESSION_EFFECTS,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -313,6 +318,10 @@ private:
void insertCommand_l(AudioCommand *command, int delayMs = 0);
void effectSessionUpdateCommand(audio_stream_type_t stream,
audio_unique_id_t sessionId, bool added);
+ void releaseOutputSessionEffectsCommand(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ int delayMs = 0);
private:
class AudioCommandData;
@@ -416,6 +425,13 @@ private:
bool mAdded;
};
+ class ReleaseOutputSessionEffectsData : public AudioCommandData {
+ public:
+ audio_io_handle_t mOutput;
+ audio_stream_type_t mStream;
+ audio_unique_id_t mSessionId;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands