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

inputDesc =new AudioInputDescriptor(inProfile, mpClientInterface);audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;// 这里最终调用到AudioFlinger的openIntput打开输入流status_t status = inputDesc->open(nullptr,availProfileDevices.itemAt(0),AUDIO_SOURCE_MIC,AUDIO_INPUT_FLAG_NONE,&input);if (status != NO_ERROR) {ALOGW("Cannot open input stream for device %s on hw module %s",availProfileDevices.toString().c_str(),hwModule->getName());continue;}for (const auto &device : availProfileDevices) {// 一旦确认连接的设备可以访问,就为它提供一个有效的 ID if (!device->isAttached()) {device->attach(hwModule);device->importAudioPortAndPickAudioProfile(inProfile, true);mAvailableInputDevices.add(device);if (newDevices) newDevices->add(device);setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);}}inputDesc->close();}}}
上面代码中提到在中打开了输入和输出设备,下面是输出流打开流程包括线程的创建:
上图会返回::中根据加载的 。
接下来继续分析输入流的打开流程以及线程的创建:
上面讲输入和输出的线程创建已经分析完毕,现在我们的系统中已经存在了一些播放线程了,后面就是一个应用如果通过开始播放音频该怎么将这段音频对应到相应的线程中去的问题 。
整个第一节音频服务初始化到这里结束,音频服务启动之后加载相应的音频库,扫描了配置文件中的一些模块和连接的外设,并打开这些外设创建了相应的工作线程,比如最常用的线程和录音的,现在整个音频系统已经启动,剩下的就是其他应用等访问音频服务的过程 。
二、 的创建流程
前面分析的时候没有进行详细的分析,作为音频后期统筹管理的模块,是如何将策略加载进去的,以及后面设备切换的时候怎么进行修改,这些内容在这一节进行分析
2.1 音频策略加载
在前面1.2节中的方法中涉及到了的创建,接着这个内容进一步详细分析:
音频策略加载的时候有一个比较重要的函数,这个函数里面的,代码如下:
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(){auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {// 确保名称唯一性以防止重复 LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),[&volumeConfig](const auto &volumeGroup) {return volumeConfig.name == volumeGroup.second->getName(); }),"group name %s defined twice, review the configuration",volumeConfig.name.c_str());// 表示当前VolumeGroup还没有被加载过,开始创建加载加载sp volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,volumeConfig.indexMax);volumeGroups[volumeGroup->getId()] = volumeGroup;for (auto &configCurve : volumeConfig.volumeCurves) {device_category deviceCat = DEVICE_CATEGORY_SPEAKER;if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());continue;}sp curve = new VolumeCurve(deviceCat);for (auto &point : configCurve.curvePoints) {curve->add({point.index, point.attenuationInMb});}volumeGroup->add(curve);}return volumeGroup;};auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {for (const auto &attr : group.attributesVect) {strategy->addAttributes({group.stream, volumeGroup->getId(), attr});volumeGroup->addSupportedAttributes(attr);}};auto checkStreamForGroups = [](auto streamType, const auto &volumeGroups) {const auto &iter = std::find_if(std::begin(volumeGroups), std::end(volumeGroups),[&streamType](const auto &volumeGroup) {const auto& streams = volumeGroup.second->getStreamTypes();return std::find(std::begin(streams), std::end(streams), streamType) !=std::end(streams);});return iter != end(volumeGroups);};// 前面三个lambda表达式后面会用到,实际是从这里开始的// 这里开始进行解析,最终会解析出来策略、标准、标准类型以及音量组四个内容// struct Config {//float version;//ProductStrategies productStrategies;//Criteria criteria;//CriterionTypes criterionTypes;//VolumeGroups volumeGroups;// };auto result = engineConfig::parse();if (result.parsedConfig == nullptr) { // 如果上面没有解析成功表示没有找到配置,所以使用默认的配置ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);engineConfig::Config config = gDefaultEngineConfig;android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);result = {std::make_unique