diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h index 6e2963245c..1596ff77e7 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h @@ -41,11 +41,24 @@ sp findPreferredDevice( IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices) { auto activeClients = desc->clientsList(true /*activeOnly*/); - auto activeClientsWithRoute = - desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/); active = activeClients.size() > 0; - if (active && activeClients.size() == activeClientsWithRoute.size()) { - return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId()); + + if (active) { + // On MMAP IOs, the preferred device is selected by the first client (virtual client + // created when the mmap stream is opened). This client is never active. + // On non MMAP IOs, the preferred device is honored only if all active clients have + // a preferred device in which case the first client drives the selection. + if (desc->getPolicyAudioPort()->isMmap()) { + // The client list is never empty on a MMAP IO + return devices.getDeviceFromId( + desc->clientsList(false /*activeOnly*/)[0]->preferredDeviceId()); + } else { + auto activeClientsWithRoute = + desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/); + if (activeClients.size() == activeClientsWithRoute.size()) { + return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId()); + } + } } return nullptr; } diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h index 99df3c06cd..d2f629734a 100644 --- a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h @@ -107,6 +107,15 @@ public: (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)); } + inline bool isMmap() const + { + return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) + && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) && + ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0)) + || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) && + ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0))); + } + void addRoute(const sp &route) { mRoutes.add(route); } const AudioRouteVector &getRoutes() const { return mRoutes; } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index bdd2427986..5aa62716c7 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -2405,9 +2405,7 @@ void AudioPolicyManager::checkCloseInputs() { for (size_t i = 0; i < mInputs.size(); i++) { const sp input = mInputs.valueAt(i); if (input->clientsList().size() == 0 - || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices()) - || (input->getPolicyAudioPort()->getFlags() - & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) { + || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) { inputsToClose.push_back(mInputs.keyAt(i)); } else { bool close = false;