本章节,大体介绍一下AudioPolicyService
手机的Audio输入源很多,例如放电影,放音乐,通话,铃声,提示音等
输出也很多,例如蓝牙,耳机,喇叭,听筒等
那么什么声音输出到什么地方呢?
这就是AudioPolicyService干的事情了。
首先明确几个概念:
1,Audio interfaces
安卓手机上目前支持三类音频播放设备,这个主要是根据声音播放端和CPU的通信关系来划分的。
static const char * const audio_interfaces[] = {
AUDIO_HARDWARE_MODULE_ID_PRIMARY, //手机板载的主设备
AUDIO_HARDWARE_MODULE_ID_A2DP, //蓝牙音频
AUDIO_HARDWARE_MODULE_ID_USB, //USB音频
};
2,Audio Devices ,是指具体的音频播放设备。比Audio interfaces的粒度要细一些
见表格
3, StreamType, 是指PCM的生成类型。是播放电影产生的?还是通话产生的?
enum stream_type {
DEFAULT =-1,
VOICE_CALL = 0,
SYSTEM = 1,
RING = 2,
MUSIC = 3,
ALARM = 4,
NOTIFICATION = 5,
BLUETOOTH_SCO = 6,
ENFORCED_AUDIBLE = 7,
DTMF = 8,
TTS = 9,
NUM_STREAM_TYPES
};
4,
STRATEGY, 是指针对某一中stream,该采用的策略。在策略里面,会根据其他信息来具体选定某一个具体的Audio Devices
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_SONIFICATION_RESPECTFUL,
STRATEGY_DTMF,
STRATEGY_ENFORCED_AUDIBLE,
NUM_STRATEGIES
};
所以,APS干的事情,实际上就是根据这一路AudioTrack的StreamType,找到他要遵循的STRATEGY,根据这个STRATEGY,在目前设备上可以获得的Audio Devices里面查找到最优的Audio Devices,
然后使用这个Audio Device来播放声音 。
下面我们来分析一下APS的启动过程
在AF章节中,我们介绍过,mediaserver进程启动时,会启动APS进程,
然后APS的构造函数被被调用到
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); //获得HAL层的so lib
rc = audio_policy_dev_open(module, &mpAudioPolicyDev); //打开上面获得的policy 设备
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy); //创建一个策略
rc = mpAudioPolicy->init_check(mpAudioPolicy); //初始化检测
}
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); //获得HAL层的so lib
rc = audio_policy_dev_open(module, &mpAudioPolicyDev); //打开上面获得的policy 设备
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy); //创建一个策略
rc = mpAudioPolicy->init_check(mpAudioPolicy); //初始化检测
}
下面针对这个构造函数具体介绍一下
和AF一样,也APS需要打开一个HAL层的so lib库。
只不过AF中的HAL 库,会调用实际的硬件。而这里的HAL库一般不调用硬件,只是为了方便厂家定义自己的策略,独立出来一个模块而已。
这里实际上打开的就是Audio_policy_hal.cpp这个so lib。并且返回一个hw_module_t作为handle.
然后audio_policy_dev_open调用Audio_policy_hal.cpp中的legacy_ap_dev_open,这主要是为一个hw_device_t结构挂钩子函数,填充信息。并且把hw_device_t返回给上层。
后面调用的create_audio_policy,实际上就是这里挂到hw_device_t上面的create_legacy_ap。
create_legacy_ap主要作用就是创建一个struct audio_policy结构体,当中挂了很多Audio_policy_hal.cpp中的钩子函数。如下:
lap->policy.set_phone_state = ap_set_phone_state;
lap->policy.set_ringer_mode = ap_set_ringer_mode;
lap->policy.set_force_use = ap_set_force_use;
lap->policy.get_force_use = ap_get_force_use;
lap->policy.set_can_mute_enforced_audible = ap_set_can_mute_enforced_audible;
lap->policy.init_check = ap_init_check;
lap->policy.get_output = ap_get_output;
lap->policy.start_output = ap_start_output;
lap->policy.stop_output = ap_stop_output;
lap->policy.release_output = ap_release_output;
lap->policy.get_input = ap_get_input;
lap->policy.start_input = ap_start_input;
lap->policy.stop_input = ap_stop_input;
lap->policy.release_input = ap_release_input;
lap->policy.init_stream_volume = ap_init_stream_volume;
lap->policy.set_stream_volume_index = ap_set_stream_volume_index;
lap->policy.get_stream_volume_index = ap_get_stream_volume_index;
lap->policy.set_stream_volume_index_for_device = ap_set_stream_volume_index_for_device;
lap->policy.get_stream_volume_index_for_device = ap_get_stream_volume_index_for_device;
lap->policy.get_strategy_for_stream = ap_get_strategy_for_stream;
lap->policy.get_devices_for_stream = ap_get_devices_for_stream;
lap->policy.get_output_for_effect = ap_get_output_for_effect;
这些钩子函数,都是后面APS实际发挥作用时要用到的。
例如最后一步调用的init_check,就是这里挂上去的。
而这些钩子函数,例如ap_init_check,最终都是调用的AudioPolicyManagerBase中的函数来发挥实际作用。
例如status_t AudioPolicyManagerBase::initCheck()
所以,APS只是一个接口而已,APS实际发挥作用,依赖的就是AudioPolicyManagerBase类。
是不是很绕?
可以说mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy)这个函数,是APS构造函数里面最重要的函数
返回的mpAudioPolicy,当中挂接了各种操作接口,后续APS实际发挥作用,全靠他。
在AudioPolicyManagerBase的构造函数中,会进行非常多的初始化操作
<pre name="code" class="cpp">AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
{
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { //读取配置文件
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
{
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { //读取配置文件
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); //根据配置文件加载 所有audio interface的so lib
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j]; //根据配置文件加载 所有output audio device
if ((outProfile->mSupportedDevices & mAttachedOutputDevices) &&
((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice & outProfile->mSupportedDevices);
audio_io_handle_t output = mpClientInterface->openOutput( //打开output
outProfile->mModule->mHandle,
&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannelMask,
&outputDesc->mLatency,
outputDesc->mFlags);
mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | //记录所有可用的output device
(outProfile->mSupportedDevices & mAttachedOutputDevices));
}
}
}
}
通过对AudioPolicyManagerBase构造函数的简化,我们可以知道其干了以下事情:
1,读取配置文件
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
#define AUDIO_POLICY_CONFIG_FILE"/system/etc/audio_policy.conf"
如下所示:
audio_hw_modules {
primary { //有哪些audio interface
outputs {
primary { //有哪些output audio device
sampling_rates 48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
deep_buffer { //有哪些output audio device
sampling_rates 48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE
flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER
}
}
inputs {
primary { //有哪些input audio device
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_VOICE_CALL
}
}
}
a2dp { //有哪些audio interface
outputs {
a2dp { //有哪些output audio device
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_A2DP
}
}
}
}
配置文件记录了有哪些audio interface, 每个audio interface里面有哪些input,output audio device,每个设备的属性。
通过读取配置文件,就知道了系统中有哪些audio interface 例如(“primary”、“a2dp”、“usb”),
每个audio interface 中有哪些input,output audio device, 例如 (primary,deep_buffer)
每个audio device中的属性 ,例如sampling_rates,channel_masks,formats
2,配置文件读取完毕之后,利用两层循环,
外层循环调用mpClientInterface->loadHwModule,遍历所有的 audio interface,
内层循环调用mpClientInterface->openOutput,遍历所有的output audio device,打开这些output audio device。
并且记录下可用的outputDevice
那么mpClientInterface->loadHwModule,mpClientInterface->openOutput具体是如何实现的呢?
AudioPolicyService::AudioPolicyService中,我们强调了mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, &mpAudioPolicy);
这个函数传入了aps_ops数组,这个数组在create_legacy_ap中,被挂到了mpClientInterface中。
所以,mpClientInterface调用的函数,就是aps_ops的函数。
struct audio_policy_service_ops aps_ops = {
open_output : aps_open_output,
open_duplicate_output : aps_open_dup_output,
close_output : aps_close_output,
suspend_output : aps_suspend_output,
restore_output : aps_restore_output,
open_input : aps_open_input,
close_input : aps_close_input,
set_stream_volume : aps_set_stream_volume,
set_stream_output : aps_set_stream_output,
set_parameters : aps_set_parameters,
get_parameters : aps_get_parameters,
start_tone : aps_start_tone,
stop_tone : aps_stop_tone,
set_voice_volume : aps_set_voice_volume,
move_effects : aps_move_effects,
load_hw_module : aps_load_hw_module,
open_output_on_module : aps_open_output_on_module,
open_input_on_module : aps_open_input_on_module,
};
其中:
static audio_module_handle_t aps_load_hw_module(void*service,const char *name)
{
sp<IAudioFlinger> af= AudioSystem::get_audio_flinger();
…
returnaf->loadHwModule(name);
}
static audio_io_handle_t aps_open_output(…)
{
sp<IAudioFlinger> af= AudioSystem::get_audio_flinger();
…
return af->openOutput((audio_module_handle_t)0,pDevices, pSamplingRate, pFormat, pChannelMask,
pLatencyMs, flags);
}
也就是说mpClientInterface->loadHwModule,mpClientInterface->openOutput最终调用了AF中的函数。
这就是我们在AF章节中提到的”在audio播放之前,AP还会调用AF的openOutput函数来打开一个输出“ ”AP会调用AF的函数AudioFlinger::loadHwModule完成对应SO的加载“
到目前为止,我们介绍完了APS的初始化部分。
那么APS具体是怎么工作的呢?让我们回到AT部分
AT章节中,我们提到了AudioTrack::set函数,经过如下层层调用:
AudioTrack::set
--->AudioSystem::getOutput
--->AudioPolicyService::getOutput
--->ap_get_output
--->AudioPolicyManagerBase::getOutput
在
AudioPolicyManagerBase::getOutput里面完成audio policy的选取
audio_io_handle_t AudioPolicyManagerBase::getOutput()
{
routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); //根据stream_type来确定这个AT应该遵循的strategy
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); //根据这个strategy,在当前可用设备中,找到优先级最高的设备
if (audio_is_linear_pcm((audio_format_t)format)) {
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); //在output playbackThread中,找到所有支持这个选中的设备的output playbackThread
output = selectOutput(outputs, flags); //在找到的所有的playback中,选择一个最优的output playbackThread
}
return output;
}
通过对代码的简化,我们可以看到,
首先要根据AT传过来的stream_type来决定AT应该遵循的策略,比如AudioSystem::TTS 和AudioSystem::MUSIC对应的是STRATEGY_MEDIA,AudioSystem::NOTIFICATION对应的是STRATEGY_SONIFICATION_RESPECTFUL。
具体下图所示:
然后根据这个策略,查询当前可用设备,在可用设备里找一个优先级最高的,逻辑如下:
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
if (strategy != STRATEGY_SONIFICATION) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
代码逻辑很简单。谁在前面,谁就优先级高。
因为要写入实际硬件,是要通过AF中的output的概念写入的,也就是通过playbackThread来写入硬件。
所以不仅要完成device的选择,还要完成playbackThread的选择
。
这里要找到所有支持这个最高优先级audio device的playbackThread,这就是getOutputsForDevice完成的工作。
当然,找到的playbackThread可能有多个,这时就要选取最合适的。这就是selectOutput函数干的事情。
那么何谓最合适呢?
audio_io_handle_t AudioPolicyManagerBase::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
AudioSystem::output_flags flags)
{
int maxCommonFlags = 0;
for (size_t i = 0; i < outputs.size(); i++) {
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(outputs[i]);
if (!outputDesc->isDuplicated()) {
int commonFlags = (int)AudioSystem::popCount(outputDesc->mProfile->mFlags & flags);
if (commonFlags > maxCommonFlags) {
outputFlags = outputs[i];
maxCommonFlags = commonFlags;
}
}
}
if (outputFlags != 0) {
return outputFlags;
}
}
可以看到,这里想做的,就是拿AT传过来的output_flags和outputDesc->mProfile->mFlags做比较,相似度最高的(maxCommonFlags值最大),就会被选中。
outputDesc->mProfile->mFlags 则是在AudioPolicyManagerBase构造函数中,读取配置文件获得。
这样,就根据AT传过来的信息,为这个AT的找到了对应的playbackThread, 并且通过调用AF的代码,在playbackThread中完成了Track的创建。
之后,AT写入playbackThread中的代码,就会写到对应的硬件中。