当前位置:   article > 正文

Android P Audio系统笔记:AudioPolicy&AudioFlinger初始化

audioflinger

AudioPolicy&AudioFlinger初始化

  • 初始化概览
    • 总体框架
    • 启动步骤
    • AudioPolicy初始化分析
      • 1、loadConfig()
      • 2、initialize()

初始化概览

总体框架

AudioFlinger和AudioPolicy两者是Android Audio框架层最主要的两个服务,他们两个是Android框架层的本地服务,在init.rc中启动;
AudioPolicyManager负责音频策略定制者,说白了就相当于Audio系统的司令。
AudioFlinger负责与底层audio alsa进行交互的实现者,那么它就是Audio系统的军官,干苦力的;
总体框架:
两个服务都属于audioserver进程,严格意义上来说audioserver通过init进程fork出来的,所以它是Linux系统中的一个进程。
AudioFlinger:media.audio_flinger
AudioPolicyService:media.audio_policy

启动步骤

1、通过init进程fork出来,从而开始各自服务的初始化
2、首先初始化audioflinger服务
3、其次初始化audiopolicyservice服务
4、进一步通过audiopolicyservice和audioflinger完成音频hal层的初始化,这部分将是本文的重点难点分析。
1、通过init进程fork出来,从而开始各自服务的初始化
来,看下它是怎么定义:

  1. //frameworks/av/media/audioserver/audioserver.rc
  2. service audioserver /system/bin/audioserver
  3. class core
  4. user audioserver
  5. onrestart restart audio-hal-2-0
  6. ioprio rt 4 //设置io优先级
  7. disabled

可以看到audioserver属于core类型,优于一般的main类型,也就是说它的启动是更早的。
audioflinger&audiopolicyserver启动:

  1. frameworks/av/media/audioserver/main_audioserver.cpp
  2. int main(int argc __unused, char **argv)
  3. {
  4. ---
  5. android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
  6. sp<ProcessState> proc(ProcessState::self());
  7. sp<IServiceManager> sm = defaultServiceManager();
  8. ALOGI("ServiceManager: %p", sm.get());
  9. AudioFlinger::instantiate();
  10. AudioPolicyService::instantiate();
  11. ---
  12. }

2、首先初始化audioflinger服务
AudioFlinger初始化比较简洁,就是创建服务并将自身注册到systemserver中去,其次就是初始化部分通信组件以便后续与audio hal层进行通讯。如下图所示:

3、其次初始化audiopolicyservice服务
AudioPolicyService的初始化就比audioflinger服务初始化复杂了,下图仅仅是audiopolicyservice与audiopolicymanager的初始化。主要就是创建出几个线程(AudioCommandThread类型的线程),以便后续与上层进行交互使用,上层调用的比如播放暂停的操作指令会进入这个线程队列,实现上层异步调用也可以防止底层耗时操作导致阻塞上层应用。接着便是创建AudioPolicyManager实例以及客户端等。大概流程如下图所示:

4、进一步通过audiopolicyservice和audioflinger完成音频hal层的初始化,这部分将是本文的重点难点分析。

audiopolicyservice启动后,开始创建audiopolicymanager,并通过audiopolicymanager初始化audiopolicy策略,然后再进行对audio路由引擎(EngineInstance)进行初始化,初始化完路由引擎后便对audio hal 的so进行加载初始化,进一步通过加载后的so针对音频设备进行open操作,并默认打开主通道的输出音频流,最后将成功初始化的音频设备进行保存到audiopolicymanager以及audioflinger中,最后完成初始化。
详细的初始化流程如下图所示:

AudioPolicy初始化分析

从上面的初始大概流程可以知道,audio框架的初始化重点在audiopolicy部分的初始化,它不仅需要初始音频策略,还需针对加载的音频策略针对hal层的音频设备进行初始化,这部分还涉及到audioflinger部分,但以audiopolicy作为主线进行分析,下面将一步步对其进行分析。

  1. //frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
  2. AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
  3. : AudioPolicyManager(clientInterface, false /*forTesting*/)
  4. {
  5. //1、加载audiopolicy的策略文件
  6. loadConfig();
  7. //2、针对加载的策略进行真正的初始化
  8. initialize();
  9. }

可以看到AudioPolicyManager构造函数很简单,就两个调用:loadConfig(),initialize();

1、loadConfig()

