audioPolicyServer解析

        研究Android多媒体已经有一段时间,特撰写关于android多媒体系列的文章,为了加深理解和认识,也希望能为想了解多媒体的同学提供帮助。

      AudioPolicyServer看名字也能猜到应该和策略相关的一些功能,不错AudioPolicyServer正是音频策略的制定者,管理和运营所有android手机上的音频硬件,我们可以通过adb shell进入手机终端,进入cd /dev/snd/ 目录查看当前手机都有那些音频设备,会发现手机上的音频设备会很多。播放音乐,来电,响铃究竟是开启的是那个音频设备呢,某种Stream类型的音频应对应什么设备,AudioPolicyServer是怎样维护现有系统中的音频设备,各个设备之间如何切换,调节音量时调节是哪个设备呢,带着这些疑问来看看AudioPolicyServer是如何实现的。


 一 首先让我们来看看与AudioPolicyServer相关联类的组织关系


1.1  AudioPolicyServer类继承IAudioPolicyServer类,为其他应用程序提供audio策略相关的功能,对外的唯一接口。

1.2   AudioPolicyManagerCustom或者AudioPolicyManagerBase,有些厂商会定制这个类,继承AudioPolicyManager,AudioPolicyManager是一个非常重要的一个类,策略的具体制定是由此类实施的,AudioPolicyServer调用AudioPolicyManager的实例来实现各种策略的功能

1.3   AudioPolicyClient类继承AudioPolicyClientInterface,AudioPolicyClient类负责与AudioFlinger的交互,AudioPolicyServer是策略的制定者,但策略的具体实施是由AudioFlinger类完成,AudioPolicyServer确定具体策略时,交给AudioPolicyClient,AudioPolicyClient在传达给AudioFlinger,AudioPolicyClient类似一个信使或者中介者。

1.4   EngineInstance类,主要为获取Engine实例提供接口,Engine类规定了具体策略相关的规定,并通过ManagerInterfaceImpl向AudioPolicyManager提供信息。


二 AudioPolicyServer初始化过程

       AudioPolicyServer是在开机的时候被初始化的,源码位于

frameworks/av/media/mediaserver/main_mediaserver.cpp 中

int main(int argc __unused, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
   ......................
        InitializeIcuOrDie();
        sp proc(ProcessState::self());
        sp sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        //首先初始化AudioFlinger
        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        ResourceManagerService::instantiate();
        CameraService::instantiate();
        //在初始化AudioPolicyService
        AudioPolicyService::instantiate();
        SoundTriggerHwService::instantiate();
        RadioService::instantiate();
#ifdef AUDIO_LISTEN_ENABLED
        ALOGI("ListenService instantiated");
        ListenService::instantiate();
#endif
        registerExtensions();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
}

AudioPolicyService::instantiate(), instantiate是父类BinderService的方法,实现在frameworks/native/include/binder/Binder.h,static void instantiate() { publish(); },直接调用 publish,BinderService是个模板类, publish函数中直接new 一个server实例并托管到servermanger中。接下来我们分析一下具体的初始化过程,见时序图

audioPolicyServer解析_第1张图片

2.1 AudioPolicyService::AudioPolicyService()构造函数


AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
      mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
{
}

AudioPolicyService构造函数初始化几个变量,其他的就没做啥,当AudioPolicyService第一次别引用时触发AudioPolicyService::onFirstRef()函数,且只有第一次被引用才会被调用,以后的调用中不会在触发此函数。

void AudioPolicyService::onFirstRef()
{
    char value[PROPERTY_VALUE_MAX];
    const struct hw_module_t *module;
    int forced_val;
    int rc;

    {
        Mutex::Autolock _l(mLock);

        // start tone playback thread
        mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);

#ifdef USE_LEGACY_AUDIO_POLICY
        ALOGI("AudioPolicyService CSTOR in legacy mode");

        /* instantiate the audio policy manager */
        rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
        if (rc) {
            return;
        }
        rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
        ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
        if (rc) {
            return;
        }

        rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
                                                   &mpAudioPolicy);
        ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
        if (rc) {
            return;
        }

        rc = mpAudioPolicy->init_check(mpAudioPolicy);
        ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
        if (rc) {
            return;
        }
        ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
#else
        ALOGI("AudioPolicyService CSTOR in new mode");
       //创建AudioPolicyClient和AudioPolicyManager实例
        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
#endif
    }
    // load audio processing modules
    spaudioPolicyEffects = new AudioPolicyEffects();
    {
        Mutex::Autolock _l(mLock);
        mAudioPolicyEffects = audioPolicyEffects;
    }
}

