android_audio架构全分析,Android深入浅出之AudioFlinger分析

一 目的

本文承接Audio第一部分的AudioTrack,通过AudioTrack作为AF(AudioFlinger)的客户端,来看看AF是如何完成工作的。

在AT(AudioTrack)中,我们涉及到的都是流程方面的事务,而不是系统Audio策略上的内容。WHY?因为AT是AF的客户端,而AF是Android系统中Audio管理的中枢。AT我们分析的是按流程方法,那么以AT为切入点的话,AF的分析也应该是流程分析了。

对于分析AT来说,只要能把它的调用顺序(也就是流程说清楚就可以了),但是对于AF的话,简单的分析调用流程 我自己感觉是不够的。因为我发现手机上的声音交互和管理是一件比较复杂的事情。举个简单例子,当听music的时候来电话了,声音处理会怎样?

虽然在Android中,还有一个叫AudioPolicyService的(APS)东西,但是它最终都会调用到AF中去,因为AF实际创建并管理了硬件设备。所以,针对Android声音策略上的分析,我会单独在以后来分析。

二 从AT切入到AF

直接从头看代码是没法掌握AF的主干的,必须要有一个切入点,也就是用一个正常的调用流程来分析AF的处理流程。先看看AF的产生吧,这个C/S架构的服务者是如何产生的呢?

2.1 AudioFlinger的诞生

AF是一个服务,这个就不用我多说了吧?代码在

framework/base/media/mediaserver/Main_mediaServer.cpp中。

intmain(intargc,char** argv)

{

sp proc(ProcessState::self());

sp sm = defaultServiceManager();

....

AudioFlinger::instantiate();--->AF的实例化

AudioPolicyService::instantiate();--->APS的实例化

....

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

}

哇塞,看来这个程序的负担很重啊。没想到。为何AF,APS要和MediaService和CameraService都放到一个篮子里?

看看AF的实例化静态函数,在framework/base/libs/audioFlinger/audioFlinger.cpp中

voidAudioFlinger::instantiate() {

defaultServiceManager()->addService( //把AF实例加入系统服务

String16("media.audio_flinger"),newAudioFlinger());

}

再来看看它的构造函数是什么做的。

AudioFlinger::AudioFlinger()

: BnAudioFlinger(),//初始化基类

mAudioHardware(0),//audio硬件的HAL对象

mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)

{

mHardwareStatus = AUDIO_HW_IDLE;

//创建代表Audio硬件的HAL对象

mAudioHardware = AudioHardwareInterface::create();

mHardwareStatus = AUDIO_HW_INIT;

if(mAudioHardware->initCheck() == NO_ERROR) {

setMode(AudioSystem::MODE_NORMAL);

//设置系统的声音模式等,其实就是设置硬件的模式

setMasterVolume(1.0f);

setMasterMute(false);

}

}

AF中经常有setXXX的函数,到底是干什么的呢?我们看看setMode函数。

status_t AudioFlinger::setMode(intmode)

{

mHardwareStatus = AUDIO_HW_SET_MODE;

status_t ret = mAudioHardware->setMode(mode);//设置硬件的模式

mHardwareStatus = AUDIO_HW_IDLE;

returnret;

}

当然,setXXX还有些别的东西,但基本上都会涉及到硬件对象。我们暂且不管它。等分析到Audio策略再说。

好了,Android系统启动的时候,看来AF也准备好硬件了。不过,创建硬件对象就代表我们可以播放了吗?

2.2 AT调用AF的流程

我这里简单的把AT调用AF的流程列一下,待会按这个顺序分析AF的工作方式。

--参加AudioTrack分析的4.1节

1. 创建

AudioTrack* lpTrack =newAudioTrack();

lpTrack->set(...);

这个就进入到C++的AT了。下面是AT的set函数

audio_io_handle_t output =

AudioSystem::getOutput((AudioSystem::stream_type)streamType,

sampleRate, format, channels, (AudioSystem::output_flags)flags);

status_t status = createTrack(streamType, sampleRate, format, channelCount,

frameCount, flags, sharedBuffer, output);

----->creatTrack会和AF打交道。我们看看createTrack重要语句

constsp& audioFlinger = AudioSystem::get_audio_flinger();

//下面很重要,调用AF的createTrack获得一个IAudioTrack对象

sp track = audioFlinger->createTrack();

sp cblk = track->getCblk();//获取共享内存的管理结构

总结一下创建的流程,AT调用AF的createTrack获得一个IAudioTrack对象,然后从这个对象中获得共享内存的对象。

2. start和write

看看AT的start,估计就是调用IAudioTrack的start吧?

voidAudioTrack::start()

{

//果然啊...

status_t status = mAudioTrack->start();

}

那write呢?我们之前讲了,AT就是从共享buffer中:

l         Lock缓存

l         写缓存

l         Unlock缓存

注意,这里的Lock和Unlock是有问题的,什么问题呢?待会我们再说

按这种方式的话,那么AF一定是有一个线程在那也是:

l         Lock,

l         读缓存,写硬件

l         Unlock

总之,我们知道了AT的调用AF的流程了。下面一个一个看。

2.3 AF流程

1 createTrack