很简单,就通过配置文件USE_XML_AUDIO_POLICY_CONF来控制是使用XML配置的策略文件还是使用传统旧config配置文件。这个变量的初始化可以通过配置文件进行选择。

  1. //frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
  2. void AudioPolicyManager::loadConfig() {
  3. #ifdef USE_XML_AUDIO_POLICY_CONF
  4. if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
  5. #else
  6. if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)
  7. && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) {
  8. #endif
  9. ALOGE("could not load audio policy configuration file, setting defaults");
  10. getConfig().setDefault();
  11. }
  12. }

其会通过Serializer.cpp进行XML文件的解析,这个是一个很繁重的任务,如需讲明其解析过程还需另起一个篇幅才能将其介绍,与初始化关系不大,一笔带过。
XML的配置文件格式如下(简化版配置):

  1. //frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml
  2. <audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
  3. <globalConfiguration speaker_drc_enabled="true"/>
  4. <modules>
  5. <module name="primary" halVersion="2.0">
  6. <attachedDevices>
  7. <item>Speaker</item>
  8. </attachedDevices>
  9. <defaultOutputDevice>Speaker</defaultOutputDevice>
  10. <mixPorts>//输出混音线程
  11. <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
  12. <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000"
  13. channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
  14. </mixPort>
  15. </mixPorts>
  16. <devicePorts>//输出设备节点
  17. <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink" >
  18. </devicePort>
  19. </devicePorts>
  20. <routes>
  21. //音频路由
  22. <route type="mix" sink="Speaker" sources="esai output,primary output"/>
  23. </routes>
  24. </module>
  25. </modules>
  26. </audioPolicyConfiguration>

2、initialize()

好了,上面的都是开胃菜,这个才是硬菜。
来,看下这个大概步骤,心中有谱,码海不慌。
主要是三个步骤:
2.1初始音频路由引擎
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
2.2、加载so 并且打开设备节点
mpClientInterface->loadHwModule(hwModule->getName())
2.3、打开输出流
status_t status = outputDesc->open(nullptr, profileType, address, AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE,&output);
怕你不信,所以贴了部分代码出来:

  1. status_t AudioPolicyManager::initialize() {
  2. //1、初始音频路由引擎
  3. // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
  4. audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
  5. if (!engineInstance) {
  6. ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
  7. return NO_INIT;
  8. }
  9. // Retrieve the Policy Manager Interface
  10. mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
  11. if (mEngine == NULL) {
  12. ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
  13. return NO_INIT;
  14. }
  15. mEngine->setObserver(this);
  16. status_t status = mEngine->initCheck();
  17. for (const auto& hwModule : mHwModulesAll) {
  18. //2、加载so 并且打开设备节点
  19. hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
  20. mHwModules.push_back(hwModule);
  21. // open all output streams needed to access attached devices
  22. // except for direct output streams that are only opened when they are actually
  23. // required by an app.
  24. // This also validates mAvailableOutputDevices list
  25. for (const auto& outProfile : hwModule->getOutputProfiles()) {
  26. //经过一系列有效判断后 创建输出相关参数
  27. sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
  28. mpClientInterface);
  29. const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
  30. const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType);
  31. String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
  32. : String8("");
  33. audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
  34. //3、打开输出流
  35. status_t status = outputDesc->open(nullptr, profileType, address,
  36. AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
  37. if (status != NO_ERROR) {
  38. ALOGW("Cannot open output stream for device %08x on hw module %s",
  39. outputDesc->mDevice,
  40. hwModule->getName());
  41. } else {
  42. for (const auto& dev : supportedDevices) {
  43. ssize_t index = mAvailableOutputDevices.indexOf(dev);
  44. // give a valid ID to an attached device once confirmed it is reachable
  45. if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
  46. //这个很重要的变量,保存了可用的输出设备,后续会进一步说明
  47. mAvailableOutputDevices[index]->attach(hwModule);
  48. }
  49. }
  50. if (mPrimaryOutput == 0 &&
  51. outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
  52. mPrimaryOutput = outputDesc;
  53. }
  54. addOutput(output, outputDesc);
  55. setOutputDevice(outputDesc, profileType, true, 0, NULL, address);
  56. }
  57. }//end inner for
  58. }//end out for
  59. }
  60. // make sure all attached devices have been allocated a unique ID

 

 

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/499781
推荐阅读
相关标签
  

闽ICP备14008679号