• AudioPolicyService启动过程(二)


    1. AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface*)

    上篇博客中已经分析如何调用到AudioPolicyManager的构造函数,本篇博客就从AudioPolicyManager的构造函数开始谈起。

    /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

    AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
        :
        mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
        mA2dpSuspended(false),
        mAudioPortGeneration(1),
        mBeaconMuteRefCount(0),
        mBeaconPlayingRefCount(0),
        mBeaconMuted(false),
        mTtsOutputAvailable(false),
        mMasterMono(false),
        mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
        mHasComputedSoundTriggerSupportsConcurrentCapture(false)
    {
        ......
        //保存AudioPolicyClient的对象,这个对象很重要,是获取AudioFlinger接口的一个对象
        mpClientInterface = clientInterface;
    
        //xml文件解析
    #ifdef USE_XML_AUDIO_POLICY_CONF
    
        //如果使用xml来配置的话,则解析audio_policy_configuration.xml文件
        //初始化一个vector audio_stream_type_t类型的stream,用于保存解析到的xml中的stream信息
        mVolumeCurves = new VolumeCurvesCollection();
        AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                                 mDefaultOutputDevice, speakerDrcEnabled,
                                 static_cast<VolumeCurvesCollection *>(mVolumeCurves));
    
        //遍历解析/odm/etc, vendor/etc/audio, vendor/etc/, system/etc这几个目录,如果找到audio_policy_configuration.xml,并解析成功,则break退出
        if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
    #else
        //conf文件的解析
        mVolumeCurves = new StreamDescriptorCollection(); 
        AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                                 mDefaultOutputDevice, speakerDrcEnabled);
                                 
        //加载并解析conf文件
        //#define AUDIO_POLICY_VENDOR_CONFIG_FILE   "/vendor/etc/audio_policy.conf"
        //#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
        if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
                (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
    #endif
            ALOGE("could not load audio policy configuration file, setting defaults");
            config.setDefault();
        }
        ........
        for (size_t i = 0; i < mHwModules.size(); i++) {
            //1.加载Moudle
            mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
            .......
            //2.对output的处理
            for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
            {
                //获取每个module中的outProfile
                const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];
    
                ......
                //得到支持设备的类型
                audio_devices_t profileType = outProfile->getSupportedDevicesType();
                
                //将输出IOProfile封装为SwAudioOutputDescriptor对象
                //创建一个outputDesc对象,该对象中描述了音频的一些参数,如采样率、通道数以及格式
                sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
                                                                                     mpClientInterface);
                ......
    
                outputDesc->mDevice = profileType;
                audio_config_t config = AUDIO_CONFIG_INITIALIZER;
                config.sample_rate = outputDesc->mSamplingRate;
                config.channel_mask = outputDesc->mChannelMask;
                config.format = outputDesc->mFormat;
                audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
                
                //将调用audioFlinger中的openOutput,打开output,在AudioFlinger中创建PlaybackTread线程,并返回线程的id
                status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
                                                                &output,
                                                                &config,
                                                                &outputDesc->mDevice,
                                                                address,
                                                                &outputDesc->mLatency,
                                                                outputDesc->mFlags);
    
                    .......
                    //将输出描述符对象SwAudioOutputDescriptor及创建的PlaybackTread线程id以键值对形式保存
                    addOutput(output, outputDesc);
                    setOutputDevice(outputDesc,
                                    outputDesc->mDevice,
                                    true,
                                    0,
                                    NULL,
                                    address.string());
                }
            }
            // open input streams needed to access attached devices to validate
            // mAvailableInputDevices list
            //3.input的处理
            for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
            {
                //获取每个module中的inProfile
                const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
    
                // chose first device present in profile's SupportedDevices also part of
                // inputDeviceTypes
                //获取所支持的设备
                audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes);
    
                //将输入IOProfile封装成AudioInputDescriptor对象
                sp<AudioInputDescriptor> inputDesc =
                        new AudioInputDescriptor(inProfile);
    
                inputDesc->mDevice = profileType;
                audio_config_t config = AUDIO_CONFIG_INITIALIZER;
                config.sample_rate = inputDesc->mSamplingRate;
                config.channel_mask = inputDesc->mChannelMask;
                config.format = inputDesc->mFormat;
                audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
                
                //将调用AudioFlinger中的openInput,在audioFlinger中创建recordThread线程,并返回其id
                status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
                                                               &input,
                                                               &config,
                                                               &inputDesc->mDevice,
                                                               address,
                                                               AUDIO_SOURCE_MIC,
                                                               AUDIO_INPUT_FLAG_NONE);
    
                if (status == NO_ERROR) {
                    const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
                    for (size_t k = 0; k  < supportedDevices.size(); k++) {
                        ssize_t index =  mAvailableInputDevices.indexOf(supportedDevices[k]);
                        // give a valid ID to an attached device once confirmed it is reachable
                        if (index >= 0) {
                            sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
                            if (!devDesc->isAttached()) {
                                devDesc->attach(mHwModules[i]);
                                devDesc->importAudioPort(inProfile, true);
                            }
                        }
                    }
                    mpClientInterface->closeInput(input);
                } 
            }
        }
        .........
    
    }

     2. mpClientInterface->函数(...)

    2.1 mpClientInterface->loadHwModule(...)

    这个地方会调用到AudioFlinger中的loadHwModule函数,为什么?

    mpClientInterface是由clientInterface赋值的。

    看一下函数的调用流程:

    mAudioPolicyClient = new AudioPolicyClient(this)------->createAudioPolicyManager(mAudioPolicyClient)-------->new AudioPolicyManager(clientInterface),因此mpClientInterface->loadHwModule实际上是调用了AudioPolicyClient类中的成员函数。

    /frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp

    audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
    {
        sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
        ......
        return af->loadHwModule(name);
    }

    从上面的代码可以看出,最终调用了AudioFlinger中的loadHwModule函数。在AudioFlinger的博客中再重点分析此函数。

    2.2 mpClientInterface->openOutput(...)

    /frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp

    status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
                                                               audio_io_handle_t *output,
                                                               audio_config_t *config,
                                                               audio_devices_t *devices,
                                                               const String8& address,
                                                               uint32_t *latencyMs,
                                                               audio_output_flags_t flags)
    {
        sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
        ......
        return af->openOutput(module, output, config, devices, address, latencyMs, flags);
    }

    最终调用到了AudioFlinger中的openOutput函数

    2.3 mpClientInterface->openInput(...)

    status_t AudioPolicyService::AudioPolicyClient::openInput(audio_module_handle_t module,
                                                              audio_io_handle_t *input,
                                                              audio_config_t *config,
                                                              audio_devices_t *device,
                                                              const String8& address,
                                                              audio_source_t source,
                                                              audio_input_flags_t flags)
    {
        sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
        ......
        return af->openInput(module, input, config, device, address, source, flags);
    }

    最终调用到AudioFlinger中的openInput函数。

    3. XML配置文件解析

    deserializeAudioPolicyXmlConfig函数用于解析xml文件,在该函数中,会依次解析/odm/etc/, /vendor/etc/audio/, /vendor/etc/, /system/etc这几个目录,如果找到audio_policy_configuration.xml文件,并解析成功,则break退出。

    在android中,该文件的默认存放路径如下:

    /frameworks/av/services/audiopolicy/config/audio_policy_configuration.xml

    但是我们一般不会使用android自带的xml文件,而是使用厂家提供的。我们以SDM429W平台为例,厂家提供的xml文件路径如下:

    /hardware/qcom/audio/configs/msm8937/audio_policy_configuration.xml

    经编译后,被放到了目录:

    /vendor/etc/audio/audio_policy_configuration.xml

    /vendor/etc/audio_policy_configuraiton.xml

     在代码中,通过宏USE_XML_AUDIO_POLICY_CONF来决定使用audio_policy.conf文件还是audio_policy_configuraiton.xml文件。该宏定义在:

    /hardware/qcom/audio/configs/msm8937/msm8937.mk中

    USE_XML_AUDIO_POLICY_CONF := 1

    此时言归正传,回到函数 deserializeAudioPolicyXmlConfig

    /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

    #define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
    #define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
    
    
    #ifdef USE_XML_AUDIO_POLICY_CONF
    // Treblized audio policy xml config will be located in /odm/etc or /vendor/etc.
    static const char *kConfigLocationList[] =
            {"/odm/etc", "/vendor/audio/etc","/vendor/etc", "/system/etc"};
    static const int kConfigLocationListSize =
            (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
    
    static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
        char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
        status_t ret;
    
        for (int i = 0; i < kConfigLocationListSize; i++) {
            PolicySerializer serializer;
            snprintf(audioPolicyXmlConfigFile,
                     sizeof(audioPolicyXmlConfigFile),
                     "%s/%s",
                     kConfigLocationList[i],
                     AUDIO_POLICY_XML_CONFIG_FILE_NAME);
            ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
            if (ret == NO_ERROR) {
                break;
            }
        }
        return ret;
    }
    #endif
    deserialize函数是解析XML的关键,不过这个函数非常复杂。对于这个函数的解析过程,可参考https://blog.csdn.net/qq_33750826/article/details/97757590
  • 相关阅读:
    Android中fragment之间和Activity的传值、切换
    IOS后台运行浅析
    IOS7 Background Fetch后台应用程序刷新
    IOS 7四种后台机制
    注册苹果开发者账号的详细步骤
    iOS关闭键盘的两种简单方法
    iOS5 切换中文键盘时覆盖输入框的完美解决方案
    IOS开发之NSLog使用技巧
    IOS总结 静变量static、全局变量extern、局部变量、实例变量
    高德地图初始化 ios
  • 原文地址:https://www.cnblogs.com/-glb/p/14257042.html
Copyright © 2020-2023  润新知