sp AudioFlinger::createTrack(

pid_t pid,//AT的pid号

intstreamType,//MUSIC,流类型

uint32_t sampleRate,//8000 采样率

intformat,//PCM_16类型

intchannelCount,//2,双声道

intframeCount,//需要创建的buffer可包含的帧数

uint32_t flags,

constsp& sharedBuffer,//AT传入的共享buffer,这里为空

intoutput,//这个是从AuidoSystem获得的对应MUSIC流类型的索引

status_t *status)

{

sp<:track> track;

sp trackHandle;

sp client;

wp wclient;

status_t lStatus;

{

Mutex::Autolock _l(mLock);

//根据output句柄,获得线程?

PlaybackThread *thread = checkPlaybackThread_l(output);

//看看这个进程是不是已经是AF的客户了

//这里说明一下,由于是C/S架构,那么作为服务端的AF肯定有地方保存作为C的AT的信息

//那么,AF是根据pid作为客户端的唯一标示的

//mClients是一个类似map的数据组织结构

wclient = mClients.valueFor(pid);

if(wclient != NULL) {

} else{

//如果还没有这个客户信息,就创建一个,并加入到map中去

client = newClient(this, pid);

mClients.add(pid, client);

}

//从刚才找到的那个线程对象中创建一个track

track = thread->createTrack_l(client, streamType, sampleRate, format,

channelCount, frameCount, sharedBuffer, &lStatus);

}

//喔,还有一个trackHandle,而且返回到AF端的是这个trackHandle对象

trackHandle = newTrackHandle(track);

returntrackHandle;

}

这个AF函数中,突然冒出来了很多新类型的数据结构。说实话,我刚开始接触的时候,大脑因为常接触到这些眼生的东西而死机!大家先不要拘泥于这些东西,我会一一分析到的。

先进入到checkPlaybackThread_l看看。

AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(intoutput)const

{

PlaybackThread *thread = NULL;

//看到这种indexOfKey的东西,应该立即能想到:

//喔,这可能是一个map之类的东西,根据key能找到实际的value

if(mPlaybackThreads.indexOfKey(output) >=0) {

thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();

}

//这个函数的意思是根据output值,从一堆线程中找到对应的那个线程

returnthread;

}

看到这里很疑惑啊:

l         AF的构造函数中没有创建线程,只创建了一个audio的HAL对象

l         如果AT是AF的第一个客户的话,我们刚才的调用流程里边,也没看到哪有创建线程的地方呀。

l         output是个什么玩意儿?为什么会根据它作为key来找线程呢?

看来,我们得去Output的来源那看看了。

我们知道,output的来源是由AT的set函数得到的:如下:

audio_io_handle_t output = AudioSystem::getOutput(

(AudioSystem::stream_type)streamType, //MUSIC类型

sampleRate, //8000

format, //PCM_16

channels, //2两个声道

(AudioSystem::output_flags)flags//0

);

上面这几个参数后续不再提示了,大家知道这些值都是由AT做为切入点传进去的

然后它在调用AT自己的createTrack,最终把这个output值传递到AF了。其中audio_io_handle_t类型就是一个int类型。

//叫handle啊?好像linux下这种叫法的很少,难道又是受MS的影响吗?

我们进到AudioSystem::getOutput看看。注意,大家想想这是系统的第一次调用,而且发生在AudioTrack那个进程里边。AudioSystem的位置在framework/base/media/libmedia/AudioSystem.cpp中

audio_io_handle_t AudioSystem::getOutput(stream_type stream,

uint32_t samplingRate,

uint32_t format,

uint32_t channels,

output_flags flags)

{

audio_io_handle_t output = 0;

if((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ==0&&

((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) ||

channels != AudioSystem::CHANNEL_OUT_MONO ||

(samplingRate != 8000&& samplingRate !=16000))) {

Mutex::Autolock _l(gLock);

//根据我们的参数,我们会走到这个里边来

//喔,又是从map中找到stream=music的output。可惜啊,我们是第一次进来

//output一定是0

output = AudioSystem::gStreamOutputMap.valueFor(stream);

}

if(output ==0) {

//我晕,又到AudioPolicyService(APS)

//由它去getOutput

constsp& aps = AudioSystem::get_audio_policy_service();

output = aps->getOutput(stream, samplingRate, format, channels, flags);

if((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ==0) {

Mutex::Autolock _l(gLock);

//如果取到output了,再把output加入到AudioSystem维护的这个map中去

//说白了,就是保存一些信息吗。免得下次又这么麻烦去骚扰APS!

AudioSystem::gStreamOutputMap.add(stream, output);

}

}

returnoutput;

}

怎么办?需要到APS中才能找到output的信息?

没办法,硬着头皮进去吧。那先得看看APS是如何创建的。不过这个刚才已经说了,是和AF一块在那个Main_mediaService.cpp中实例化的。

位置在framework/base/lib/libaudioflinger/ AudioPolicyService.cpp中

AudioPolicyService::AudioPolicyService()

: BnAudioPolicyService() , mpPolicyManager(NULL)

{

// 下面两个线程以后再说

mTonePlaybackThread = newAudioCommandThread(String8(""));

mAudioCommandThread = newAudioCommandThread(String8("ApmCommandThread"));

#if(defined GENERIC_AUDI

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值