Android 7.0 Audio: AudioPolicyService和他的碼農APM

AudioPolicyService負責音頻策略處理,包括根據手機的各種狀態和器件的存在、插拔狀態、用戶使能狀態,給不同的audio stream選擇不同的輸入輸出設備,控制不同設備的增益等。

代碼層面,該類則主要是維護3個線程looper,通過不同的輔助類,向client提供服務。

 

AudioPolicyService的相關類關係如下,

 

 

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

 

sp<AudioPolicyEffects>audioPolicyEffects = 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<AudioPolicyService> 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<AudioCommand> 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<IAudioPolicyServiceClient>& client)

{

 

        sp<NotificationClient> 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<DeviceDescriptor> &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<VolumeCurvesCollection *>(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<AudioPolicyManagerInterface>();

    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<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];

            sp<SwAudioOutputDescriptor> 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<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];

            sp<AudioInputDescriptor> 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的構造過程,

<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">

    <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->

 

    <!-- Global configuration Decalaration -->

<globalConfiguration speaker_drc_enabled="true"/>

    <modules>

        <!-- Primary Audio HAL -->

        <module name="primary" halVersion="2.0">

            <attachedDevices>

                <item>Earpiece</item>

                <item>Speaker</item>

                <item>Telephony Tx</item>

                <item>Built-In Mic</item>

                <item>Built-In Back Mic</item>

                <item>FM Tuner</item>

                <item>Telephony Rx</item>

            </attachedDevices>

            <defaultOutputDevice>Speaker</defaultOutputDevice>

            <mixPorts>

                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_PRIMARY">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

                <mixPort name="raw" role="source"

                        flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

                <mixPort name="deep_buffer" role="source"

                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

                <mixPort name="multichannel" role="source"

                        flags="AUDIO_OUTPUT_FLAG_DIRECT">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

                <mixPort name="direct_pcm" role="source"

                        flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"

                             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"/>

                </mixPort>

                <mixPort name="compressed_offload" role="source"

                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">

                    <profile name="" format="AUDIO_FORMAT_MP3"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_FLAC"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_ALAC"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_APE"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_LC"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_WMA"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_WMA_PRO"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_VORBIS"

                             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"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_LC"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V1"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V2"

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

                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>

                </mixPort>

                <mixPort name="voice_tx" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

                <mixPort name="voip_rx" role="source"

                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

 

                <mixPort name="primary input" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

                </mixPort>

                <mixPort name="surround_sound" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

                             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"/>

                </mixPort>

                <mixPort name="voice_rx" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </mixPort>

            </mixPorts>

 

            <devicePorts>

                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->

                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">

                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="BT SCO All" type="AUDIO_DEVICE_OUT_ALL_SCO" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

 

                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

                </devicePort>

                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

                </devicePort>

                <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

                             samplingRates="48000"

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>

                </devicePort>

                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>

                </devicePort>

                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

                <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">

                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

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

                </devicePort>

            </devicePorts>

            <!-- route declaration, i.e. list all available sources for a given sink -->

            <routes>

                <route type="mix" sink="Earpiece"

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

                <route type="mix" sink="Speaker"

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

                <route type="mix" sink="Wired Headset"

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

                <route type="mix" sink="Wired Headphones"

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

                <route type="mix" sink="Line"

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

                <route type="mix" sink="HDMI"

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

                <route type="mix" sink="Proxy"

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

                <route type="mix" sink="FM"

                       sources="primary output"/>

                <route type="mix" sink="BT SCO All"

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

                <route type="mix" sink="Telephony Tx"

                       sources="voice_tx"/>

                <route type="mix" sink="primary input"

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

                <route type="mix" sink="surround_sound"

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

                <route type="mix" sink="voice_rx"

                       sources="Telephony Rx"/>

            </routes>

 

        </module>

 

        <!-- A2dp Audio HAL -->

        <xi:include href="a2dp_audio_policy_configuration.xml"/>

 

        <!-- Usb Audio HAL -->

        <xi:include href="usb_audio_policy_configuration.xml"/>

 

        <!-- Remote Submix Audio HAL -->

        <xi:include href="r_submix_audio_policy_configuration.xml"/>

 

    </modules>

    <!-- End of Modules section -->

 

    <!-- Volume section -->

 

    <xi:include href="audio_policy_volumes.xml"/>

    <xi:include href="default_volume_tables.xml"/>

 

    <!-- End of Volume section -->

 

</audioPolicyConfiguration>

 

 

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的概述分析就到這裏,細節部分要結合具體的調用流程分析。









如果覺得我的文章對您有用,請打賞。您的支持是對我莫大的認可


發佈了96 篇原創文章 · 獲贊 40 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章