从大的方面来说,Android2.3的音频系统架构与Android2.2相比并没有太多的改变。对2.2的音频架构分析依然适用于2.3,之前很多人已经对这方面进行非常详尽的阐述,这里就不重复了。各模块文件的存放位置有所变更,这点倒是要了解的。
1、有个较大的改进的是引入了mixable audio effects系统。我草草翻了翻代码,应该是opensles实现的。opensles也是2.3新引入的一个音频库,这使得Android的音效变得更强大。但应该会牺牲一些性能,比方说之前Android Framework层固定audio sample rate为44.1khz,对音频流进行resample(AudioResampler.cpp),这使得audio相关线程CPU占用率非常高。
Android给我的感觉就是太照顾开发者了。纵然是底层都有很多地方使用跨平台软件方法,尽量减少HAL,如mixer、equalizer等。mixer还算好,起码在AudioHardwareInterface.h有提供接口供HAL实现,声音特效如equalizer就只是软件实现了。有关HAL的实现参考hardware和device这两个目录的文件;对于audio,android2.3.1-gingerbread/device/samsung/crespo/libaudio是极具价值的,我估计就算移植另一个平台,对于这部分的改动都是非常少的。
2、Android2.2时代还保留opencore多媒体框架,虽然只使用了omx-component,其他默认情况下选择了stagefright。而2.3则完全使用了stagefright,opencore也从android中移除了。有关opencore和stagefright的介绍见:http://blogold.chinaunix.net/u2/61880/showart.php?id=2339481
与opencore同一命运的是alsa-lib。开始时我挺吃惊的,opencore可以用stagefright来替代,但是有什么音频底层库可以替代alsa-lib?看到android2.3.1-gingerbread/device/samsung/crespo/libaudio才释然,原来其中的alsa_pcm.c和alsa_mixer.c实现了一个迷你的alsa-lib。
我想在今后的版本中,Google可能还会继续干同样的事,不断移除一些开源库,而实现自己的一套,显得更简洁。以我个人来说是不大喜欢这个做法。开源库往往功能更强大,接口也标准,现在开发者又要多花稍许时间去熟悉android阉割版的接口--或许多虑了,毕竟开发者很少会去改动framework层;还有就是开源库还会不断更新修正,Google能不能跟上也难说。
2011/4/9
稍微分析一下Audio HAL即audioflinger以下,因为看了网上几篇文章,看起来有些错误或许阐述得不够清晰。
首先AudioFlinger.cpp:
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
mHardwareStatus = AUDIO_HW_IDLE;
mAudioHardware = AudioHardwareInterface::create();
mHardwareStatus = AUDIO_HW_INIT;
if (mAudioHardware->initCheck() == NO_ERROR) {
// open 16-bit output stream for s/w mixer
mMode = AudioSystem::MODE_NORMAL;
setMode(mMode);
setMasterVolume(1.0f);
setMasterMute(false);
} else {
LOGE("Couldn't even initialize the stubbed audio hardware!");
}
#ifdef LVMX
LifeVibes::init();
mLifeVibesClientPid = -1;
#endif
}
可以看到红色部分是通过AudioHardwareInterface.create来创建一个audio hardware接口,我们追溯到AudioHardwareInterface.cpp:
AudioHardwareInterface* AudioHardwareInterface::create()
{
/*
* FIXME: This code needs to instantiate the correct audio device
* interface. For now - we use compile-time switches.
*/
AudioHardwareInterface* hw = 0;
char value[PROPERTY_VALUE_MAX];
#ifdef GENERIC_AUDIO
hw = new AudioHardwareGeneric();
#else
// if running in emulation - use the emulator driver
if (property_get("ro.kernel.qemu", value, 0)) {
LOGD("Running in emulation - using generic audio driver");
hw = new AudioHardwareGeneric();
}
else {
LOGV("Creating Vendor Specific AudioHardware");
hw = createAudioHardware();
}
#endif
if (hw->initCheck() != NO_ERROR) {
LOGW("Using stubbed audio hardware. No sound will be produced.");
delete hw;
hw = new AudioHardwareStub();
}
#ifdef WITH_A2DP
hw = new A2dpAudioInterface(hw);
#endif
#ifdef ENABLE_AUDIO_DUMP
// This code adds a record of buffers in a file to write calls made by AudioFlinger.
// It replaces the current AudioHardwareInterface object by an intermediate one which
// will record buffers in a file (after sending them to hardware) for testing purpose.
// This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
// The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
LOGV("opening PCM dump interface");
hw = new AudioDumpInterface(hw); // replace interface
#endif
return hw;
}
以不同的颜色区分,这里可以支持6种audio接口,分别为:
1、Generic Audio:是Android默认选中的audio hardware,操作底层设备节点是/dev/eac,具体见AudioHardwareGeneric.cpp。我没深入了解这个接口对应的底层驱动。
2、Emulator Audio:也是用Generic Audio。
3、Vendor Specific Audio:厂商自定义audio hardware接口,这是我们的重点,一般来说我们需要实现的就是这个接口,稍后重点分析一下。
4、A2DP Audio:蓝牙音频,没有深入了解。
5、Stubbed Audio:实现方法在AudioHardwareStub.cpp,可以看到大多数函数只是返回一个值,并没有实际操作。它只是保证Android最起码能得到一个audio hardware实例,从而使其启动运行,当然是没有声音的。
6、Dump Audio:详细见注释,主要用来调试上层音频程序,将上层record的声音保存到一个文件中,方便分析。
Vendor Specific Audio
一般我们只需要实现hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h提供的接口就可以了,然后extern "C" AudioHardwareInterface* createAudioHardware(void);方便AudioHardwareInterface* AudioHardwareInterface::create()调用。
以samsung的crespo为例,device/samsung/crespo/libaudio/AudioHardware.cpp,它实现一个AudioHardware的类,其方法也是根据AudioHardwareInterface.h提供的纯虚函数接口来实现的。
extern "C" AudioHardwareInterface* createAudioHardware(void) {
return new AudioHardware();
}
注:如开篇所说,Android2.3已经去掉了alsa-lib,这里其实调用到底层还是alsa-driver,它实现了一个mini alsa-lib,有兴趣的可以看看。当然根据需要也可以用其他的音频驱动架构如OSS或许厂商自己的固件(不开源的,想来Android HAL也是这个目的)。
BoardConfig
板配置选项文件见build/target/board/generic/BoardConfig.mk,默认下定义:
BOARD_USES_GENERIC_AUDIO := true
这是使用Generic Audio接口。
如果要使用vendor specific audio接口,可以修改:
HAVE_HTC_AUDIO_DRIVER := false
BOARD_USES_GENERIC_AUDIO := false
然后添加:
BOARD_USES_VENDOR_SPECIFIC_AUDIO := true
BOARD_USES_VENDOR_SPECIFIC_AUDIO要根据自己板子的Android.mk来定。