Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +86 −55 Original line number Diff line number Diff line Loading @@ -287,9 +287,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output); // close unused outputs after device disconnection or direct outputs that have // been opened by checkOutputsForDevice() to query dynamic parameters // "outputs" vector never contains duplicated outputs if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && (desc->mDirectOpenCount == 0))) { (desc->mDirectOpenCount == 0)) || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) && !isOutputOnlyAvailableRouteToSomeDevice(desc))) { clearAudioSourcesForOutput(output); closeOutput(output); } Loading Loading @@ -5361,6 +5364,29 @@ void AudioPolicyManager::checkVirtualizerClientRoutes() { } } bool AudioPolicyManager::isOutputOnlyAvailableRouteToSomeDevice( const sp<SwAudioOutputDescriptor>& outputDesc) { if (outputDesc->isDuplicated()) { return false; } DeviceVector devices = outputDesc->supportedDevices(); for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (desc == outputDesc || desc->isDuplicated()) { continue; } DeviceVector sharedDevices = desc->filterSupportedDevices(devices); if (!sharedDevices.isEmpty() && (desc->devicesSupportEncodedFormats(sharedDevices.types()) == outputDesc->devicesSupportEncodedFormats(sharedDevices.types()))) { return false; } } return true; } status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mixerConfig, const audio_attributes_t *attr, audio_io_handle_t *output) { Loading @@ -5376,80 +5402,67 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix } if (!canBeSpatializedInt( attr, configPtr, devicesTypeAddress)) { ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__); ALOGV("%s provided attributes or mixer config cannot be spatialized", __func__); return BAD_VALUE; } sp<IOProfile> profile = getSpatializerOutputProfile(configPtr, devicesTypeAddress); if (profile == nullptr) { ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__); ALOGV("%s no suitable output profile for provided attributes or mixer config", __func__); return BAD_VALUE; } if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile && configPtr != nullptr && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) { *output = mSpatializerOutput->mIoHandle; ALOGV("%s returns current spatializer output %d", __func__, *output); return NO_ERROR; } mSpatializerOutput.clear(); std::vector<sp<SwAudioOutputDescriptor>> spatializerOutputs; for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (!desc->isDuplicated() && desc->mProfile == profile) { ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle); mSpatializerOutput = desc; break; if (!desc->isDuplicated() && (desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) { spatializerOutputs.push_back(desc); ALOGV("%s adding opened spatializer Output %d", __func__, desc->mIoHandle); } } if (mSpatializerOutput == nullptr) { ALOGW("%s no opened spatializer output for profile %s", __func__, profile->getName().c_str()); return BAD_VALUE; mSpatializerOutput.clear(); bool outputsChanged = false; for (const auto& desc : spatializerOutputs) { if (desc->mProfile == profile && (configPtr == nullptr || configPtr->channel_mask == desc->mMixerChannelMask)) { mSpatializerOutput = desc; ALOGV("%s reusing current spatializer output %d", __func__, desc->mIoHandle); } else { ALOGV("%s closing spatializerOutput output %d to match channel mask %#x" " and devices %s", __func__, desc->mIoHandle, configPtr != nullptr ? configPtr->channel_mask : 0, devices.toString().c_str()); closeOutput(desc->mIoHandle); outputsChanged = true; } } if (configPtr != nullptr && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) { audio_config_base_t savedMixerConfig = { .sample_rate = mSpatializerOutput->getSamplingRate(), .format = mSpatializerOutput->getFormat(), .channel_mask = mSpatializerOutput->mMixerChannelMask, }; DeviceVector savedDevices = mSpatializerOutput->devices(); ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)", __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask); closeOutput(mSpatializerOutput->mIoHandle); //from now on mSpatializerOutput is null if (mSpatializerOutput == nullptr) { sp<SwAudioOutputDescriptor> desc = openOutputWithProfileAndDevice(profile, devices, mixerConfig); if (desc == nullptr) { // re open the spatializer output with previous channel mask desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig); if (desc == nullptr) { ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__); } else { if (desc != nullptr) { mSpatializerOutput = desc; outputsChanged = true; } mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); *output = AUDIO_IO_HANDLE_NONE; ALOGW("%s could not open spatializer output with requested config", __func__); return BAD_VALUE; } mSpatializerOutput = desc; checkVirtualizerClientRoutes(); if (outputsChanged) { mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); } checkVirtualizerClientRoutes(); if (mSpatializerOutput == nullptr) { ALOGV("%s could not open spatializer output with requested config", __func__); return BAD_VALUE; } *output = mSpatializerOutput->mIoHandle; ALOGV("%s returns new spatializer output %d", __func__, *output); return NO_ERROR; ALOGV("%s returning new spatializer output %d", __func__, *output); return OK; } status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) { Loading @@ -5460,9 +5473,12 @@ status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) return BAD_VALUE; } mSpatializerOutput.clear(); if (!isOutputOnlyAvailableRouteToSomeDevice(mSpatializerOutput)) { ALOGV("%s closing spatializer output %d", __func__, mSpatializerOutput->mIoHandle); closeOutput(mSpatializerOutput->mIoHandle); //from now on mSpatializerOutput is null checkVirtualizerClientRoutes(); } return NO_ERROR; } Loading Loading @@ -5739,6 +5755,21 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices) inputDesc->close(); } } // Check if spatializer outputs can be closed until used. // mOutputs vector never contains duplicated outputs at this point. std::vector<audio_io_handle_t> outputsClosed; for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0 && !isOutputOnlyAvailableRouteToSomeDevice(desc)) { outputsClosed.push_back(desc->mIoHandle); desc->close(); } } for (auto output : outputsClosed) { removeOutput(output); } } void AudioPolicyManager::addOutput(audio_io_handle_t output, Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +10 −0 Original line number Diff line number Diff line Loading @@ -1096,6 +1096,16 @@ private: void checkVirtualizerClientRoutes(); /** * @brief Returns true if at least one device can only be reached via the output passed * as argument. Always returns false for duplicated outputs. * This can be used to decide if an output can be closed without forbidding * playback to any given device. * @param outputDesc the output to consider * @return true if at least one device can only be reached via the output. */ bool isOutputOnlyAvailableRouteToSomeDevice(const sp<SwAudioOutputDescriptor>& outputDesc); /** * @brief getInputForDevice selects an input handle for a given input device and * requester context Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +86 −55 Original line number Diff line number Diff line Loading @@ -287,9 +287,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output); // close unused outputs after device disconnection or direct outputs that have // been opened by checkOutputsForDevice() to query dynamic parameters // "outputs" vector never contains duplicated outputs if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && (desc->mDirectOpenCount == 0))) { (desc->mDirectOpenCount == 0)) || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) && !isOutputOnlyAvailableRouteToSomeDevice(desc))) { clearAudioSourcesForOutput(output); closeOutput(output); } Loading Loading @@ -5361,6 +5364,29 @@ void AudioPolicyManager::checkVirtualizerClientRoutes() { } } bool AudioPolicyManager::isOutputOnlyAvailableRouteToSomeDevice( const sp<SwAudioOutputDescriptor>& outputDesc) { if (outputDesc->isDuplicated()) { return false; } DeviceVector devices = outputDesc->supportedDevices(); for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (desc == outputDesc || desc->isDuplicated()) { continue; } DeviceVector sharedDevices = desc->filterSupportedDevices(devices); if (!sharedDevices.isEmpty() && (desc->devicesSupportEncodedFormats(sharedDevices.types()) == outputDesc->devicesSupportEncodedFormats(sharedDevices.types()))) { return false; } } return true; } status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mixerConfig, const audio_attributes_t *attr, audio_io_handle_t *output) { Loading @@ -5376,80 +5402,67 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix } if (!canBeSpatializedInt( attr, configPtr, devicesTypeAddress)) { ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__); ALOGV("%s provided attributes or mixer config cannot be spatialized", __func__); return BAD_VALUE; } sp<IOProfile> profile = getSpatializerOutputProfile(configPtr, devicesTypeAddress); if (profile == nullptr) { ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__); ALOGV("%s no suitable output profile for provided attributes or mixer config", __func__); return BAD_VALUE; } if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile && configPtr != nullptr && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) { *output = mSpatializerOutput->mIoHandle; ALOGV("%s returns current spatializer output %d", __func__, *output); return NO_ERROR; } mSpatializerOutput.clear(); std::vector<sp<SwAudioOutputDescriptor>> spatializerOutputs; for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if (!desc->isDuplicated() && desc->mProfile == profile) { ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle); mSpatializerOutput = desc; break; if (!desc->isDuplicated() && (desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) { spatializerOutputs.push_back(desc); ALOGV("%s adding opened spatializer Output %d", __func__, desc->mIoHandle); } } if (mSpatializerOutput == nullptr) { ALOGW("%s no opened spatializer output for profile %s", __func__, profile->getName().c_str()); return BAD_VALUE; mSpatializerOutput.clear(); bool outputsChanged = false; for (const auto& desc : spatializerOutputs) { if (desc->mProfile == profile && (configPtr == nullptr || configPtr->channel_mask == desc->mMixerChannelMask)) { mSpatializerOutput = desc; ALOGV("%s reusing current spatializer output %d", __func__, desc->mIoHandle); } else { ALOGV("%s closing spatializerOutput output %d to match channel mask %#x" " and devices %s", __func__, desc->mIoHandle, configPtr != nullptr ? configPtr->channel_mask : 0, devices.toString().c_str()); closeOutput(desc->mIoHandle); outputsChanged = true; } } if (configPtr != nullptr && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) { audio_config_base_t savedMixerConfig = { .sample_rate = mSpatializerOutput->getSamplingRate(), .format = mSpatializerOutput->getFormat(), .channel_mask = mSpatializerOutput->mMixerChannelMask, }; DeviceVector savedDevices = mSpatializerOutput->devices(); ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)", __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask); closeOutput(mSpatializerOutput->mIoHandle); //from now on mSpatializerOutput is null if (mSpatializerOutput == nullptr) { sp<SwAudioOutputDescriptor> desc = openOutputWithProfileAndDevice(profile, devices, mixerConfig); if (desc == nullptr) { // re open the spatializer output with previous channel mask desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig); if (desc == nullptr) { ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__); } else { if (desc != nullptr) { mSpatializerOutput = desc; outputsChanged = true; } mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); *output = AUDIO_IO_HANDLE_NONE; ALOGW("%s could not open spatializer output with requested config", __func__); return BAD_VALUE; } mSpatializerOutput = desc; checkVirtualizerClientRoutes(); if (outputsChanged) { mPreviousOutputs = mOutputs; mpClientInterface->onAudioPortListUpdate(); } checkVirtualizerClientRoutes(); if (mSpatializerOutput == nullptr) { ALOGV("%s could not open spatializer output with requested config", __func__); return BAD_VALUE; } *output = mSpatializerOutput->mIoHandle; ALOGV("%s returns new spatializer output %d", __func__, *output); return NO_ERROR; ALOGV("%s returning new spatializer output %d", __func__, *output); return OK; } status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) { Loading @@ -5460,9 +5473,12 @@ status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) return BAD_VALUE; } mSpatializerOutput.clear(); if (!isOutputOnlyAvailableRouteToSomeDevice(mSpatializerOutput)) { ALOGV("%s closing spatializer output %d", __func__, mSpatializerOutput->mIoHandle); closeOutput(mSpatializerOutput->mIoHandle); //from now on mSpatializerOutput is null checkVirtualizerClientRoutes(); } return NO_ERROR; } Loading Loading @@ -5739,6 +5755,21 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices) inputDesc->close(); } } // Check if spatializer outputs can be closed until used. // mOutputs vector never contains duplicated outputs at this point. std::vector<audio_io_handle_t> outputsClosed; for (size_t i = 0; i < mOutputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i); if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0 && !isOutputOnlyAvailableRouteToSomeDevice(desc)) { outputsClosed.push_back(desc->mIoHandle); desc->close(); } } for (auto output : outputsClosed) { removeOutput(output); } } void AudioPolicyManager::addOutput(audio_io_handle_t output, Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +10 −0 Original line number Diff line number Diff line Loading @@ -1096,6 +1096,16 @@ private: void checkVirtualizerClientRoutes(); /** * @brief Returns true if at least one device can only be reached via the output passed * as argument. Always returns false for duplicated outputs. * This can be used to decide if an output can be closed without forbidding * playback to any given device. * @param outputDesc the output to consider * @return true if at least one device can only be reached via the output. */ bool isOutputOnlyAvailableRouteToSomeDevice(const sp<SwAudioOutputDescriptor>& outputDesc); /** * @brief getInputForDevice selects an input handle for a given input device and * requester context Loading