AndroidAudio Native服务之启动流程分析一.docx
- 文档编号:29476982
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:60
- 大小:789.99KB
AndroidAudio Native服务之启动流程分析一.docx
《AndroidAudio Native服务之启动流程分析一.docx》由会员分享,可在线阅读,更多相关《AndroidAudio Native服务之启动流程分析一.docx(60页珍藏版)》请在冰豆网上搜索。
AndroidAudioNative服务之启动流程分析一
Android--AudioNative服务之启动流程分析
(一)
Android中的Audio系统是比较庞大、繁杂的一部分内容,其中会涉及较多的音频编解码、多媒体制式与AndroidAudioHAL设备管理的知识。
随着Android的发展,其所支持的音频设备也变得越来丰富,如扬声器、耳机、听筒等等;这种变化也为Android管理如此丰富的音频设备以及如何正确、合理地切换音频输出提出了更高的要求。
面对如此繁杂的管理要求,我们分析AndroidAudio服务的历程想必也不会轻松。
接下来,我们会以AudioNative服务的启动为入口,以其基本实现流程为重点,抓住代码中的各个关键点,循序渐进地学习AndroidAudio部分的知识,先让我们对它有一个基本的认识和了解;其他的代码细节分析,则需要我们在工作、学习中花费更多的时间去揣摩和思考了。
AndroidAudio部分最主要的Native服务有两个:
AudioFlinger和AudioPolicyService。
AudioFlinger是AndroidAudio系统的核心与中枢。
从上,它为AndroidAudioAPI实现提供具体的功能接口;向下,它与AudioHAL层交互,管理音频设备。
我们知道HAL层是Android对各个物理设备的代码抽象。
HAL层中封装了操作物理设备的接口,通过调用这些接口,我们就可以操作设备,实现我们自己的功能。
又由于AudioFlinger负责管理这些Audio设备,所以我们可以猜测它有一套自己的机制,来区分和管理这些AudioInterface。
同时,AudioFlinger直接与HAL交互,它其中也必然实现了音频数据管理、音频输入输出等功能。
我们也要注意,Android中支持多种音频设备,那么就需要有一位大师来管理音频数据到底从哪种设备输入或者输出;这就牵扯到一种策略制定的问题,它指引音频数据的流向,即与哪种物理设备交互。
既然是制定策略,那这位大师当然就是AudioPolicyService。
基于这种分工,我们可以得出:
AudioFlinger是一个工作繁重的服务,它是Audio策略的功能执行者,直接负责音频数据与音频设备的交互;而策略由AudioPolicyService制定,它负责把控AudioFlinger的工作方向。
有了这些概念,我们再去分析AudioFlinger和AudioPolicyService的服务启动过程。
与之前不同的是,较新的Android系统中,Audio相关的服务都被移动了audioserver进程中。
系统启动的时候,会创建该进程,其中就有AudioFlinger和AudioPolicyService的启动处理:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
intmain(intargc__unused,char**argv)
{
signal(SIGPIPE,SIG_IGN);
booldoLog=(bool)property_get_bool("ro.test_harness",0);
pid_tchildPid;
//FIXMETheadvantageofmakingtheprocesscontainingmedia.logservicetheparentprocessof
//theprocessthatcontainstheotheraudioservices,isthatitallowsustocollectmore
//detailedinformationsuchassignalnumbers,stopandcontinue,resourceusage,etc.
//Butitisalsomorecomplex.Considerreplacingthisbyindependentprocesses,andusing
//binderondeathnotificationinstead.
if(doLog&&(childPid=fork())!
=0){
//media.logservice
//prctl(PR_SET_NAME,(unsignedlong)"media.log",0,0,0);
//unfortunatelypsignoresPR_SET_NAMEforthemainthread,sousethisuglyhack
strcpy(argv[0],"media.log");
sp
:
self());
MediaLogService:
:
instantiate();
ProcessState:
:
self()->startThreadPool();
IPCThreadState:
:
self()->joinThreadPool();
for(;;){
siginfo_tinfo;
intret=waitid(P_PID,childPid,&info,WEXITED|WSTOPPED|WCONTINUED);
if(ret==EINTR){
continue;
}
if(ret<0){
break;
}
charbuffer[32];
constchar*code;
switch(info.si_code){
caseCLD_EXITED:
code="CLD_EXITED";
break;
caseCLD_KILLED:
code="CLD_KILLED";
break;
caseCLD_DUMPED:
code="CLD_DUMPED";
break;
caseCLD_STOPPED:
code="CLD_STOPPED";
break;
caseCLD_TRAPPED:
code="CLD_TRAPPED";
break;
caseCLD_CONTINUED:
code="CLD_CONTINUED";
break;
default:
snprintf(buffer,sizeof(buffer),"unknown(%d)",info.si_code);
code=buffer;
break;
}
structrusageusage;
getrusage(RUSAGE_CHILDREN,&usage);
ALOG(LOG_ERROR,"media.log","pid%dstatus%dcode%suser%ld.%03ldssys%ld.%03lds",
info.si_pid,info.si_status,code,
usage.ru_utime.tv_sec,usage.ru_utime.tv_usec/1000,
usage.ru_stime.tv_sec,usage.ru_stime.tv_usec/1000);
sp
sp
if(binder!
=0){
Vector
binder->dump(-1,args);
}
switch(info.si_code){
caseCLD_EXITED:
caseCLD_KILLED:
caseCLD_DUMPED:
{
ALOG(LOG_INFO,"media.log","exiting");
_exit(0);
//notreached
}
default:
break;
}
}
}else{
//allotherservices
if(doLog){
prctl(PR_SET_PDEATHSIG,SIGKILL);//ifparentmedia.logdiesbeforeme,killmealso
setpgid(0,0);//butifIdiefirst,don'tkillmyparent
}
sp
:
self());
sp
ALOGI("ServiceManager:
%p",sm.get());
AudioFlinger:
:
instantiate();//启动AudioFlinger
AudioPolicyService:
:
instantiate();//启动AudioPolicyService
RadioService:
:
instantiate();
SoundTriggerHwService:
:
instantiate();
ProcessState:
:
self()->startThreadPool();
IPCThreadState:
:
self()->joinThreadPool();
}
}
AudioFlinger:
:
instantiate()、AudioPolicyService:
:
instantiate()的调用就是服务的启动过程,下面我们一一分析。
一、AudioFlinger:
:
instantiate()
AudioFlinger的继承关系声明如下:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
classAudioFlinger:
publicBinderService
AudioFlinger是一个Binder服务的服务端实现,整个AudioFlinger的Binder服务结构如图所示:
继承BnAudioFlinger说明它确实是IAudioFlinger的服务端;而BinderService更像是一个模板工具类,它封装了Binder服务发布、启动的一些方法:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
template
classBinderService
{
public:
staticstatus_tpublish(boolallowIsolated=false){
sp
returnsm->addService(
String16(SERVICE:
:
getServiceName()),
newSERVICE(),allowIsolated);
}
staticvoidpublishAndJoinThreadPool(boolallowIsolated=false){
publish(allowIsolated);
joinThreadPool();
}
staticvoidinstantiate(){publish();}
staticstatus_tshutdown(){returnNO_ERROR;}
private:
staticvoidjoinThreadPool(){
sp
:
self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState:
:
self()->joinThreadPool();
}
};
BinderService:
:
instantiate()内部会创建AudioFlinger服务实例,并通过ServiceManager将其发布到系统中;其中,AudioFlinger服务注册的名称是“media.audio_flinger”。
我们看看IAudioFlinger和AudioFlinger的定义。
首先是IAudioFlinger:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
classIAudioFlinger:
publicIInterface
{
public:
DECLARE_META_INTERFACE(AudioFlinger);
//invariantonexitforallAPIsthatreturnansp<>:
//(returnvalue!
=0)==(*status==NO_ERROR)
/*createanaudiotrackandregistersitwithAudioFlinger.
*returnnullifthetrackcannotbecreated.
*/
virtualsp
virtualsp
//FIXMESurprisingly,format/latencydon'tworkforinputhandles
/*querytheaudiohardwarestate.Thisstateneverchanges,
*andthereforecanbecached.
*/
virtualuint32_tsampleRate(audio_io_handle_tioHandle)const=0;
//reserved;formerlychannelCount()
virtualaudio_format_tformat(audio_io_handle_toutput)const=0;
virtualsize_tframeCount(audio_io_handle_tioHandle)const=0;
//returnestimatedlatencyinmilliseconds
virtualuint32_tlatency(audio_io_handle_toutput)const=0;
/*set/gettheaudiohardwarestate.Thiswillprobablybeusedby
*thepreferencepanel,mostly.
*/
virtualstatus_tsetMasterVolume(floatvalue)=0;
......
virtualboolmasterMute()const=0;
/*set/getstreamtypestate.Thiswillprobablybeusedby
*thepreferencepanel,mostly.
*/
virtualstatus_tsetStreamVolume(audio_stream_type_tstream,floatvalue,
audio_io_handle_toutput)=0;
......
virtualboolstreamMute(audio_stream_type_tstream)const=0;
//setaudiomode
virtualstatus_tsetMode(audio_mode_tmode)=0;
//micmute/state
virtualstatus_tsetMicMute(boolstate)=0;
virtualboolgetMicMute()const=0;
virtualstatus_tsetParameters(audio_io_handle_tioHandle,
constString8&keyValuePairs)=0;
virtualString8getParameters(audio_io_handle_tioHandle,constString8&keys)
const=0;
virtualstatus_topenOutput()=0;
virtualaudio_io_handle_topenDuplicateOutput()=0;
virtualstatus_tcloseOutput(audio_io_handle_toutput)=0;
virtualstatus_tsuspendOutput(audio_io_handle_toutput)=0;
virtualstatus_trestoreOutput(audio_io_handle_toutput)=0;
virtualstatus_topenInput()=0;
virtualstatus_tcloseInput(audio_io_handle_tinput)=0;
......
virtualaudio_module_handle_tloadHwModule(constchar*name)=0;//加载Interface
......
};
IAudioFlinger定义了AudioFlinger服务的基本业务函数。
我们从中可以看到,它定义了加载AudioInterface、音量设置、音频设备属性获取(采样率、帧信息)、打开音频设备输入、输出流等函数。
AudioFlinger是IAudioFlinger的服务端实现,它必定要实现IAudioFlinger中的接口;我们这里只看一些它添加的主要函数定义:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
ThreadBase*checkThread_l(audio_io_handle_tioHandle)const;
PlaybackThread*checkPlaybackThread_l(audio_io_handle_toutput)const;
MixerThread*checkMixerThread_l(audio_io_handle_toutput)const;
RecordThread*checkRecordThread_l(audio_io_handle_tinput)const;
sp
audio_io_handle_t*input,
audio_config_t*config,
audio_devices_tdevice,
constString8&address,
audio_source_tsource,
audio_input_flags_tflags);
sp
audio_io_handle_t*output,
audio_config_t*config,
audio_devices_tdevices,
constString8&address,
audio_output_flags_tflags);
voidcloseOutputFinish(sp
voidcloseInputFinish(sp
//norangecheck,AudioFlinger:
:
mLockheld
boolstreamMute_l(audio_stream_type_tstream)const
{returnmStreamTypes[stream].mute;}
//norangecheck,doesn'tcheckper-threadstreamvolume,AudioFlinger:
:
mLockheld
floatstreamVolume_l(audio_stream_type_tstream)const
{returnmStreamTypes[stream].volume;}
voidioConfigChanged(audio_io_config_eventevent,
constsp
pid_tpid=0);
//Allocateanaudio_unique_id_t.
//Specifictypesareaudio_io_handle_t,audio_session_t,effectID(int),
//audio_module_handle_t,andaudio_patch_handle_t.
//TheyallsharethesameIDspace,butthenamespacesareactuallyindependent
//becausethereareseparateKeyedVectorsforeachkindofID.
//ThereturnvalueiscasttothespecifictypedependingonhowtheIDwillbeused.
//FIXMEThisAPIdoesnothandlerollovertozer
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android Audio Native服务之启动流程分析一 Native 服务 启动 流程 分析