Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +64 −39 Original line number Diff line number Diff line Loading @@ -257,11 +257,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript } else { checkCloseOutputs(); } if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); updateCallRouting(newDevices); } (void)updateCallRouting(false /*fromCache*/); const DeviceVector msdOutDevices = getMsdAudioOutDevices(); for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); Loading Loading @@ -349,10 +345,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // getDeviceForStrategy() cache updateDevicesAndOutputs(); if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); updateCallRouting(newDevices); } (void)updateCallRouting(false /*fromCache*/); // Reconnect Audio Source for (const auto &strategy : mEngine->getOrderedProductStrategies()) { auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front(); Loading Loading @@ -517,23 +510,58 @@ status_t AudioPolicyManager::getHwOffloadEncodingFormatsSupportedForA2DP( return status; } uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs) DeviceVector AudioPolicyManager::selectBestRxSinkDevicesForCall(bool fromCache) { DeviceVector rxSinkdevices{}; rxSinkdevices = mEngine->getOutputDevicesForAttributes( attributes_initializer(AUDIO_USAGE_VOICE_COMMUNICATION), nullptr, fromCache); if (!rxSinkdevices.isEmpty() && mAvailableOutputDevices.contains(rxSinkdevices.itemAt(0))) { auto rxSinkDevice = rxSinkdevices.itemAt(0); auto telephonyRxModule = mHwModules.getModuleForDeviceType( AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT); // retrieve Rx Source device descriptor sp<DeviceDescriptor> rxSourceDevice = mAvailableInputDevices.getDevice( AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT); // RX Telephony and Rx sink devices are declared by Primary Audio HAL if (isPrimaryModule(telephonyRxModule) && (telephonyRxModule->getHalVersionMajor() >= 3) && telephonyRxModule->supportsPatch(rxSourceDevice, rxSinkDevice)) { ALOGW("%s() device %s using HW Bridge", __func__, rxSinkDevice->toString().c_str()); return DeviceVector(rxSinkDevice); } } // Note that despite the fact that getNewOutputDevices() is called on the primary output, // the device returned is not necessarily reachable via this output // (filter later by setOutputDevices()) return getNewOutputDevices(mPrimaryOutput, fromCache); } status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs) { if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache); return updateCallRoutingInternal(rxDevices, delayMs, waitMs); } return INVALID_OPERATION; } status_t AudioPolicyManager::updateCallRoutingInternal( const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs) { bool createTxPatch = false; bool createRxPatch = false; uint32_t muteWaitMs = 0; if(!hasPrimaryOutput() || mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) { return muteWaitMs; return INVALID_OPERATION; } ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device"); ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__); audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION }; auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr); ALOG_ASSERT(txSourceDevice != 0, "updateCallRouting() input selected device not available"); ALOG_ASSERT(txSourceDevice != 0, "%s() input selected device not available", __func__); ALOGV("updateCallRouting device rxDevice %s txDevice %s", ALOGV("%s device rxDevice %s txDevice %s", __func__, rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str()); disconnectTelephonyRxAudioSource(); Loading Loading @@ -562,8 +590,8 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui (telephonyRxModule->getHalVersionMajor() >= 3)) { if (rxSourceDevice == 0 || txSinkDevice == 0) { // RX / TX Telephony device(s) is(are) not currently available ALOGE("updateCallRouting() no telephony Tx and/or RX device"); return muteWaitMs; ALOGE("%s() no telephony Tx and/or RX device", __func__); return INVALID_OPERATION; } // createAudioPatchInternal now supports both HW / SW bridging createRxPatch = true; Loading Loading @@ -601,8 +629,10 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui } mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs); } return muteWaitMs; if (waitMs != nullptr) { *waitMs = muteWaitMs; } return NO_ERROR; } sp<AudioPatch> AudioPolicyManager::createTelephonyPatch( Loading Loading @@ -720,25 +750,22 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) } if (hasPrimaryOutput()) { // Note that despite the fact that getNewOutputDevices() is called on the primary output, // the device returned is not necessarily reachable via this output if (state == AUDIO_MODE_IN_CALL) { (void)updateCallRouting(false /*fromCache*/, delayMs); } else { DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && rxDevices.isEmpty()) { rxDevices = mPrimaryOutput->devices(); } if (state == AUDIO_MODE_IN_CALL) { updateCallRouting(rxDevices, delayMs); } else if (oldState == AUDIO_MODE_IN_CALL) { if (oldState == AUDIO_MODE_IN_CALL) { disconnectTelephonyRxAudioSource(); if (mCallTxPatch != 0) { releaseAudioPatchInternal(mCallTxPatch->getHandle()); mCallTxPatch.clear(); } setOutputDevices(mPrimaryOutput, rxDevices, force, 0); } else { } setOutputDevices(mPrimaryOutput, rxDevices, force, 0); } } Loading Loading @@ -3236,9 +3263,7 @@ status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strate void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs) { uint32_t waitMs = 0; if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/); waitMs = updateCallRouting(newDevices, delayMs); if (updateCallRouting(true /*fromCache*/, delayMs, &waitMs) == NO_ERROR) { // Only apply special touch sound delay once delayMs = 0; } Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +14 −1 Original line number Diff line number Diff line Loading @@ -729,9 +729,22 @@ protected: String8(devices.itemAt(0)->address().c_str()) : String8(""); } uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0); status_t updateCallRouting( bool fromCache, uint32_t delayMs = 0, uint32_t *waitMs = nullptr); status_t updateCallRoutingInternal( const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs); sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device, uint32_t delayMs); /** * @brief selectBestRxSinkDevicesForCall: if the primary module host both Telephony Rx/Tx * devices, and it declares also supporting a HW bridge between the Telephony Rx and the * given sink device for Voice Call audio attributes, select this device in prio. * Otherwise, getNewOutputDevices() is called on the primary output to select sink device. * @param fromCache true to prevent engine reconsidering all product strategies and retrieve * from engine cache. * @return vector of devices, empty if none is found. */ DeviceVector selectBestRxSinkDevicesForCall(bool fromCache); bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const; status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc, Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +64 −39 Original line number Diff line number Diff line Loading @@ -257,11 +257,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript } else { checkCloseOutputs(); } if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); updateCallRouting(newDevices); } (void)updateCallRouting(false /*fromCache*/); const DeviceVector msdOutDevices = getMsdAudioOutDevices(); for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); Loading Loading @@ -349,10 +345,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // getDeviceForStrategy() cache updateDevicesAndOutputs(); if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); updateCallRouting(newDevices); } (void)updateCallRouting(false /*fromCache*/); // Reconnect Audio Source for (const auto &strategy : mEngine->getOrderedProductStrategies()) { auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front(); Loading Loading @@ -517,23 +510,58 @@ status_t AudioPolicyManager::getHwOffloadEncodingFormatsSupportedForA2DP( return status; } uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs) DeviceVector AudioPolicyManager::selectBestRxSinkDevicesForCall(bool fromCache) { DeviceVector rxSinkdevices{}; rxSinkdevices = mEngine->getOutputDevicesForAttributes( attributes_initializer(AUDIO_USAGE_VOICE_COMMUNICATION), nullptr, fromCache); if (!rxSinkdevices.isEmpty() && mAvailableOutputDevices.contains(rxSinkdevices.itemAt(0))) { auto rxSinkDevice = rxSinkdevices.itemAt(0); auto telephonyRxModule = mHwModules.getModuleForDeviceType( AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT); // retrieve Rx Source device descriptor sp<DeviceDescriptor> rxSourceDevice = mAvailableInputDevices.getDevice( AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT); // RX Telephony and Rx sink devices are declared by Primary Audio HAL if (isPrimaryModule(telephonyRxModule) && (telephonyRxModule->getHalVersionMajor() >= 3) && telephonyRxModule->supportsPatch(rxSourceDevice, rxSinkDevice)) { ALOGW("%s() device %s using HW Bridge", __func__, rxSinkDevice->toString().c_str()); return DeviceVector(rxSinkDevice); } } // Note that despite the fact that getNewOutputDevices() is called on the primary output, // the device returned is not necessarily reachable via this output // (filter later by setOutputDevices()) return getNewOutputDevices(mPrimaryOutput, fromCache); } status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs) { if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache); return updateCallRoutingInternal(rxDevices, delayMs, waitMs); } return INVALID_OPERATION; } status_t AudioPolicyManager::updateCallRoutingInternal( const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs) { bool createTxPatch = false; bool createRxPatch = false; uint32_t muteWaitMs = 0; if(!hasPrimaryOutput() || mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) { return muteWaitMs; return INVALID_OPERATION; } ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device"); ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__); audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION }; auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr); ALOG_ASSERT(txSourceDevice != 0, "updateCallRouting() input selected device not available"); ALOG_ASSERT(txSourceDevice != 0, "%s() input selected device not available", __func__); ALOGV("updateCallRouting device rxDevice %s txDevice %s", ALOGV("%s device rxDevice %s txDevice %s", __func__, rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str()); disconnectTelephonyRxAudioSource(); Loading Loading @@ -562,8 +590,8 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui (telephonyRxModule->getHalVersionMajor() >= 3)) { if (rxSourceDevice == 0 || txSinkDevice == 0) { // RX / TX Telephony device(s) is(are) not currently available ALOGE("updateCallRouting() no telephony Tx and/or RX device"); return muteWaitMs; ALOGE("%s() no telephony Tx and/or RX device", __func__); return INVALID_OPERATION; } // createAudioPatchInternal now supports both HW / SW bridging createRxPatch = true; Loading Loading @@ -601,8 +629,10 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui } mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs); } return muteWaitMs; if (waitMs != nullptr) { *waitMs = muteWaitMs; } return NO_ERROR; } sp<AudioPatch> AudioPolicyManager::createTelephonyPatch( Loading Loading @@ -720,25 +750,22 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) } if (hasPrimaryOutput()) { // Note that despite the fact that getNewOutputDevices() is called on the primary output, // the device returned is not necessarily reachable via this output if (state == AUDIO_MODE_IN_CALL) { (void)updateCallRouting(false /*fromCache*/, delayMs); } else { DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && rxDevices.isEmpty()) { rxDevices = mPrimaryOutput->devices(); } if (state == AUDIO_MODE_IN_CALL) { updateCallRouting(rxDevices, delayMs); } else if (oldState == AUDIO_MODE_IN_CALL) { if (oldState == AUDIO_MODE_IN_CALL) { disconnectTelephonyRxAudioSource(); if (mCallTxPatch != 0) { releaseAudioPatchInternal(mCallTxPatch->getHandle()); mCallTxPatch.clear(); } setOutputDevices(mPrimaryOutput, rxDevices, force, 0); } else { } setOutputDevices(mPrimaryOutput, rxDevices, force, 0); } } Loading Loading @@ -3236,9 +3263,7 @@ status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strate void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs) { uint32_t waitMs = 0; if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/); waitMs = updateCallRouting(newDevices, delayMs); if (updateCallRouting(true /*fromCache*/, delayMs, &waitMs) == NO_ERROR) { // Only apply special touch sound delay once delayMs = 0; } Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +14 −1 Original line number Diff line number Diff line Loading @@ -729,9 +729,22 @@ protected: String8(devices.itemAt(0)->address().c_str()) : String8(""); } uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0); status_t updateCallRouting( bool fromCache, uint32_t delayMs = 0, uint32_t *waitMs = nullptr); status_t updateCallRoutingInternal( const DeviceVector &rxDevices, uint32_t delayMs, uint32_t *waitMs); sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device, uint32_t delayMs); /** * @brief selectBestRxSinkDevicesForCall: if the primary module host both Telephony Rx/Tx * devices, and it declares also supporting a HW bridge between the Telephony Rx and the * given sink device for Voice Call audio attributes, select this device in prio. * Otherwise, getNewOutputDevices() is called on the primary output to select sink device. * @param fromCache true to prevent engine reconsidering all product strategies and retrieve * from engine cache. * @return vector of devices, empty if none is found. */ DeviceVector selectBestRxSinkDevicesForCall(bool fromCache); bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const; status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc, Loading