AudioPolicyService首先创建了三个线程, mTonePlaybackThread用于音调的播放,mAudioCommandThread音频参数的传达,比如上层经常会掉用一些setParamter的方法,最终都会通过mAudioCommandThread线程传达下去mOutputCommandThread与通路相关一些操作。比如新建一个通路,释放一个通路等。宏USE_LEGACY_AUDIO_POLICY是否开启老版本的策略,这是为了兼容老的策略版本,本文是基于android5.0以上版本分析的,所以不去在看,即此宏没有被开启。

2.2  mAudioPolicyClient = new AudioPolicyClient(this);此处新建 AudioPolicyClient实例并将AudioPolicyService实例传给AudioPolicyClient,保存在mAudioPolicyClient变量中。 AudioPolicyClient类定义在frameworks/av/services/audiopolicy/service/AudioPolicyService.h,AudioPolicyClient具体实现在frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp文件中。

2.3   mAudioPolicyManager =createAudioPolicyManager(mAudioPolicyClient);创建AudioPolicyManager实例对象,保存在变量中mAudioPolicyManager,参数mAudioPolicyClient将AudioPolicyClient的实例传送到AudioPolicyManager实例中,这样AudioPolicyManager就可以直接调用AudioPolicyClient的功能,createAudioPolicyManager是一个c函数,部分厂家可能会对此修改,但不论厂家如何修改都会继承AudioPolicyManager类来做一些微调。

2.4   创建AudioPolicyManager实例时,AudioPolicyManager构造函数做了重要的工作,也是AudioPolicyService初始化的核心。

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
    :
#ifdef AUDIO_POLICY_TEST
    Thread(false),
