Release audio patch just after it was created in case no waiting caller
3s timeout (error -110, TIMED_OUT) might happen during audio patch
creation in AudioCommandThread. In such case the caller (e.g. binder
transaction: AudioPolicyManager::startAudioSource() ->
connectAudioSource()) gets no valid handle and quits with error, while
AudioCommandThread keeps trying to finalize patch create.
In case AudioCommandThread succeeds (after 3s timeout), the handle
becomes lost while resources allocated by audio-hal during patch create
remain busy so next tries of creating audio patches fail (error -12,
NO_MEMORY).
To prevent from audio-hal resources leakage, release the audio patch
that nobody is waiting for just after it was created.
Test: Manual
Bug: https://partnerissuetracker.corp.google.com/issues/356095582
Change-Id: I7bee96541b03299d0f8cbd9d724ae217b9a66bb3
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 8d53bd5..d529130 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1801,6 +1801,7 @@
++numTimesBecameEmpty;
}
mLastCommand = command;
+ status_t createAudioPatchStatus;
switch (command->mCommand) {
case SET_VOLUME: {
@@ -1858,10 +1859,11 @@
ALOGV("AudioCommandThread() processing create audio patch");
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
- command->mStatus = PERMISSION_DENIED;
+ createAudioPatchStatus = PERMISSION_DENIED;
} else {
ul.unlock();
- command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
+ createAudioPatchStatus = af->createAudioPatch(&data->mPatch,
+ &data->mHandle);
ul.lock();
}
} break;
@@ -2030,8 +2032,28 @@
{
audio_utils::lock_guard _l(command->mMutex);
if (command->mWaitStatus) {
+ if (command->mCommand == CREATE_AUDIO_PATCH) {
+ command->mStatus = createAudioPatchStatus;
+ }
command->mWaitStatus = false;
command->mCond.notify_one();
+ } else if (command->mCommand == CREATE_AUDIO_PATCH &&
+ command->mStatus == TIMED_OUT &&
+ createAudioPatchStatus == NO_ERROR) {
+ // Because of special handling in insertCommand_l() the CREATE_AUDIO_PATCH
+ // command wait status can be only false in case timeout (see TIMED_OUT)
+ // happened.
+ CreateAudioPatchData *createData =
+ (CreateAudioPatchData *)command->mParam.get();
+ ALOGW("AudioCommandThread() no caller awaiting for handle(%d) after \
+ processing create audio patch, going to release it",
+ createData->mHandle);
+ sp<AudioCommand> releaseCommand = new AudioCommand();
+ releaseCommand->mCommand = RELEASE_AUDIO_PATCH;
+ ReleaseAudioPatchData *releaseData = new ReleaseAudioPatchData();
+ releaseData->mHandle = createData->mHandle;
+ releaseCommand->mParam = releaseData;
+ insertCommand_l(releaseCommand, 0);
}
}
waitTime = -1;
@@ -2549,7 +2571,8 @@
// Disable wait for status if delay is not 0.
// Except for create audio patch command because the returned patch handle
- // is needed by audio policy manager
+ // is needed by audio policy manager. Audio patch created after timeout
+ // (see TIMED_OUT) will be released from threadLoop().
if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
command->mWaitStatus = false;
}