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的概述分析就到这里,细节部分要结合具体的调用流程分析。
如果觉得我的文章对您有用,请打赏。您的支持是对我莫大的认可!