refactor mutexes for audio effects in audio flinger and audio policy
Remove effect specific mutex (mEffectLock) in AudioPolicyService: Due to
concurrent capture (among other reasons), it is necessary that the audio
policy manager state preserved by mLock includes audio effects
registration and enabling.
Moved all audio policy API calls from audio flinger out of locked regions
for audio flinger, thread and effects mutexes to avoid cross deadlocks
between audioflinger and audio policy manager:
- centralized audio policy API calls in EffectModule::updatePolicyState()
- the enabled state now reflects the state requested by the controlling
handle, not the actual effect processing state: a suspended effect is
now considered enabled.
A new audio policy manager API moveEffectsToIo() is added to atomically
handle moving effects to a new input or output without having to call
unregister > register > enable sequence.
Also fix assert in setStreamVolume to match volume group refactoring
in audio policy manager.
Bug: 128419018
Test: CTS tests for audio effects.
Test: manual tests with Duo calls, Play Music, Youtube, notifications
with and without Bluetooth and wired headset.
Change-Id: I8bd3af81026c55b6be283b3a9b41fe4998e060fd
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index bf98c60..4a8bb52 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -103,6 +103,7 @@
LIST_AUDIO_VOLUME_GROUPS,
GET_VOLUME_GROUP_FOR_ATTRIBUTES,
SET_ALLOWED_CAPTURE_POLICY,
+ MOVE_EFFECTS_TO_IO,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -550,6 +551,22 @@
return static_cast <status_t> (reply.readInt32());
}
+ status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(ids.size());
+ for (auto id : ids) {
+ data.writeInt32(id);
+ }
+ data.writeInt32(io);
+ status_t status = remote()->transact(MOVE_EFFECTS_TO_IO, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
+
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
Parcel data, reply;
@@ -1284,6 +1301,7 @@
case GET_OUTPUT_FOR_ATTR:
case ACQUIRE_SOUNDTRIGGER_SESSION:
case RELEASE_SOUNDTRIGGER_SESSION:
+ case MOVE_EFFECTS_TO_IO:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
@@ -1700,6 +1718,31 @@
return NO_ERROR;
} break;
+ case MOVE_EFFECTS_TO_IO: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ std::vector<int> ids;
+ int32_t size;
+ status_t status = data.readInt32(&size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (size > MAX_ITEMS_PER_LIST) {
+ return BAD_VALUE;
+ }
+ for (int32_t i = 0; i < size; i++) {
+ int id;
+ status = data.readInt32(&id);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ ids.push_back(id);
+ }
+
+ audio_io_handle_t io = data.readInt32();
+ reply->writeInt32(static_cast <int32_t>(moveEffectsToIo(ids, io)));
+ return NO_ERROR;
+ } break;
+
case IS_STREAM_ACTIVE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();