音频输出设备的选择

场景:使用AudioTrack播放一段音频,streamtype是AUDIO_STREAM_MUSIC;

跟踪音频输出设备选择的流程,代码会走到这里:

1.frameworks\av\media\libaudioclient\AudioTrack.cpp
 
status_t AudioTrack::createTrack_l(){
 
    ......
    
    //假设此时播放的是音乐,那这里的streamType是Music类型,所以属性attr为NULL
    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
    
    ......
 
    //通过属性以及stream的类型获取当前track输出的output设备;
    //传入的audio_attributes_t等参数,带回output
    status = AudioSystem::getOutputForAttr(attr, &output,
                                           mSessionId, &streamType, mClientUid,
                                           &config,
                                           mFlags, &mRoutedDeviceId, &mPortId);
 
    ......
 
}
 
 
2.frameworks\av\media\libaudioclient\AudioSystem.cpp
status_t AudioSystem::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)
{
    //实现类是AudioPolicyInterfaceImpl
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return NO_INIT;
    //调用AudioPolicyInterfaceImpl.getOutputForAttr();
    return aps->getOutputForAttr(attr, output, session, stream, uid,
                                 config,
                                 flags, selectedDeviceId, portId);
}
 
3.frameworks\av\services\audiopolicy\service\AudioPolicyInterfaceImpl.cpp
status_t AudioPolicyService::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)
{
    if (mAudioPolicyManager == NULL) {
        return NO_INIT;
    }
    ALOGV("getOutput()");
    Mutex::Autolock _l(mLock);
 
    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    if (!isTrustedCallingUid(callingUid) || uid == (uid_t)-1) {
        ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
                "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
        uid = callingUid;
    }
    //进入AudioPolicyManager
    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
                                                 config,
                                                 flags, selectedDeviceId, portId);
}
 
 
4.frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
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)
{
    audio_attributes_t attributes;
    //对于当前music的track,传入的attr是NULL,
    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保存到attributes的属性中
        /*对于当前music的场景,attributes会被如下赋值
		    attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
       	    attr->usage = AUDIO_USAGE_MEDIA;
		*/
        stream_type_to_audio_attributes(*stream, &attributes);
    }
 
    ......
 
    *stream = streamTypefromAttributesInt(&attributes);
 
    ......
 
    //②根据当前音频的属性,获取当前track的音频策略,根据attributes选中Strategy
    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
 
    //③根据当前track的音频策略,获取当前音频的输出终端,根据Strategy选中device
    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
 
    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
    }
 
    ALOGV("getOutputForAttr() device 0x%x, samplingRate %d, format %x, channelMask %x, flags %x",
          device, config->sample_rate, config->format, config->channel_mask, flags);
 
    //④根据音频设备,音频输出标识,format等选择输出路径,根据选定的device获取Output
    *output = getOutputForDevice(device, session, *stream,
                                 config->sample_rate, config->format, config->channel_mask,
                                 flags, &config->offload_info);
    ......
 
    return NO_ERROR;
}
 

先看①:stream_type_to_audio_attributes(*stream, &attributes),将stream保存到attributes的属性中:

frameworks\av\media\libaudioclient\include\media\AudioPolicyHelper.h
static inline
void stream_type_to_audio_attributes(audio_stream_type_t streamType,
                                     audio_attributes_t *attr) {
    memset(attr, 0, sizeof(audio_attributes_t));
 
    switch (streamType) {
    case AUDIO_STREAM_DEFAULT:
    case AUDIO_STREAM_MUSIC:
        attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
        attr->usage = AUDIO_USAGE_MEDIA;
        break;
    case AUDIO_STREAM_VOICE_CALL:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
        break;
    case AUDIO_STREAM_ENFORCED_AUDIBLE:
        attr->flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
        // intended fall through, attributes in common with STREAM_SYSTEM
    case AUDIO_STREAM_SYSTEM:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
        break;
    case AUDIO_STREAM_RING:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
        break;
    case AUDIO_STREAM_ALARM:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_ALARM;
        break;
    case AUDIO_STREAM_NOTIFICATION:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_NOTIFICATION;
        break;
    case AUDIO_STREAM_BLUETOOTH_SCO:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
        attr->flags |= AUDIO_FLAG_SCO;
        break;
    case AUDIO_STREAM_DTMF:
        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
        break;
    case AUDIO_STREAM_TTS:
        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
        attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
        break;
    default:
        ALOGE("invalid stream type %d when converting to attributes", streamType);
    }
}

content_type:具体输出类型。android当前一共提供了11种stream_type,但一旦进入到Attribute,Android就只将其整理成几种类型。这才是实际的类型。

这里的stream_type,usage定义在audio-base.h中,content_type定义在了audio.h中:
 

1.system\media\audio\include\system\audio-base.h
typedef enum {
    AUDIO_STREAM_DEFAULT = -1, // (-1)
    AUDIO_STREAM_MIN = 0,
    AUDIO_STREAM_VOICE_CALL = 0,
    AUDIO_STREAM_SYSTEM = 1,
    AUDIO_STREAM_RING = 2,
    AUDIO_STREAM_MUSIC = 3,
    AUDIO_STREAM_ALARM = 4,
    AUDIO_STREAM_NOTIFICATION = 5,
    AUDIO_STREAM_BLUETOOTH_SCO = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
    AUDIO_STREAM_DTMF = 8,
    AUDIO_STREAM_TTS = 9,
    AUDIO_STREAM_ACCESSIBILITY = 10,
    AUDIO_STREAM_REROUTING = 11,
    AUDIO_STREAM_PATCH = 12,
    AUDIO_STREAM_PUBLIC_CNT = 11, // (ACCESSIBILITY + 1)
    AUDIO_STREAM_FOR_POLICY_CNT = 12, // PATCH
    AUDIO_STREAM_CNT = 13, // (PATCH + 1)
} audio_stream_type_t;
 