#endif //AUDIO_POLICY_TEST
    mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
    mA2dpSuspended(false),
    mSpeakerDrcEnabled(false),
    mAudioPortGeneration(1),
    mBeaconMuteRefCount(0),
    mBeaconPlayingRefCount(0),
    mBeaconMuted(false),
    mTtsOutputAvailable(false)
{
    //获取EngineInstance实例
    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
    if (!engineInstance) {
        ALOGE("%s:  Could not get an instance of policy engine", __FUNCTION__);
        return;
    }
    // 通过EngineInstance实例查询到AudioPolicyManagerInterface的实例
    // mEngine是ManagerInterfaceImpl类的实例
    mEngine = engineInstance->queryInterface();
    if (mEngine == NULL) {
        ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
        return;
    }
    mEngine->setObserver(this);
    status_t status = mEngine->initCheck();
    ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);

    mUidCached = getuid();
    mpClientInterface = clientInterface;
    //设置默认输出设备为speaker
    mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
    //加载解析audio_policy.conf文件
    if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
                 mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
                 mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
        if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE,
                                  mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
                                  mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
            ALOGE("could not load audio policy configuration file, setting defaults");
            defaultAudioPolicyConfig();
        }
    }
    // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices

    // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
    mEngine->initializeVolumeCurves(mSpeakerDrcEnabled);

    // open all output streams needed to access attached devices
    audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
    audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
    for (size_t i = 0; i < mHwModules.size(); i++) {
        //通过mpClientInterface加载相应HwModule相应的库文件,mpClientInterface最终会调用
        //audioflinger加载库文件
        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
        if (mHwModules[i]->mHandle == 0) {
            ALOGW("could not open HW module %s", mHwModules[i]->mName);
            continue;
        }
        // open all output streams needed to access attached devices
        // except for direct output streams that are only opened when they are actually
        // required by an app.
        // This also validates mAvailableOutputDevices list
        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
        {
            //
            const sp outProfile = mHwModules[i]->mOutputProfiles[j];

            if (outProfile->mSupportedDevices.isEmpty()) {
                ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
                continue;
            }
            if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
                mTtsOutputAvailable = true;
            }

            if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                continue;
            }
            audio_devices_t profileType = outProfile->mSupportedDevices.types();
            if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
                profileType = mDefaultOutputDevice->type();
            } else {
                // chose first device present in mSupportedDevices also part of
                // outputDeviceTypes
                for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
                    profileType = outProfile->mSupportedDevices[k]->type();
                    if ((profileType & outputDeviceTypes) != 0) {
                        break;
                    }
                }
            }
            if ((profileType & outputDeviceTypes) == 0) {
                continue;
            }
            sp 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;
            //audiopolicyserver在加载audio_policy.conf之后,为各个hw module建立了几个软件通路,
            //各个通路需要和audioflinger建立联系,每一个通路都有audio_io_handle_t与audioflinger建立对应关系
            //APS通过ModuleHandle和audio_io_handle_t可以再audioflinger中找到对应的实体,每个audio_io_handle_t
            //都对应一个PlaybackThread
            status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
                                                            &output,
                                                            &config,
                                                            &outputDesc->mDevice,
                                                            String8(""),
                                                            &outputDesc->mLatency,
                                                            outputDesc->mFlags);

            if (status != NO_ERROR) {
                ALOGW("Cannot open output stream for device %08x on hw module %s",
                      outputDesc->mDevice,
                      mHwModules[i]->mName);
            } else {
                outputDesc->mSamplingRate = config.sample_rate;
                outputDesc->mChannelMask = config.channel_mask;
                outputDesc->mFormat = config.format;

                for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) {
                    audio_devices_t type = outProfile->mSupportedDevices[k]->type();
                    ssize_t index =
                            mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
                    // give a valid ID to an attached device once confirmed it is reachable
                    if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
                        mAvailableOutputDevices[index]->attach(mHwModules[i]);
                    }
                }
                if (mPrimaryOutput == 0 &&
                        outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
                    mPrimaryOutput = outputDesc;
                }
                addOutput(output, outputDesc);
                setOutputDevice(outputDesc,
                                outputDesc->mDevice,
                                true);
            }
        }
        // open input streams needed to access attached devices to validate
        // mAvailableInputDevices list
        for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
        {
            const sp inProfile = mHwModules[i]->mInputProfiles[j];

            if (inProfile->mSupportedDevices.isEmpty()) {
                ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName);
                continue;
            }
            // chose first device present in mSupportedDevices also part of
            // inputDeviceTypes
            audio_devices_t profileType = AUDIO_DEVICE_NONE;
            for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
                profileType = inProfile->mSupportedDevices[k]->type();
                if (profileType & inputDeviceTypes) {
                    break;
                }
            }
            if ((profileType & inputDeviceTypes) == 0) {
                continue;
            }
            sp inputDesc = new AudioInputDescriptor(inProfile);

            inputDesc->mInputSource = AUDIO_SOURCE_MIC;
            inputDesc->mDevice = profileType;

            // find the address
            DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType);
            //   the inputs vector must be of size 1, but we don't want to crash here
            String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress
                    : String8("");
            ALOGV("  for input device 0x%x using address %s", profileType, address.string());
            ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!");

            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;
            status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
                                                           &input,
                                                           &config,
                                                           &inputDesc->mDevice,
                                                           address,
                                                           AUDIO_SOURCE_MIC,
                                                           AUDIO_INPUT_FLAG_NONE);

            if (status == NO_ERROR) {
                for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) {
                    audio_devices_t type = inProfile->mSupportedDevices[k]->type();
                    ssize_t index =
                            mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                    // give a valid ID to an attached device once confirmed it is reachable
                    if (index >= 0) {
                        sp devDesc = mAvailableInputDevices[index];
                        if (!devDesc->isAttached()) {
                            devDesc->attach(mHwModules[i]);
                            devDesc->importAudioPort(inProfile);
                        }
                    }
                }
                mpClientInterface->closeInput(input);
            } else {
                ALOGW("Cannot open input stream for device %08x on hw module %s",
                      inputDesc->mDevice,
                      mHwModules[i]->mName);
            }
        }
    }
    // make sure all attached devices have been allocated a unique ID
    for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
        if (!mAvailableOutputDevices[i]->isAttached()) {
            ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->type());
            mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
            continue;
        }
        // The device is now validated and can be appended to the available devices of the engine
        mEngine->setDeviceConnectionState(mAvailableOutputDevices[i],
                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
        i++;
    }
    for (size_t i = 0; i  < mAvailableInputDevices.size();) {
        if (!mAvailableInputDevices[i]->isAttached()) {
            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
            mAvailableInputDevices.remove(mAvailableInputDevices[i]);
            continue;
        }
        // The device is now validated and can be appended to the available devices of the engine
        mEngine->setDeviceConnectionState(mAvailableInputDevices[i],
                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
        i++;
    }
    // make sure default device is reachable
    if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
    }

    ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
   //通路打通之后更新路由策略对应的默认设备
    updateDevicesAndOutputs();

#ifdef AUDIO_POLICY_TEST
    if (mPrimaryOutput != 0) {
        AudioParameter outputCmd = AudioParameter();
        outputCmd.addInt(String8("set_id"), 0);
        mpClientInterface->setParameters(mPrimaryOutput->mIoHandle, outputCmd.toString());

        mTestDevice = AUDIO_DEVICE_OUT_SPEAKER;
        mTestSamplingRate = 44100;
        mTestFormat = AUDIO_FORMAT_PCM_16_BIT;
        mTestChannels =  AUDIO_CHANNEL_OUT_STEREO;
        mTestLatencyMs = 0;
        mCurOutput = 0;
        mDirectOutput = false;
        for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
            mTestOutputs[i] = 0;
        }

        const size_t SIZE = 256;
        char buffer[SIZE];
        snprintf(buffer, SIZE, "AudioPolicyManagerTest");
        run(buffer, ANDROID_PRIORITY_AUDIO);
    }
