Android 11音频服务创建以及播放的流程

文中相关图片的源文件在。
一、音频服务初始化流程
当前版本: 11
大致的创建流程如下:
经过上面的流程系统音频服务已经启动处于待命状态,如果有应用需要播放则会通过服务最终选择合适的硬件将声音播出,接下来按照上面的流程进行进一步的细分 。
1.1 开机启动音频服务
音频服务在/av/media//.cpp中,这里会启动音频的和两大组件,简单的流程如下:
经过上面流程之后音频系统中会启动用于处理后面所有的音频播放,具体的功能后面再详细分析,负责后面的音频策略的处理等流程,和之间进行交互 。
1.2 模块加载
通过上面流程会调用到的构造函数,进行模块的处理,流程如下:
在上面的构造函数中实例化了设备接口以及音效接口,此时模块已经成功创建出来,后面就是创建出来后和之间的交互过程 。
1.3 模块加载
负责音频的一些策略管理以及命令处理,具体的启动流程如下:
总结:
首先分析了从创建的流程,这里涉及到第三方自己的,所以中间多了一个RD的创建有了对象之后需要加载音频的一些配置文件,包括描述所有外部设备以及设备之间路由情况的.xml,这个xml文件解析之后会将内容存放到持有的对象中,具体的作用我们后面分析加载完xml之后就是进行对象的创建,这个对象负责管理音频策略相关的内容对象创建完毕之后需要对xml解析出来的内容进行处理,这部分涉及和的交互,放在后面一节讲述 1.3.1 和交互流程
这里涉及几个重要的文件位置:
分析:在ss的时候会加载音频库,这里会加载第三方自己实现的库,一般第三方的库中都有对open函数指针的赋值,这里赋的是;然后调用最终调用到之后会打开相应的模块,并将所有的操作指针进行赋值,如果成功返回再创建对象,在这里也是为以后调用/等函数做准备,这些函数就包含在这个对象中 。

Android 11音频服务创建以及播放的流程

文章插图
1.3.2 输入输出设备的打开和线程创建
在前面流程图的第三步,具体代码如下:
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices){for (const auto& hwModule : mHwModulesAll) {if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {continue;}hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {ALOGW("could not open HW module %s", hwModule->getName());continue;}mHwModules.push_back(hwModule);// 打开访问附加设备所需的所有输出流,除了仅在应用程序实际需// 要时才打开的直接输出流 。这也验证了 mAvailableOutputDevices 列表 for (const auto& outProfile : hwModule->getOutputProfiles()) {if (!outProfile->canOpenNewIo()) {ALOGE("Invalid Output profile max open count %u for profile %s",outProfile->maxOpenCount, outProfile->getTagName().c_str());continue;}if (!outProfile->hasSupportedDevices()) {ALOGW("Output profile contains no device on module %s", hwModule->getName());continue;}// 这里和primary_audio_policy_coinfiguration.xml中给hifi音源加的flag进行对应if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {mTtsOutputAvailable = true;}const DeviceVector &supportedDevices = outProfile->getSupportedDevices();DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);sp supportedDevice = 0;if (supportedDevices.contains(mDefaultOutputDevice)) {supportedDevice = mDefaultOutputDevice;} else {// 选择配置文件的 SupportedDevices 中存在的第一个设备,// 也是 mAvailableOutputDevices 的一部分 。if (availProfileDevices.isEmpty()) {continue;}supportedDevice = availProfileDevices.itemAt(0);}if (!mOutputDevicesAll.contains(supportedDevice)) {continue;}// 根据outProfile 得到一个描述符,设置mpClientInterface// 描述了source和sink之间的关系sp> outputDesc = new SwAudioOutputDescriptor(outProfile,mpClientInterface);audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;// 在这里最终调用AudioFlinger的openOutput函数打开这个输出流,并返回表示这个设备的输出流// 的句柄audio_io_handle_t用于后面AudioTrack创建的时候查找具体的线程使用status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),AUDIO_STREAM_DEFAULT,AUDIO_OUTPUT_FLAG_NONE, &output);if (status != NO_ERROR) {ALOGW("Cannot open output stream for devices %s on hw module %s",// 表示失败,不能打开profile对应的device的输出流supportedDevice->toString().c_str(), hwModule->getName());continue;}for (const auto &device : availProfileDevices) {// 一旦确认连接的设备可以访问,就为它提供一个有效的 ID if (!device->isAttached()) {device->attach(hwModule);mAvailableOutputDevices.add(device); // 添加到可用的输出设备中device->setEncapsulationInfoFromHal(mpClientInterface);if (newDevices) newDevices->add(device);setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);}}if (mPrimaryOutput == 0 &&outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {mPrimaryOutput = outputDesc; // 设置主音频输出}if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {outputDesc->close(); // 如果是直接输出流则先关闭} else {// 将这个添加到打开的输出描述符列表mOutputs中(SwAudioOutputCollection类型)addOutput(output, outputDesc);// 设置适合当前Source的输出设备,这一部分内容和修改的pfw文件有关setOutputDevices(outputDesc,DeviceVector(supportedDevice),true,0,NULL);}}// 打开访问附加设备所需的输入流以验证 mAvailableInputDevices 列表 for (const auto& inProfile : hwModule->getInputProfiles()) {if (!inProfile->canOpenNewIo()) {ALOGE("Invalid Input profile max open count %u for profile %s",inProfile->maxOpenCount, inProfile->getTagName().c_str());continue;}// 如果当前sink没有相应的设备支持则结束if (!inProfile->hasSupportedDevices()) {ALOGW("Input profile contains no device on module %s", hwModule->getName());continue;}// 选择配置文件中存在的第一个设备支持的设备也是可用输入设备的一部分 const DeviceVector &supportedDevices = inProfile->getSupportedDevices();DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);if (availProfileDevices.isEmpty()) {ALOGE("%s: Input device list is empty!", __FUNCTION__);continue;}// 根据inProfile 得到一个描述符,设置mpClientInterfacesp