typedef enum {
    AUDIO_USAGE_UNKNOWN = 0,
    AUDIO_USAGE_MEDIA = 1,
    AUDIO_USAGE_VOICE_COMMUNICATION = 2,
    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING = 3,
    AUDIO_USAGE_ALARM = 4,
    AUDIO_USAGE_NOTIFICATION = 5,
    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
    AUDIO_USAGE_NOTIFICATION_EVENT = 10,
    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY = 11,
    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12,
    AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13,
    AUDIO_USAGE_GAME = 14,
    AUDIO_USAGE_VIRTUAL_SOURCE = 15,
    AUDIO_USAGE_ASSISTANT = 16,
    AUDIO_USAGE_CNT = 17,
    AUDIO_USAGE_MAX = 16, // (CNT - 1)
} audio_usage_t;
 
2.system\media\audio\include\system\audio.h
typedef enum {
    AUDIO_CONTENT_TYPE_UNKNOWN      = 0,
    AUDIO_CONTENT_TYPE_SPEECH       = 1,
    AUDIO_CONTENT_TYPE_MUSIC        = 2,
    AUDIO_CONTENT_TYPE_MOVIE        = 3,
    AUDIO_CONTENT_TYPE_SONIFICATION = 4,
 
    AUDIO_CONTENT_TYPE_CNT,
    AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
} audio_content_type_t;

再看②: routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);//根据当前音频的属性,获取当前track的音频策略也就是根据attributes选中Strategy:

uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
    // flags to strategy mapping
    if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
        return (uint32_t) STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
    }
    if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
        return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
    }
    // usage to strategy mapping
    //进入Engine.cpp
    //这里范围音频策略是:STRATEGY_MEDIA
    return static_cast<uint32_t>(mEngine->getStrategyForUsage(attr->usage));
}
 
 
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
{
    // usage to strategy mapping
    switch (usage) {
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        return STRATEGY_ACCESSIBILITY;
 
    case AUDIO_USAGE_MEDIA:
    case AUDIO_USAGE_GAME:
    case AUDIO_USAGE_ASSISTANT:
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
        return STRATEGY_MEDIA;
 
    case AUDIO_USAGE_VOICE_COMMUNICATION:
        return STRATEGY_PHONE;
 
    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
        return STRATEGY_DTMF;
 
    case AUDIO_USAGE_ALARM:
    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
        return STRATEGY_SONIFICATION;
 
    case AUDIO_USAGE_NOTIFICATION:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
    case AUDIO_USAGE_NOTIFICATION_EVENT:
        return STRATEGY_SONIFICATION_RESPECTFUL;
 
    case AUDIO_USAGE_UNKNOWN:
    default:
        return STRATEGY_MEDIA;
    }
}

音频策略strategy定义在RoutingStrategy.h中:

frameworks\av\services\audiopolicy\common\include\RoutingStrategy.h
enum routing_strategy {
    STRATEGY_MEDIA,
    STRATEGY_PHONE,
    STRATEGY_SONIFICATION,
    STRATEGY_SONIFICATION_RESPECTFUL,
    STRATEGY_DTMF,
    STRATEGY_ENFORCED_AUDIBLE,
    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
    STRATEGY_ACCESSIBILITY,
    STRATEGY_REROUTING,
    NUM_STRATEGIES
};

   然后看③: audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);//根据当前track的音频策略,获取当前音频的输出终端,也就是根据Strategy选中device:

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
                                                         bool fromCache)
{
    ......
    return mEngine->getDeviceForStrategy(strategy);
}
 
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
{
    DeviceVector availableOutputDevices = mApmObserver->getAvailableOutputDevices();
    DeviceVector availableInputDevices = mApmObserver->getAvailableInputDevices();
 
    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
 
    return getDeviceForStrategyInt(strategy, availableOutputDevices,
                                   availableInputDevices, outputs);
}

策略,USAGE,STREAM对应关系如下:

STRATEGY_ACCESSIBILITY
    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY  // 11
        AUDIO_STREAM_TTS  //  9

STRATEGY_MEDIA
    AUDIO_USAGE_MEDIA  //  1
        AUDIO_STREAM_DEFAULT  // -1
        AUDIO_STREAM_MUSIC    //  3
    AUDIO_USAGE_GAME
    AUDIO_USAGE_ASSISTANT
    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
    AUDIO_USAGE_ASSISTANCE_SONIFICATION  //  11
        AUDIO_STREAM_ENFORCED_AUDIBLE   //  7
        AUDIO_STREAM_SYSTEM  //  1

STRATEGY_PHONE
    AUDIO_USAGE_VOICE_COMMUNICATION  //  2
        AUDIO_STREAM_VOICE_CALL  //  0
        AUDIO_STREAM_BLUETOOTH_SCO  //  6

STRATEGY_DTMF
    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING  //  3
        AUDIO_STREAM_DTMF  //  8

STRATEGY_SONIFICATION
    AUDIO_USAGE_ALARM  // 4
        AUDIO_STREAM_ALARM  //  4
    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE  //  6
        AUDIO_STREAM_RING  //  2

STRATEGY_SONIFICATION_RESPECTFUL
    AUDIO_USAGE_NOTIFICATION  //  5
        AUDIO_STREAM_NOTIFICATION  //  5
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT
    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED
    AUDIO_USAGE_NOTIFICATION_EVENT

STRATEGY_MEDIA
    AUDIO_USAGE_UNKNOWN  //  0
    default

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值