Android 7.0 Audio: AudioPolicyService和他的码农APM

AudioPolicyService负责音频策略处理,包括根据手机的各种状态和器件的存在、插拔状态、用户使能状态,给不同的audio stream选择不同的输入输出设备,控制不同设备的增益等。

代码层面,该类则主要是维护3个线程looper,通过不同的辅助类,向client提供服务。

 

AudioPolicyService的相关类关系如下,

 Android 7.0 Audio: AudioPolicyService和他的码农APM_第1张图片

 

同AudioFlinger,APS在audioServer里启动。AudioPolicyService有两种实现方案,由USE_LEGACY_AUDIO_POLICY控制,

如果是LEGACY方法,使用一个ops函数集操作接口,类似驱动模块的写法,在AudioPolicyClientImplLegacy.cpp实现所有函数功能,这些函数实际上就是对AF的功能封装,在其构造函数中初始,这种方法以及废弃,我们就不具体分析。

另外一种方法,在AudioPolicyService的onFirstRef中,创建了如下几个重要的线程和实例。

void AudioPolicyService::onFirstRef()

{

 

        // 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);

 

        mAudioPolicyClient = new AudioPolicyClient(this);

        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);

 

spaudioPolicyEffects = new AudioPolicyEffects();

}

 

 

AudioCommandThread是AudioPolicyService的内部类,继承自Thread,在其onFirstRef启动线程,

void AudioPolicyService::AudioCommandThread::onFirstRef()

{

    run(mName.string(), ANDROID_PRIORITY_AUDIO);

}

 

 

它对外提供各种接口,如startOutputCommand,向其队列发消息,如START_OUTPUT,然后由其threadLoop处理这些消息,这样的好处是避免消息拥塞,避免调用栈过长,阻塞系统等,代码结构清晰,系统耦合性也低。

bool AudioPolicyService::AudioCommandThread::threadLoop()

{

    nsecs_t waitTime = -1;

 

    mLock.lock();

    while (!exitPending())

    {

        sp svc;

        while (!mAudioCommands.isEmpty() && !exitPending()) {

            nsecs_t curTime = systemTime();

            // commands are sorted by increasing time stamp: execute them from index 0 and up

            if (mAudioCommands[0]->mTime <= curTime) {

                sp command = mAudioCommands[0];

                mAudioCommands.removeAt(0);

                mLastCommand = command;

 

                switch (command->mCommand) {

                case START_OUTPUT: {

                    StartOutputData *data = (StartOutputData *)command->mParam.get();

                    ALOGV("AudioCommandThread() processing start output %d",

                            data->mIO);

                    svc = mService.promote();

                    if (svc == 0) {

                        command->mStatus = UNKNOWN_ERROR;

                        break;

                    }

                    mLock.unlock();

                    command->mStatus = svc->doStartOutput(data->mIO, data->mStream, data->mSession);

                    mLock.lock();

 

threadLoop主要调用ToneGenerator,AudioSystem,AF,还有自身的功能实现函数AudioPolicyIntefaceImpl来完成相应的消息处理。实际上,APII也只是封装了对APM(AudioPolicyManager)的调用而已。

 

 

AudioPolicyService还有一个NotificationClient子类,提供接口registerClient让客户端注册,貌似只有AS一个客户,和AF类似。

AudioSystem.cpp(frameworks\av\media\libmedia):       af->registerClient(afc);

AudioSystem.cpp(frameworks\av\media\libmedia):       ap->registerClient(apc);

AudioSystem.cpp(frameworks\av\media\libmedia):           af->registerClient(afc);

I

void AudioPolicyService::registerClient(const sp& client)

{

 

        sp notificationClient = new NotificationClient(this,

                                                                           client,

                                                                           uid);

        ALOGV("registerClient() client %p, uid %d", client.get(), uid);

 

        mNotificationClients.add(uid, notificationClient);

 

}

 

 

 

AudioPolicyClient : publicAudioPolicyClientInterface,代码实现在AudioPolicyClientImpl.cpp,这个类也只是一个功能封装类,调用了AF,AudioSystem,APS的接口。在APS的构造函数中作为APM的构造参数传入,所以它是APM调用AF,AudioSystem,APS的桥梁。

        mAudioPolicyClient = new AudioPolicyClient(this);

        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);

 

 

 

对于APM类,

APS创建了它的实例,自己的文件不怎么使用它,但通过looper,使用APII来调用APM的功能。我们先分析这些表面的调用关系,之后要思考其背后的设计意图。

 

通过后面分析APM,会发现前面围绕APS讲了一堆的策略、架构、汇报关系的东西,其实真正干活的只有APM,它就是APS架构里面的码农,干了个体力活还不显眼,毕竟大家喜欢看架构和策略方面的东西。

 

APM还是有些技能的,首先他有几个工具,他把他们交给AudioPolicyConfig去管理(在AudioPolicyConfig.h中),

HwModuleCollection &mHwModules;

DeviceVector &mAvailableOutputDevices;

    DeviceVector &mAvailableInputDevices;

    sp &mDefaultOutputDevices;

    VolumeCurvesCollection *mVolumeCurves;

 

在APM的构造函数里,

首先从/system/etc/audio_policy_configuration.xml加载相关配置信息,并序列化、以及初始,不再使用/system/etc/audio_policy.conf文件,这里会用到PolicySerializer和EngineInstance。

后面就是围绕AudioPolicyConfig管理的几个类,根据配置文件进行初始化,如,代码太多,不一一细化。

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) {

 

1.加载配置信息

#ifdef USE_XML_AUDIO_POLICY_CONF

    mVolumeCurves = new VolumeCurvesCollection();

    AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,

                             mDefaultOutputDevice, speakerDrcEnabled,

                             static_cast(mVolumeCurves));

    PolicySerializer serializer;

    if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {

        config.setDefault();

}

#endif

 

    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();

mEngine = engineInstance->queryInterface();

    mEngine->setObserver(this);

    status_t status = mEngine->initCheck();

2. 加载配置文件里的模块,并一一初始化

    for (size_t i = 0; i < mHwModules.size(); i++) {

        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());

  

  2.1  打开输出流设备

        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)

        {

            const sp outProfile = mHwModules[i]->mOutputProfiles[j];

            sp outputDesc = new SwAudioOutputDescriptor(outProfile,

                                                                                 mpClientInterface);

            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;

            status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),

                                                            &output,

                                                            &config,

                                                            &outputDesc->mDevice,

                                                            address,

                                                            &outputDesc->mLatency,

                                                            outputDesc->mFlags);

                addOutput(output, outputDesc);

                setOutputDevice(outputDesc,

                                outputDesc->mDevice,

                                true,

                                0,

                                NULL,

                                address.string());

    }

  2.2  打开输入流设备

        for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)

        {

            const sp inProfile = mHwModules[i]->mInputProfiles[j];

            sp inputDesc =

                    new AudioInputDescriptor(inProfile);

            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);

    }

 

