转载请标注原文地址:http://blog.csdn.net/uranus_wm/article/details/12748559
前一篇文章介绍了linux alsa初始化的过程,并根据dai_link创建了设备节点,提供给上层应用作为访问接口
这篇文章主要介绍下android soundrecorder从应用层到HAL层的代码框架
后面一片文章重点介绍linux部分,然后说明一下音频数据在内存中的流向和一些相关的调试方法
首先还是看图:
更正说明:tinyalsa访问设备节点应该是/dev/snd/pcmCxDxp, /dev/snd/pcmCxDxc和/dev/snd/controlCx,画图时没有确认造成笔误
这个框图大致把soundrecorder从app到framework到HAL的类图画了出来
有些子类父类继承关系没有表示出来,从soundrecorder到AudioRecord基本就是一条线下来
我也没有详细去看代码,stagefright这一块很庞大,实现了多种mime格式的编解码
音频数据生成文件保存在sd卡中应该是在MPEG4Writer这里完成的,这个没有细看
我们重点看下AudioSystem,AudioPolicyService,AudioFlinger和AudioHardware这块。
以open_record()和get_input()这两个方法为例我们看下这几个类之间的调用关系
从AudioRecord.cpp开始,文件位置:frameworks\base\media\libmedia\AudioRecord.cpp
status_t AudioRecord::openRecord_l(
uint32_t sampleRate,
uint32_t format,
uint32_t channelMask,
int frameCount,
uint32_t flags,
audio_io_handle_t input)
{
status_t status;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
sampleRate, format,
channelMask,
frameCount,
((uint16_t)flags) << 16,
&mSessionId,
&status);
...
}
audio_io_handle_t AudioRecord::getInput_l()
{
mInput = AudioSystem::getInput(mInputSource,
mCblk->sampleRate,
mFormat,
mChannelMask,
(audio_in_acoustics_t)mFlags,
mSessionId);
return mInput;
}
可以看到openRecord_l()直接用AudioSystem这个静态类获取AudioFlinger这个service
const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
{
Mutex::Autolock _l(gLock);
if (gAudioFlinger.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.audio_flinger"));
} while(true);
if (gAudioFlingerClient == NULL) {
gAudioFlingerClient = new AudioFlingerClient();
}
binder->linkToDeath(gAudioFlingerClient);
gAudioFlinger = interface_cast<IAudioFlinger>(binder);
gAudioFlinger->registerClient(gAudioFlingerClient);
}
return gAudioFlinger;
}
这里我碰到个问题,get_audio_flinger从ServiceManager获取audio_flinger service,但是我找了半天没有找到add这个service的地方
找到的朋友可以提醒我一下
另外一个getInput_l(),这是一个通路选择的方法,android也用一个service来维护:AudioPolicyService
这个Service对应一个虚拟的硬件设备,由audio_policy_hal提供接口访问,这么做我估计是为了结构上比较清晰,但是代码看起来就有点绕了
从上面类图来看getInput_l()的调用过程:
从AudioSystem->AudioPolicyService->audio_policy_hal->AudioPolicyManagerBase->AudioPolicyCompatClient->AudioPolicyService->AudioFlinger
文件位置:frameworks\base\media\libmedia\AudioSystem.cpp
audio_io_handle_t AudioSystem::getInput(int inputSource,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics,
int sessionId)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
}
文件位置:frameworks\base\services\audioflinger\AudioPolicyService.cpp
audio_io_handle_t AudioPolicyService::getInput(int inputSource,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics,
int audioSession)
{
if (mpAudioPolicy == NULL) {
return 0;
}
Mutex::Autolock _l(mLock);
audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
format, channels, acoustics);
}
文件位置:hardware\libhardware_legacy\audio\audio_policy_hal.cpp
static audio_io_handle_t ap_get_input(struct audio_policy *pol, int inputSource,
uint32_t sampling_rate,
uint32_t format,
uint32_t channels,
audio_in_acoustics_t acoustics)
{
struct legacy_audio_policy *lap = to_lap(pol);
return lap->apm->getInput(inputSource, sampling_rate, format, channels,