Android音频模块启动流程分析
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/tasks
2) 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》这篇文章,他已经写得非常详细清晰。