Qidi 06.08.2017 (Markdown & Haroopad)
注意:本文基于 Android 7.0 进行分析。
1) 设备开机,系统启动时将执行 /system/etc/init/audioserver.rc ,运行 /system/bin/ 目录下的 audioserver 服务。audioserver.rc 内容如下:
service audioserver /system/bin/audioserver class main user audioserver # media gid needed for /dev/fm (radio ) and for /data/misc/media (tee) group audio radio camera drmpc inet media mediarm net_bt net_bt_admin net_bw_acct ioprio rt 4 writepid /dev/cpuset/forground/tasks /dev/stune/foreground/tasks2) audioserver 进程会依次对 AudioFlinger、AudioPolicyService、RadioService、SoundTriggerHwService 进行实例化。如果设备集成了杜比音效,杜比音效的内存管理服务 DolbyMemoryService 也会在这里进行实例化。frameworks/av/media/audioserver/main_audioserver.cpp 的 main() 函数关键代码如下:
int main(int argc __unused, char** argv) { .... if (doLog && (child = fork()) != 0) { // 启动 Log 线程 .... } else { .... AudioFlinger::instantiate(); // AudioFlinger 的实例化先于AudioPolicyService AudioPolicyService::instantiate(); RadioService::instantiate(); #ifdef DOLBY_ENABLE DolbyMemoryService::instantiate(); #endif SoundTriggerHwService::instantiate(); .... } }3) AudioFlinger 开始构造并调用 AudioFlinger::onFirstRef() 方法进行初始化,这个过程中会初始化 MIXER 和 DUPLICATING 类型的 playback 线程被创建后的等待延时时间,然后创建 PatchPanel 对象,并将系统的音频模式设置为 AUDIO_MODE_NORMAL。相关代码位于 frameworks/av/services/audioflinger/audioflinger.cpp。
4) AudioPolicyService 开始构造并调用 AudioPolicyService::onFirstRef() 方法进行初始化,这个过程中会创建 AudioPolicyManager 对象。Android 7.0系统为了兼容老版本系统中的函数调用,提供了 2 种创建 AudioPolicyManager 的方式,默认情况下,我们是使用的新的创建方式。frameworks/av/services/audiopolicy/AudioPolicyService.cpp 的 AudioPolicyService::onFirstRef() 函数关键代码如下:
void AudioPolicyService::onFirstRef() { { .... // start tone playback thread mTonePlaybackThread = new AudioCommandThread(String8("ApmTone", this)); // start audio commands thread mTonePlaybackThread = new AudioCommandThread(String8("ApmAudio", this)); // start output activity command thread mTonePlaybackThread = new AudioCommandThread(String8("ApmOutput", this)); #ifdef USE_LEGACY_AUDIO_POLICY // 使用老版本的 audio policy 初始化方式 .... #else // 使用最新的 audio policy 初始化方式 ALOGI("AudioPolicyService CSTOR in new mode"); mAudioPolicyClient = new AudioPolicyClient(this); mAudioPolicyManager =createAudioPolicyManager(mAudioPolicyClient); // 创建 AudioPolicyManager 对象 .... #endif } // load audio processing modules sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects(); { .... mAudioPolicyEffects = audioPolicyEffects; } }4.1) createAudioPolicyManager() 函数的实现位于 frameworks/av/services/audiopolicy/manager/AudioPolicyFactory.cpp文件中。查看源码后我们会发现它实际上是直接调用了 AudioPolicyManager 的构造函数。代码如下:
namespace android { extern "C" AndroidPolicyInterface* createAudioPolicyManager( AudioPolicyInterface *clientInterface) { return new AudioPolicyManager(clientInterface); // 调用 AudioPolicyManager 的构造函数创建对象 } }4.2) AudioPolicyManager 的构造函数将解析音频策略配置文件,从而获取到设备所支持的音频设备信息(包括设备是否支持 Offload、Direct 模式输出,各输入输出 profile 所支持的采样率、通道数、数据格式等),加载全部 HwModule,为之创建所有非 direct 输出类型的 outputStream 和所有 inputStream,并创建相应的 playbackThread 或 recordThread 线程。需要注意的是,Android 7.0上的音频策略配置文件开始使用 XML 格式,其文件名为 audio_policy_configuration.xml,而在之前的版本上音频策略配置文件为 audio_policy.conf。frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp 中 AudioPolicyManager 构造函数的关键代码如下:
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) : #ifdef AUDIO_POLICY_TEST Thread(false), #endif //AUDIO_POLICY_TEST mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mA2dpSuspended(false), mAudioPortGeneration(1), mBeaconMuteRefCount(0), mBeaconPlayingRefCount(0), mBeaconMuted(false), mTtsOutputAvailable(false), mMasterMono(false) { .... #ifdef USE_XML_AUDIO_POLICY_CONF // 设备使用的配置文件为 audio_policy_configuration.xml mVolumeCurves = new VolumeCurvesCollection(); AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice, speakerDrcEnabled, static_cast<VolumeCurvesCollection *>(mVolumeCurves)); PolicySerializer serializer; // 解析 xml 配置文件,将设备支持的音频输出设备保存在 mAvailableOutputDevices 变量中, // 将设备支持的音频输入设备保存在 mAvailableInputDevices 变量中,将设备的默认音频输出 // 设备保存在 mDefaultOutputDevice 变量中。 if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) { #else // 设备使用的配置文件为 audio_policy.conf mVolumeCurves = new StreamDescriptorCollection(); AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice, speakerDrcEnabled); // 优先解析 vendor 目录下的 conf 配置文件,然后解析 device 目录下的 conf 配置文件。 // 将设备支持的音频输出设备保存在 mAvailableOutputDevices 变量中, // 将设备支持的音频输入设备保存在 mAvailableInputDevices 变量中,将设备的默认音频输出 // 设备保存在 mDefaultOutputDevice 变量中。 if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) { #endif ALOGE("could not load audio policy configuration file, setting defaults"); config.setDefault(); } // must be done after reading the policy (since conditionned by Speaker Drc Enabling) mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled); // 设置音量调节曲线 .... // 依次加载 HwModule 并打开其所含 profile 的 outputStream 及 inputStream for (size_t i = 0; i < mHwModules.size(); i++) { mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName()); if (mHwModules[i]->mHandle == 0) { ALOGW("could not open HW module %s", mHwModules[i]->getName()); 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 // 打开当前 module 下所有非 direct 类型 profile 的 outputStream for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; .... // 如果当前操作的 module.profile 是 direct 类型,则不为其打开 outputStream if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { continue; } .... // 获取采样率、通道数、数据格式等各音频参数 sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, mpClientInterface); const DeviceVector &supportedDevices = outProfile->getSupportedDevices(); const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType); String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress : String8(""); 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; // 为当前 module.profile 打开对应的 outputStream 并创建 playbackThread 线程 status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(), &output, &config, &outputDesc->mDevice, address, &outputDesc->mLatency, outputDesc->mFlags); .... } // open input streams needed to access attached devices to validate // mAvailableInputDevices list // 打开当前 module 下所有 profile 的 inputStream 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); 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; // 为当前 module.profile 打开对应的 inputStream 并创建 recordThread 线程 status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(), &input, &config, &inputDesc->mDevice, address, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE); .... } } .... updateDevicesAndOutputs(); // 更新系统缓存的音频输出设备信息 .... }5) 至此,Android 系统中音频模块的启动就完成了,两大关键音频组件 AudioFlinger 和 AudioPolicyService 均已创建并运行,设备所支持的音频输入输出硬件信息也已经被 AudioPolicyManager 所解析。如果此时发生了插入耳机等操作,则 AudioPolicyService 将会接收到底层通知并把 Audio Route 切换到 WiredHeadset 等响应配置;如果此时在 APP 发生了播放音乐的操作,则 AudioFlinger 会接收到上层通知并创建相应 Track。
6) 之后设备开始播放声音时,音频数据将从 AudioTrack 传输到 AudioFlinger,再传输到 Audio HAL,直到最终写入硬件,这也是一个冗长复杂的过程。想了解这部分流程的朋友们,我推荐你们阅读 zyuanyun 写的《Android 音频系统:从 AudioTrack 到 AudioFlinger》这篇文章,他已经写得非常详细清晰。