audiopolicy: stop output if it's still active before being released.
There's an assertion in outputDesc->removeClient assuming client
is inactive before removed, which is not always true.
Fix by stoping the output before being released.
Bug: 140221629
Test: make
Change-Id: Ifd7ee020ee4e392d80e93763e078d363a62ec8c4
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 1d9223e..1302486 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -182,6 +182,7 @@
* Active ref count of the client will be incremented/decremented through setActive API
*/
virtual void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
+ bool isClientActive(const sp<TrackClientDescriptor>& client);
bool isActive(uint32_t inPastMs) const;
bool isActive(VolumeSource volumeSource = VOLUME_SOURCE_NONE,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 25f7c27..1756021 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -123,6 +123,12 @@
client->setActive(active);
}
+bool AudioOutputDescriptor::isClientActive(const sp<TrackClientDescriptor>& client)
+{
+ return client != nullptr &&
+ std::find(begin(mActiveClients), end(mActiveClients), client) != end(mActiveClients);
+}
+
bool AudioOutputDescriptor::isActive(VolumeSource vs, uint32_t inPastMs, nsecs_t sysTime) const
{
return (vs == VOLUME_SOURCE_NONE) ?
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 7b8a2ea..cc4ec36 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1954,6 +1954,12 @@
ALOGV("releaseOutput() %d", outputDesc->mIoHandle);
+ sp<TrackClientDescriptor> client = outputDesc->getClient(portId);
+ if (outputDesc->isClientActive(client)) {
+ ALOGW("releaseOutput() inactivates portId %d in good faith", portId);
+ stopOutput(portId);
+ }
+
if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
if (outputDesc->mDirectOpenCount <= 0) {
ALOGW("releaseOutput() invalid open count %d for output %d",
@@ -1965,9 +1971,7 @@
mpClientInterface->onAudioPortListUpdate();
}
}
- // stopOutput() needs to be successfully called before releaseOutput()
- // otherwise there may be inaccurate stream reference counts.
- // This is checked in outputDesc->removeClient below.
+
outputDesc->removeClient(portId);
}