该小节讲解AudioFlinger启动的过程,作为一个硬件访问服务,其启动过程十分的简单,只需要向系统注册服务就可以了,然后被动的等待其他的客户端来访问。 在上一小节讲解了AudioPolicyService的启动过程,其除了注册本身的服务之外,还调用了AudioFlinger加载厂家提供的so文件。并且open某个output。在这小节的我们除了讲解AudioFlinger服务之外,还会讲解上小节遗留下来的两个问题: a. 注册AudioFlinger服务 b. 被AudioPolicyService调用以打开厂家提供的so文件 c. 被AudioPolicyService调用来open output、创建playback thread
下面是AudioFlinger调用的时序图: 从图中我们可以知道其添加服务只通过BinderService.h中的:
static status_t publish(bool allowIsolated = false) {
sp sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
publish函数,所以前面提到的第一点,a. 注册AudioFlinger服务就已经解决。 我们下面来看看:c. 被AudioPolicyService调用来open output、创建playback thread 。在上小节我们已经分析过,在AudioPolicyManagerBase.cpp文件中:
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
audio_io_handle_t output = mpClientInterface->openOutput(outProfile->mModule->mHandle,&outputDesc->mDevice,&outputDesc->mSamplingRate,&outputDesc->mFormat,&outputDesc->mChannelMask,&outputDesc->mLatency,outputDesc->mFlags);
下面是之前小节讲解相关文件时画的图片,在此拷贝一下: 在讲解b. 被AudioPolicyService调用以打开厂家提供的so文件之前,有如下问题
b.1:加载哪个so文件?文件名是什么?文件从何而来?
名字从/system/etc/audio_policy.conf文件中得到(该文件上小节分析,知道其有model:primary,a2dp,usb,r_submix)
在开放版上执行ls /system/lib/hw/audio*可以看到文件如下:
/system/lib/hw/audio.a2dp.default.so(蓝牙)
/system/lib/hw/audio.primary.default.so
/system/lib/hw/audio.r_submix.default.so
/system/lib/hw/audio.usb.default.so
/system/lib/hw/audio.vr_bee_hidraw.default.so
/system/lib/hw/audio_policy.default.so
可以知道,其与我们的model一一对应。
b.2:改so文件由什么源文件组成?
在上面贴出的框图中(AudioPolicyService边下面),我们可以看到起涉及andio_hw_hal.cpp(硬件抽象层)与AudioHardware.cpp(厂家提供),其最终编译成/system/lib/hw/audio.primary.default.so文件
查看源码hardware\rockchip\audio\legacy_hal\Android.mk:
LOCAL_SRC_FILES := \
AudioHardwareInterface.cpp\
AudioHardware.cpp \
audio_hw_hal.cpp\
alsa_mixer.c\
alsa_route.c\
alsa_pcm.c
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_HARDWARE)
可以知道其会生成文件audio.primary.default.so,其他的so文件也是同理。其中audio_hw_hal.cpp就是厂家提供的。这样我们就知道了so文件的来源,回答了第一个问题。
现在我们反过来看看第一个问题,我们如何去加载这个文件。我们依旧打开AudioPolicyManagerBase.cpp的构造函数:
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
loadAudioPolicyConfig
/*对每一个Modules创建一个HwModule *module = new HwModule(root->name);
然后通过mHwModules.add(module);添加到mHwModules*/
loadHwModules(root);
/*取出所有的module*/
for (size_t i = 0; i mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
在上面我们可以看到,其使用的一个远程调用,该最终会导致AudioFlinger中的loadHwModule,进入AudioFlinger.cpp:
/*一下的name我们暂时都当做primary */
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
loadHwModule_l(name)
/*打开audio.primary.xxx文件,构造audio_hw_device_t结构体*/
int rc = load_audio_interface(name, &dev);
/*AUDIO_HARDWARE_MODULE_ID "audio"
if_name "primary "
及加载audio.primary.xxx文件,不继续深究,有兴趣可以自行了解
*/
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
/*得到so文件之后,调用so文件中的open函数,打开hw_device,这里的hw_device只是一个抽象,没有实质的与硬件打交道*/
/*根据厂家提供的AudioHardware类,获得一个audio_hw_device_t **dev结构体。该结构体最终会保存在AudioFlinger.cpp中的AudioHwDevice类里面*/
rc = audio_hw_device_open(mod, dev);
现在我们已经知道,其如何从系统中得到so文件。在继续深入讲解audio_hw_device_open函数之前我们先做一些总结:
对硬件的封装: AudioFlinger : AudioHwDevice (放入mAudioHwDevs数组中) audio_hw_hal.cpp : audio_hw_device 厂家 : AudioHardware (派生自: AudioHardwareInterface)
AudioHwDevice是对audio_hw_device的封装,
audio_hw_device中函数的实现要通过AudioHardware类对象
下面是硬件封装的框图: AudioFlinger把硬件相关的封装成一个AudioHwDevice。其通过audio_hw_hal.cpp访问硬件,audio_hw_hal.cpp对硬件的操作封装成了audio_hw_device(可以看出AudioHwDevice中包含了audio_hw_hal)。audio_hw_hal.cpp只是一个接口,其需要依赖厂家提供的AudioHardware.cpp。其派生自AudioHardwareInterface,封装成AudioHardware类。
下面我们继续分析audio_hw_device_open(mod, dev);:
/*其会调调用so(audio_hw_hal.cpp)文件中的open函数*/
static inline int audio_hw_device_open(const struct hw_module_t* module,struct audio_hw_device** device)
module->methods->open(module, AUDIO_HARDWARE_INTERFACE,(struct hw_device_t**)device);
上面的函数,最终会调用audio_hw_hal.cpp中的open函数legacy_adev_open:
static int legacy_adev_open(const hw_module_t* module, const char* name,hw_device_t** device)
struct legacy_audio_device *ladev;
/*以下为audio_hw_hal.cpp定义的函数,该些函数都会使用到厂家提供的AudioHardware类*/
ladev->device.init_check = adev_init_check;
ladev->device.set_voice_volume = adev_set_voice_volume;
ladev->device.set_master_volume = adev_set_master_volume;
ladev->device.get_master_volume = adev_get_master_volume;
/*获得厂家提供的AudioHardware,保存在ladev->hwif中*/
ladev->hwif = createAudioHardware();
return new AudioHardwareStub();
这样b的问题我们就解决了,现在只剩下一个问题了:c. 被AudioPolicyService调用来open output、创建playback thread(可以从时序图的A2部分开始看),我们依旧打开AudioPolicyManagerBase.cpp,找到他的构造函数:
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
/*加载解析配置文件*/
loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE)
/*加载从配置文件得到的so(路径)文件*/
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
/*配置文件的每一个modle都会被存放在mHwModules数组中,每个modle中存在一个或者多个ouput,其存放在mOutputProfiles数组中,mOutputProfiles为IOprofile类*/
for (size_t j = 0; j mOutputProfiles.size(); j++)
/*获得一个outProfile结构体 */
const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];
/*根据outProfile结构体获得一个AudioOutputDescriptor描述符*/
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
/*发起远程调用,调用AudioFlinger中的openOutput*/
audio_io_handle_t output = mpClientInterface->openOutput(outProfile->mModule->mHandle,&outputDesc->mDevice,&outputDesc->mSamplingRate,&outputDesc->mFormat,&outputDesc->mChannelMask,&outputDesc->mLatency,outputDesc->mFlags);
我们进入AudioFlinger.cpp找到openOutput函数:
status_t AudioFlinger::openOutput(audio_module_handle_t module,audio_io_handle_t *output, audio_config_t *config,audio_devices_t *devices,const String8& address,uint32_t *latencyMs,audio_output_flags_t flags)
/*该处返回一个线程,显然openOutput_l中会创建一个播放线程*/
sp thread = openOutput_l(module, output, config, *devices, address, flags);
/*获得一个AudioHwDevice,前面提到AudioFlinger对应一个或者多个AudioHwDevice ,每一个AudioHwDevice都对应一个module(so文件),所支持的设备*/
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
status_t status = outHwDev->openOutputStream(&outputStream,*output,devices,flags,config,address.string());
/*根据类型不一样,创建不同的线程*/
thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
/*一般创建该线程较多,表示声音来源多种多样,其会把这些声音混合起来*/
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
mPlaybackThreads.add(*output, thread);
下面我们做一些总结:
/*描述多个modules*/
audio_hw_modules {
primary { //一个modules对应一个厂家提供的so文件
outputs { //一个modules可以有多个output
primary {//一个output表明他的参数(primary代表默认设备)
......
}
spdif_passthrough {
......
}
hdmi {
......
}
}
inputs {//一个modules可以有多个input
primary {
}
}
}
a2dp {
outputs {
a2dp {
......
}
}
}
usb {
outputs {
usb_accessory {
......
}
usb_device {
......
}
}
inputs {
usb_device {
......
}
}
}
r_submix {
outputs {
submix {
......
}
}
inputs {
submix {
......
}
}
}
}
上面是我们之前讲解过的配置文件,其中primary,a2dp,usb,r_submix节点间我们称为modle,在primary中存在一个outputs与inputs结点。
1.在AudioPolicyService中存在一个mHwModules数组,其中有多个mHwModule,每个mHwModule包含.mName,.mOutputProfiles(对应一个output结点配置:IOProfiles类),.mInputProfiles(对应一个或者多个input结点配置:IOProfiles类).等成员。 2.由AudioFlinger实现,根据mHwModules数组中每个mHwModule的名字,打开厂家提供的so文件。然后构建硬件封装的对象mAudioHwDevice放入mAudioHwDevices数组中。mAudioHwDevice中含有audio_hw_device结构体,audio_hw_device又包含了厂家提供的AudioHardWare对象。 3.打开module中的output创建playbackTraad线程(由AudioFlinger实现,但是由AudioPolicyService调用):对每一个module中的每一个output Profiles,如果flog不是特殊的,则调用status_t status = outHwDev->openOutputStream(&outputStream,*output,devices,flags,config,address.string())。然后创建线程thread = new DirectOutputThread,在通过mPlaybackThreads.add(*output, thread)添加到mPlaybackThreads线程数组之中。所以,没一个Output都对应一个线程(猜测input也是如此)。