#endif //AUDIO_POLICY_TEST
}
2.5 通过 audio_policy::EngineInstance::getInstance()方法获取 EngineInstance实例,实现比较简单,engineInstance是个静态的实例,不需要new。EngineInstance这个类中包含了Engine一个静态实例,通过queryInterface获取Engine的代理ManagerInterfaceImpl

2.6 通过engineInstance这个静态实例进一步查询获取AudioPolicyManagerInterface类的一个实例,AudioPolicyManager类中变量mEngine是ManagerInterfaceImpl的实例,他是Engine的代理,AudioPolicyManager通过mEngine查询获取当前设备信息。路由策略的规则都在是Engine类中定义的

Engine::Engine()
    : mManagerInterface(this),
      mPhoneState(AUDIO_MODE_NORMAL),
      mApmObserver(NULL)
{
    for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
        mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
    }
}
Engine类的实例也是静态构建的,类被加载前就已经被创建了,各个路由策略的mForceUse初始值AUDIO_POLICY_FORCE_NONE,没有强制使用某个设备
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
    switch(usage) {
    case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
        if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
            config != AUDIO_POLICY_FORCE_NONE) {
            ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_MEDIA:
        if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
            ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_RECORD:
        if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_NONE) {
            ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
            return BAD_VALUE;
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_DOCK:
        if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
            config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
            config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
            config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
            config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
            ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_SYSTEM:
        if (config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
            ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
        }
        mForceUse[usage] = config;
        break;
    case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
        if (config != AUDIO_POLICY_FORCE_NONE &&
            config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
            ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
        }
        mForceUse[usage] = config;
        break;
    default:
        ALOGW("setForceUse() invalid usage %d", usage);
        break;
    }
    return NO_ERROR;
}
应用层在切换设备的时候就会调用Engine::setForceUse,这个方法规定了各种场景下可以切换的设备, Engine中还有其他的方法getStrategyForStream,getStrategyForUsage,getDeviceForStrategy等等,其中getDeviceForStrategy就会用到mForceUse的信息,综合各种情景,最终输出具体设备。Engine的作用就是将各种流,各种应用场景转换成对应的路由策略,在由路由策略输出具体的设备信息,最终完成设备的选择

2.7 加载audio_policy.conf配置信息,audio_policy.conf文件中是预先根据平台特性设置好的音频信息,优先加载 /vendor/etc/audio_policy.conf,如果没有就加载/system/etc/audio_policy.conf

audioPolicyServer解析_第2张图片

图(audio hw modules)

从图中看到音频硬件模块是如何划分的:primary硬件模块为出厂时就具备的音频设备,比如,speaker ,mic等等,a2db模块就是蓝牙设备,usb模块是通过usb输出音频信息的设备,r_submix模块为远程音频设备。各个硬件模块又细分输入输出通路,输入输出通路根据使用的硬件设备,支持的音频格式,采样率等信息,在规划具体的通路,比如primary硬件模块输出通路就规划了九条具体的通路,分析支持不同的应用场景。


AudioPolicyManager根据图(audio hw modules)的组织关系,将各个硬件模块封装成HwModule对象,将具体的通道封装成IoProfile对象,根据组织关系存储起来 。 audioPolicyServer这里所建立的通路都是控制通路,非数据通路。

2.8 完成audio_policy.conf信息的解析之后,就要进入实质性加载硬件设备的操作,根据mHwModules中保存硬件模块,分别加载图(audio hw modules)中primary,a2db,usb,r_submix设备,audiopolicyserver只下达加载操作,这些设备的具体加载过程由AudioFlinger完成,加载成功之后AudioFlinger会返回 audio_module_handle_t ,audiopolicyserver后期会通过这个module handle与audioflinger交互信息。

       2.9 每个硬件模块包含多个输入输出通道,硬件模组加载成功之后,就要打通每条通道,并为每条通道设置默认device。mpClientInterface->openOutput ,mpClientInterface->openInput分别开启输出输入通路,这些通路的具体建立也是在audioflinger中完成的,通路建立完成之后,audioflinger返回audio_io_handle_t给audioPolicyServer,每一个io handle都对应一个thread,要么是PlaybackThread,要么是RecordThread,audioPolicyServer可以根据io handle找到具体thread实例

以上操作完成之后AudioPolicyManager调用updateDevicesAndOutputs更新每个路由策略的设备信息,保存在数组变量mDeviceForStrategy,后面的操作可直接获取当前路由策略下的具体device,完成路由选择工作。至此audioPolicyServer的初始化过程分析完毕。


你可能感兴趣的:(audioPolicyServer解析)