Fix memory leak when filtering commands in insertCommand_l()
When AudioPolicyService::AudioCommandThread::insertCommand_l filters
a command from the queue, the AudioCommand* is removed from the
vector mAudioCommands by calling mAudioCommands.removeAt(). This will
destroy the pointer and compact the vector, but not delete the
AudioCommand object.
This patch adds code to delete a filtered out AudioCommand and its
data object mParam. However, mParam was void* and deleting a void
pointer is undefined behavior according to the C++
standard. Therefore, the data classes are modified to inherit
from an abstract base class with a virtual destructor.
The deletion of non-filtered commands in
AudioPolicyService::AudioCommandThread::threadLoop() was already
correct, as each case casts mParam to the proper type before
deleting.
This also fixes AOSP issue 36370.
Change-Id: I2b63838aff3608132aa496f964a929f78c4b6267
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index a37272d..6ea5324 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -678,6 +678,10 @@
if (!mAudioCommands.isEmpty()) {
release_wake_lock(mName.string());
}
+ for (size_t k=0; k < mAudioCommands.size(); k++) {
+ delete mAudioCommands[k]->mParam;
+ delete mAudioCommands[k];
+ }
mAudioCommands.clear();
delete mpToneGenerator;
}
@@ -849,7 +853,7 @@
ToneData *data = new ToneData();
data->mType = type;
data->mStream = stream;
- command->mParam = (void *)data;
+ command->mParam = data;
Mutex::Autolock _l(mLock);
insertCommand_l(command);
ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
@@ -950,7 +954,7 @@
data->mIO = output;
data->mStream = stream;
data->mSession = session;
- command->mParam = (void *)data;
+ command->mParam = data;
Mutex::Autolock _l(mLock);
insertCommand_l(command);
ALOGV("AudioCommandThread() adding stop output %d", output);
@@ -963,7 +967,7 @@
command->mCommand = RELEASE_OUTPUT;
ReleaseOutputData *data = new ReleaseOutputData();
data->mIO = output;
- command->mParam = (void *)data;
+ command->mParam = data;
Mutex::Autolock _l(mLock);
insertCommand_l(command);
ALOGV("AudioCommandThread() adding release output %d", output);
@@ -1052,6 +1056,10 @@
for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
if (mAudioCommands[k] == removedCommands[j]) {
ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+ // for commands that are not filtered,
+ // command->mParam is deleted in threadLoop
+ delete mAudioCommands[k]->mParam;
+ delete mAudioCommands[k];
mAudioCommands.removeAt(k);
break;
}