3.设置输入输出状态和设备使能专题

    // make sure all attached devices have been allocated a unique ID

    for (size_t i = 0; i  < mAvailableOutputDevices.size();) {

        if (!mAvailableOutputDevices[i]->isAttached()) {

            ALOGW("Output 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++;

    }

 

    updateDevicesAndOutputs();

}

 

一份完整的audio_policy_configuration.xml如下,可对照这个配置分解来分析APM的构造过程,

   

 

   

   

       

       

           

                Earpiece

                Speaker

                Telephony Tx

                Built-In Mic

                Built-In Back Mic

                FM Tuner

                Telephony Rx

           

            Speaker

           

               

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                        flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW">

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

                

                        flags="AUDIO_OUTPUT_FLAG_DIRECT">

                   

                             samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000" channelMasks="dynamic"/>

               

               

                        flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM">

                    

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

               

               

                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>

                    

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

               

               

                   

                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX">

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>

               

 

               

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

               

               

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1"/>

               

               

                   

                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>

               

            

 

           

               

               

                  

                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>

               

               

                    

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>

               

               

                    

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>

               

               

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>

               

               

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>

               

               

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>

               

               

                   

                             samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000" channelMasks="dynamic"/>

               

               

                    

                             samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000" channelMasks="dynamic"/>

               

               

                   

                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>

               

 

               

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

               

               

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

               

               

                   

                             samplingRates="48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>

               

               

                   

                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

               

               

                   

                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>

               

               

                   

                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>

               

           

           

           

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

               

                       sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>

               

                       sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>

                

                       sources="primary output"/>

               

                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>

                

                       sources="voice_tx"/>

               

                       sources="Wired Headset Mic,BT SCO Headset Mic,FM Tuner,Telephony Rx"/>

               

                       sources="Built-In Mic,Built-In Back Mic"/>

               

                       sources="Telephony Rx"/>

           

 

       

 

       

       

 

       

       

 

       

       

 

   

   

 

   

 

   

   

 

   

 

 

 

APM类的继承关系:

AudioPolicyInterface—AudioPolicyManagerBase—AudioPolicyManagerDefault

AudioPolicyInterface—AudioPolicyManager-- AudioPolicyManagerCustom

AudioPolicyClientInterface-- 

 

 

AudioPolicyManagerBase

getDeviceForStrategy  根据路由策略,按一定优先顺序选取不同的设备类型,对应用来讲,不用关心手机的各种状态和器件的存在、插拔状态、用户使能状态。

mAvailableOutputDevices表明了当前device能支持哪些输出设备,在AudioPolicyManagerBase构造时初始,在setDeviceConnectionState中更新。

mAvailableInputDevices表明了当前device能支持哪些输入设备,在defaultAudioPolicyConfig时初始,在setDeviceConnectionState中更新。

 

代码里还有这样一套APM,应该是legacy的,被废弃了,

AudioPolicyManager.cpp(hardware\qcom\audio\policy_hal)

AudioPolicyInterface.h (hardware\libhardware_legacy\include\hardware_legacy)

Audio_policy_hal.cpp (hardware\libhardware_legacy\audio)

AudioPolicyManagerCustom

 

 

APS里各种元素的对应关系(一对一或一对多的关系):

System -- audiointerfaces

Audiointerface -- outputs

Output -- devices

Stream Type -- PlaybackThread --device

 

APS的概述分析就到这里,细节部分要结合具体的调用流程分析。





Android 7.0 Audio: AudioPolicyService和他的码农APM_第2张图片




如果觉得我的文章对您有用,请打赏。您的支持是对我莫大的认可


你可能感兴趣的:(Android,audio)