From 89a8ea964d569f410695fb7cef6f3e854aafcbb8 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 29 Sep 2023 17:02:12 -0700 Subject: [PATCH] audio: Fix notification of streams of the device change Replace the incorrect logic which was considering each port individually with the correct logic which considers a connection of a mix port to device ports. Bug: 302573756 Test: atest VtsHalAudioCoreTargetTest Change-Id: I7df6e32315945897d88923ea4d9744e590e85dfd --- audio/aidl/default/Module.cpp | 65 ++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp index 0d4e21f311..663bfa4f76 100644 --- a/audio/aidl/default/Module.cpp +++ b/audio/aidl/default/Module.cpp @@ -340,21 +340,43 @@ void Module::registerPatch(const AudioPatch& patch) { ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch) { - // Streams from the old patch need to be disconnected, streams from the new - // patch need to be connected. If the stream belongs to both patches, no need - // to update it. + // Notify streams about the new set of devices they are connected to. auto maybeFailure = ndk::ScopedAStatus::ok(); - std::set idsToDisconnect, idsToConnect, idsToDisconnectOnFailure; - idsToDisconnect.insert(oldPatch.sourcePortConfigIds.begin(), - oldPatch.sourcePortConfigIds.end()); - idsToDisconnect.insert(oldPatch.sinkPortConfigIds.begin(), oldPatch.sinkPortConfigIds.end()); - idsToConnect.insert(newPatch.sourcePortConfigIds.begin(), newPatch.sourcePortConfigIds.end()); - idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end()); - std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) { - if (idsToConnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) { - if (auto status = mStreams.setStreamConnectedDevices(portConfigId, {}); status.isOk()) { + using Connections = + std::map>; + Connections oldConnections, newConnections; + auto fillConnectionsHelper = [&](Connections& connections, + const std::vector& mixPortCfgIds, + const std::vector& devicePortCfgIds) { + for (int32_t mixPortCfgId : mixPortCfgIds) { + connections[mixPortCfgId].insert(devicePortCfgIds.begin(), devicePortCfgIds.end()); + } + }; + auto fillConnections = [&](Connections& connections, const AudioPatch& patch) { + if (std::find_if(patch.sourcePortConfigIds.begin(), patch.sourcePortConfigIds.end(), + [&](int32_t portConfigId) { return mStreams.count(portConfigId) > 0; }) != + patch.sourcePortConfigIds.end()) { + // Sources are mix ports. + fillConnectionsHelper(connections, patch.sourcePortConfigIds, patch.sinkPortConfigIds); + } else if (std::find_if(patch.sinkPortConfigIds.begin(), patch.sinkPortConfigIds.end(), + [&](int32_t portConfigId) { + return mStreams.count(portConfigId) > 0; + }) != patch.sinkPortConfigIds.end()) { + // Sources are device ports. + fillConnectionsHelper(connections, patch.sinkPortConfigIds, patch.sourcePortConfigIds); + } // Otherwise, there are no streams to notify. + }; + fillConnections(oldConnections, oldPatch); + fillConnections(newConnections, newPatch); + + std::for_each(oldConnections.begin(), oldConnections.end(), [&](const auto& connectionPair) { + const int32_t mixPortConfigId = connectionPair.first; + if (auto it = newConnections.find(mixPortConfigId); + it == newConnections.end() || it->second != connectionPair.second) { + if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, {}); + status.isOk()) { LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id " - << portConfigId << " has been disconnected"; + << mixPortConfigId << " has been disconnected"; } else { // Disconnection is tricky to roll back, just register a failure. maybeFailure = std::move(status); @@ -362,23 +384,26 @@ ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatc } }); if (!maybeFailure.isOk()) return maybeFailure; - std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) { - if (idsToDisconnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) { - const auto connectedDevices = findConnectedDevices(portConfigId); + std::set idsToDisconnectOnFailure; + std::for_each(newConnections.begin(), newConnections.end(), [&](const auto& connectionPair) { + const int32_t mixPortConfigId = connectionPair.first; + if (auto it = oldConnections.find(mixPortConfigId); + it == oldConnections.end() || it->second != connectionPair.second) { + const auto connectedDevices = findConnectedDevices(mixPortConfigId); if (connectedDevices.empty()) { // This is important as workers use the vector size to derive the connection status. LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port " "config id " - << portConfigId; + << mixPortConfigId; } - if (auto status = mStreams.setStreamConnectedDevices(portConfigId, connectedDevices); + if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, connectedDevices); status.isOk()) { LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id " - << portConfigId << " has been connected to: " + << mixPortConfigId << " has been connected to: " << ::android::internal::ToString(connectedDevices); } else { maybeFailure = std::move(status); - idsToDisconnectOnFailure.insert(portConfigId); + idsToDisconnectOnFailure.insert(mixPortConfigId); } } });