(config),static_cast>(ret == NO_ERROR ? 0 : 1)};} ...ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement); // 这里是解析的时候跳过的无效策略数engineConfig::VolumeGroup defaultVolumeConfig;engineConfig::VolumeGroup defaultSystemVolumeConfig;// 循环解析所有的音量组for (auto &volumeConfig : result.parsedConfig->volumeGroups) {// 保存未在配置中定义的流的默认音量配置 讲music和patch作为未定义流类型的默认配置if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {defaultVolumeConfig = volumeConfig;}if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {defaultSystemVolumeConfig = volumeConfig;}// 这里调用上面第一个lamabda表达式// 这里定义的mVolumeGroups是一个map容器,其中second是VolumeGroup指针,定义在VolumeGroup.h中// 这里调用这个lambda表达式是为了讲volumeConfig中包含的volumeGroups解析到mVolumeGroups中loadVolumeConfig(mVolumeGroups, volumeConfig);}// 循环遍历所有的音频策略for (auto& strategyConfig : result.parsedConfig->productStrategies) {sp strategy = new ProductStrategy(strategyConfig.name);for (const auto &group : strategyConfig.attributesGroups) {// 查找该策略是否有相应的音量组const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),[&group](const auto &volumeGroup) {return group.volumeGroup == volumeGroup.second->getName(); });sp volumeGroup = nullptr;// 如果没有为此策略提供音量组,则使用音乐音量组配置创建一个新的音量组(视为默认设置) if (iter == end(mVolumeGroups)) {engineConfig::VolumeGroup volumeConfig;if (group.stream >= AUDIO_STREAM_PUBLIC_CNT) {volumeConfig = defaultSystemVolumeConfig;} else {volumeConfig = defaultVolumeConfig;}ALOGW("%s: No configuration of %s found, using default volume configuration", __FUNCTION__, group.volumeGroup.c_str());volumeConfig.name = group.volumeGroup;volumeGroup = loadVolumeConfig(mVolumeGroups, volumeConfig);} else {volumeGroup = iter->second;}if (group.stream != AUDIO_STREAM_DEFAULT) {// 可以将旧流一次分配给卷组 LOG_ALWAYS_FATAL_IF(checkStreamForGroups(group.stream, mVolumeGroups),"stream %s already assigned to a volume group, ""review the configuration", toString(group.stream).c_str());volumeGroup->addSupportedStream(group.stream);}// 为策略添加相应的属性addSupportedAttributesToGroup(group, volumeGroup, strategy);}// 将新创建的strategy保存到mProductStrategies中并分配一个单独的IDproduct_strategy_t strategyId = strategy->getId();mProductStrategies[strategyId] = strategy;}mProductStrategies.initialize();return result;}
三、 应用播放音频
应用播放音频是通过创建的方式进行播放的,每一个音频流对应着一个的实例,每个会在创建的时候注册到中,由将所有的进行混合再传入到HAL中进行播放 。
通过前面的分析流程知道了启动时加载了系统支持的所有音频接口,并且打开了默认的音频输出,并且为该输出创建了一个播放线程,同时为该线程分配了一个全局唯一的值,任何Track想要发声都需要去查找相应的值找到对应的播放线程才能最终将音频数据传输到HAL层进行播放,大致的播放框图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img--84)(./TN1.11.7870音频文档/应用播放流程.png)]
3.1 应用创建Track流程 调用::接口传入音频参数获取最小缓冲区大小,调用到HAL层判断当前硬件是否支持该种类型的音频播放,如果不支持后续也不会创建Track 。new ::::play
需要注意的是音频播放的时候有两种模式:
模式下需要先调用write方法,后调用play方法;模式下先调用play方法,后调用write方法 。
在这里创建共享内存的时候会用到获取的值最终创建缓冲区大小,这一步最终会进入到HAL层使用应用的采样率等一些参数来判断当前硬件是否支持该种类型的音频播放 。