Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +101 −52 Original line number Diff line number Diff line Loading @@ -780,17 +780,39 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream) return output; } status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, status_t AudioPolicyManager::getAudioAttributes(audio_attributes_t *dstAttr, const audio_attributes_t *srcAttr, audio_stream_type_t srcStream) { if (srcAttr != NULL) { if (!isValidAttributes(srcAttr)) { ALOGE("%s invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", __func__, srcAttr->usage, srcAttr->content_type, srcAttr->flags, srcAttr->tags); return BAD_VALUE; } *dstAttr = *srcAttr; } else { if (srcStream < AUDIO_STREAM_MIN || srcStream >= AUDIO_STREAM_PUBLIC_CNT) { ALOGE("%s: invalid stream type", __func__); return BAD_VALUE; } stream_type_to_audio_attributes(srcStream, dstAttr); } return NO_ERROR; } status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr, audio_io_handle_t *output, audio_session_t session, const audio_attributes_t *attr, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId, audio_port_handle_t *portId) audio_port_handle_t *selectedDeviceId) { audio_attributes_t attributes; DeviceVector outputDevices; routing_strategy strategy; audio_devices_t device; Loading @@ -798,35 +820,20 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, audio_devices_t msdDevice = getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD); // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } if (attr != NULL) { if (!isValidAttributes(attr)) { ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", attr->usage, attr->content_type, attr->flags, attr->tags); return BAD_VALUE; } attributes = *attr; } else { if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) { ALOGE("getOutputForAttr(): invalid stream type"); return BAD_VALUE; } stream_type_to_audio_attributes(*stream, &attributes); status_t status = getAudioAttributes(resultAttr, attr, *stream); if (status != NO_ERROR) { return status; } ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x" ALOGV("%s usage=%d, content=%d, tag=%s flags=%08x" " session %d selectedDeviceId %d", attributes.usage, attributes.content_type, attributes.tags, attributes.flags, __func__, resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags, session, requestedDeviceId); *stream = streamTypefromAttributesInt(&attributes); *stream = streamTypefromAttributesInt(resultAttr); strategy = getStrategyForAttr(&attributes); strategy = getStrategyForAttr(resultAttr); // First check for explicit routing (eg. setPreferredDevice) if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) { Loading @@ -836,30 +843,30 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } else { // If no explict route, is there a matching dynamic policy that applies? sp<SwAudioOutputDescriptor> desc; if (mPolicyMixes.getOutputForAttr(attributes, uid, desc) == NO_ERROR) { if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, desc) == NO_ERROR) { ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr"); if (!audio_has_proportional_frames(config->format)) { return BAD_VALUE; } *stream = streamTypefromAttributesInt(&attributes); *stream = streamTypefromAttributesInt(resultAttr); *output = desc->mIoHandle; AudioMix *mix = desc->mPolicyMix; sp<DeviceDescriptor> deviceDesc = mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress); *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE; ALOGV("getOutputForAttr() returns output %d", *output); goto exit; ALOGV("%s returns output %d", __func__, *output); return NO_ERROR; } // Virtual sources must always be dynamicaly or explicitly routed if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE"); if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__); return BAD_VALUE; } device = getDeviceForStrategy(strategy, false /*fromCache*/); } if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC); } Loading @@ -869,7 +876,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, // to getOutputForDevice. // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side. if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX && (*stream == AUDIO_STREAM_MUSIC || attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) && (*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) && audio_is_linear_pcm(config->format) && isInCall()) { if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) { Loading @@ -880,9 +887,9 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } } ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, " ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, " "flags %#x", device, config->sample_rate, config->format, config->channel_mask, *flags); __func__, device, config->sample_rate, config->format, config->channel_mask, *flags); *output = AUDIO_IO_HANDLE_NONE; if (msdDevice != AUDIO_DEVICE_NONE) { Loading @@ -906,22 +913,48 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId() : AUDIO_PORT_HANDLE_NONE; exit: ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId); return NO_ERROR; } status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, audio_io_handle_t *output, audio_session_t session, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId, audio_port_handle_t *portId) { // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } const audio_port_handle_t requestedDeviceId = *selectedDeviceId; audio_attributes_t resultAttr; status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid, config, flags, selectedDeviceId); if (status != NO_ERROR) { return status; } audio_config_base_t clientConfig = {.sample_rate = config->sample_rate, .format = config->format, .channel_mask = config->channel_mask }; *portId = AudioPort::getNextUniqueId(); sp<TrackClientDescriptor> clientDesc = new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig, new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig, requestedDeviceId, *stream, getStrategyForAttr(&attributes), getStrategyForAttr(&resultAttr), *flags); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); outputDesc->addClient(clientDesc); ALOGV(" getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d", *output, *selectedDeviceId, *portId); ALOGV("%s returns output %d selectedDeviceId %d for port ID %d", __func__, *output, requestedDeviceId, *portId); return NO_ERROR; } Loading Loading @@ -3400,11 +3433,20 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor> srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 && srcDeviceDesc->getAudioPort()->mGains.size() > 0) { ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__); // TODO: may explicitly specify whether we should use HW or SW patch // create patch between src device and output device // create Hwoutput and add to mHwOutputs } else { SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs); audio_io_handle_t output = selectOutput(outputs); audio_attributes_t resultAttr; audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = sourceDesc->config().sample_rate; config.channel_mask = sourceDesc->config().channel_mask; config.format = sourceDesc->config().format; audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId); if (output == AUDIO_IO_HANDLE_NONE) { ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice); return INVALID_OPERATION; Loading Loading @@ -3437,6 +3479,13 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor> __FUNCTION__, status); return INVALID_OPERATION; } if (outputDesc->getClient(sourceDesc->portId()) != nullptr) { ALOGW("%s source portId has already been attached to outputDesc", __func__); return INVALID_OPERATION; } outputDesc->addClient(sourceDesc); uint32_t delayMs = 0; status = startSource(outputDesc, sourceDesc, &delayMs); Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +15 −0 Original line number Diff line number Diff line Loading @@ -661,6 +661,21 @@ private: const String8& address /*in*/, SortedVector<audio_io_handle_t>& outputs /*out*/); uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; } // internal method, get audio_attributes_t from either a source audio_attributes_t // or audio_stream_type_t, respectively. status_t getAudioAttributes(audio_attributes_t *dstAttr, const audio_attributes_t *srcAttr, audio_stream_type_t srcStream); // internal method, called by getOutputForAttr() and connectAudioSource. status_t getOutputForAttrInt(audio_attributes_t *resultAttr, audio_io_handle_t *output, audio_session_t session, const audio_attributes_t *attr, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId); // internal method to return the output handle for the given device and format audio_io_handle_t getOutputForDevice( audio_devices_t device, Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +101 −52 Original line number Diff line number Diff line Loading @@ -780,17 +780,39 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream) return output; } status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, status_t AudioPolicyManager::getAudioAttributes(audio_attributes_t *dstAttr, const audio_attributes_t *srcAttr, audio_stream_type_t srcStream) { if (srcAttr != NULL) { if (!isValidAttributes(srcAttr)) { ALOGE("%s invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", __func__, srcAttr->usage, srcAttr->content_type, srcAttr->flags, srcAttr->tags); return BAD_VALUE; } *dstAttr = *srcAttr; } else { if (srcStream < AUDIO_STREAM_MIN || srcStream >= AUDIO_STREAM_PUBLIC_CNT) { ALOGE("%s: invalid stream type", __func__); return BAD_VALUE; } stream_type_to_audio_attributes(srcStream, dstAttr); } return NO_ERROR; } status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr, audio_io_handle_t *output, audio_session_t session, const audio_attributes_t *attr, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId, audio_port_handle_t *portId) audio_port_handle_t *selectedDeviceId) { audio_attributes_t attributes; DeviceVector outputDevices; routing_strategy strategy; audio_devices_t device; Loading @@ -798,35 +820,20 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, audio_devices_t msdDevice = getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD); // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } if (attr != NULL) { if (!isValidAttributes(attr)) { ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", attr->usage, attr->content_type, attr->flags, attr->tags); return BAD_VALUE; } attributes = *attr; } else { if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) { ALOGE("getOutputForAttr(): invalid stream type"); return BAD_VALUE; } stream_type_to_audio_attributes(*stream, &attributes); status_t status = getAudioAttributes(resultAttr, attr, *stream); if (status != NO_ERROR) { return status; } ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x" ALOGV("%s usage=%d, content=%d, tag=%s flags=%08x" " session %d selectedDeviceId %d", attributes.usage, attributes.content_type, attributes.tags, attributes.flags, __func__, resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags, session, requestedDeviceId); *stream = streamTypefromAttributesInt(&attributes); *stream = streamTypefromAttributesInt(resultAttr); strategy = getStrategyForAttr(&attributes); strategy = getStrategyForAttr(resultAttr); // First check for explicit routing (eg. setPreferredDevice) if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) { Loading @@ -836,30 +843,30 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } else { // If no explict route, is there a matching dynamic policy that applies? sp<SwAudioOutputDescriptor> desc; if (mPolicyMixes.getOutputForAttr(attributes, uid, desc) == NO_ERROR) { if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, desc) == NO_ERROR) { ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr"); if (!audio_has_proportional_frames(config->format)) { return BAD_VALUE; } *stream = streamTypefromAttributesInt(&attributes); *stream = streamTypefromAttributesInt(resultAttr); *output = desc->mIoHandle; AudioMix *mix = desc->mPolicyMix; sp<DeviceDescriptor> deviceDesc = mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress); *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE; ALOGV("getOutputForAttr() returns output %d", *output); goto exit; ALOGV("%s returns output %d", __func__, *output); return NO_ERROR; } // Virtual sources must always be dynamicaly or explicitly routed if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE"); if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) { ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__); return BAD_VALUE; } device = getDeviceForStrategy(strategy, false /*fromCache*/); } if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC); } Loading @@ -869,7 +876,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, // to getOutputForDevice. // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side. if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX && (*stream == AUDIO_STREAM_MUSIC || attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) && (*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) && audio_is_linear_pcm(config->format) && isInCall()) { if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) { Loading @@ -880,9 +887,9 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, } } ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, " ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, " "flags %#x", device, config->sample_rate, config->format, config->channel_mask, *flags); __func__, device, config->sample_rate, config->format, config->channel_mask, *flags); *output = AUDIO_IO_HANDLE_NONE; if (msdDevice != AUDIO_DEVICE_NONE) { Loading @@ -906,22 +913,48 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId() : AUDIO_PORT_HANDLE_NONE; exit: ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId); return NO_ERROR; } status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, audio_io_handle_t *output, audio_session_t session, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId, audio_port_handle_t *portId) { // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } const audio_port_handle_t requestedDeviceId = *selectedDeviceId; audio_attributes_t resultAttr; status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid, config, flags, selectedDeviceId); if (status != NO_ERROR) { return status; } audio_config_base_t clientConfig = {.sample_rate = config->sample_rate, .format = config->format, .channel_mask = config->channel_mask }; *portId = AudioPort::getNextUniqueId(); sp<TrackClientDescriptor> clientDesc = new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig, new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig, requestedDeviceId, *stream, getStrategyForAttr(&attributes), getStrategyForAttr(&resultAttr), *flags); sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output); outputDesc->addClient(clientDesc); ALOGV(" getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d", *output, *selectedDeviceId, *portId); ALOGV("%s returns output %d selectedDeviceId %d for port ID %d", __func__, *output, requestedDeviceId, *portId); return NO_ERROR; } Loading Loading @@ -3400,11 +3433,20 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor> srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 && srcDeviceDesc->getAudioPort()->mGains.size() > 0) { ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__); // TODO: may explicitly specify whether we should use HW or SW patch // create patch between src device and output device // create Hwoutput and add to mHwOutputs } else { SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs); audio_io_handle_t output = selectOutput(outputs); audio_attributes_t resultAttr; audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = sourceDesc->config().sample_rate; config.channel_mask = sourceDesc->config().channel_mask; config.format = sourceDesc->config().format; audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId); if (output == AUDIO_IO_HANDLE_NONE) { ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice); return INVALID_OPERATION; Loading Loading @@ -3437,6 +3479,13 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor> __FUNCTION__, status); return INVALID_OPERATION; } if (outputDesc->getClient(sourceDesc->portId()) != nullptr) { ALOGW("%s source portId has already been attached to outputDesc", __func__); return INVALID_OPERATION; } outputDesc->addClient(sourceDesc); uint32_t delayMs = 0; status = startSource(outputDesc, sourceDesc, &delayMs); Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +15 −0 Original line number Diff line number Diff line Loading @@ -661,6 +661,21 @@ private: const String8& address /*in*/, SortedVector<audio_io_handle_t>& outputs /*out*/); uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; } // internal method, get audio_attributes_t from either a source audio_attributes_t // or audio_stream_type_t, respectively. status_t getAudioAttributes(audio_attributes_t *dstAttr, const audio_attributes_t *srcAttr, audio_stream_type_t srcStream); // internal method, called by getOutputForAttr() and connectAudioSource. status_t getOutputForAttrInt(audio_attributes_t *resultAttr, audio_io_handle_t *output, audio_session_t session, const audio_attributes_t *attr, audio_stream_type_t *stream, uid_t uid, const audio_config_t *config, audio_output_flags_t *flags, audio_port_handle_t *selectedDeviceId); // internal method to return the output handle for the given device and format audio_io_handle_t getOutputForDevice( audio_devices_t device, Loading