android volume设置 代码分析
android volume设置 代码分析。
volume设置,跳过binder部分(binder请独立理解)
没有采用深度优先的方法,容易绕来绕去,就不知道再看什么了。
采用不断透调的方法讲解,一步一步从上层直逼底层,从整体上了解音量设置过程。
透调中有点难度的调用最后讲解。
一、jni部分
android_media_audiosystem.cpp-----framework/base/core/jni/
[cpp]view plaincopy
android_media_audiosystem_setstreamvolumeindex(jnienv*env,
jobjectthiz,
jintstream,
jintindex,
jintdevice)
{
returncheck_audiosystem_command(
audiosystem::setstreamvolumeindex(static_cast(stream),
index,
(audio_devices_t)device));
} 对于函数的行惨,不必过多考虑,是上层java传给的。
关键的参数:
index:音量值;
device:如下列举了一笑部分
[cpp]view plaincopy
enum{
audio_device_none=0x0,
/*reservedbits*/
audio_device_bit_in=0x80000000,
audio_device_bit_default=0x40000000,
/*outputdevices*/
audio_device_out_earpiece=0x1,
audio_device_out_speaker=0x2,
audio_device_out_wired_headset=0x4,
audio_device_out_wired_headphone=0x8,
audio_device_out_bluetooth_sco=0x10,
audio_device_out_bluetooth_sco_headset=0x20,
。。。
}
stream:
[cpp]view plaincopy
/*theaudiostreamforphonecalls*/
publicstaticfinalintstream_voice_call=0;
/*theaudiostreamforsystemsounds*/
publicstaticfinalintstream_system=1;
/*theaudiostreamforthephoneringandmessagealerts*/
publicstaticfinalintstream_ring=2;
/*theaudiostreamformusicplayback*/
publicstaticfinalintstream_music=3;
/*theaudiostreamforalarms*/
publicstaticfinalintstream_alarm=4;
/*theaudiostreamfornotifications*/
publicstaticfinalintstream_notification=5;
/*@hidetheaudiostreamforphonecallswhenconnectedonbluetooth*/
publicstaticfinalintstream_bluetooth_sco=6;
/*@hidetheaudiostreamforenforcedsystemsoundsincertaincountries(e.gcamerainjapan)*/
publicstaticfinalintstream_system_enforced=7;
/*@hidetheaudiostreamfordtmftones*/
publicstaticfinalintstream_dtmf=8;
看到函数内部,调用的仕audiosystem的setstreamvolumeindex函数,进到audiosystem
二、audiosystem
audiosystem.cpp-----framework/av/media/libmedia/
[cpp]view plaincopy
status_taudiosystem::setstreamvolumeindex(audio_stream_type_tstream,
intindex,
audio_devices_tdevice)
{
constsp&aps=audiosystem::get_audio_policy_service();
if(aps==0)returnpermission_denied;
returnaps->setstreamvolumeindex(stream,index,device);
}
这里采用了binder机制,直接无视它!知道是一种调用方式就可以。
看到函数调用了audiopolicyservice里的函数setstreamvolumeindex;
三、audiopolicyservice
audiopolicyservice.cpp-----framework/av/media/services/audioflinger
[cpp]view plaincopy
status_taudiopolicyservice::setstreamvolumeindex(audio_stream_type_tstream,
intindex,
audio_devices_tdevice)
{
if(mpaudiopolicy==null){
returnno_init;
}
if(!settingsallowed()){
returnpermission_denied;
}
if(uint32_t(stream)>=audio_stream_cnt){
returnbad_value;
}
mutex::autolock_l(mlock);
if(mpaudiopolicy->set_stream_volume_index_for_device){
returnmpaudiopolicy->set_stream_volume_index_for_device(mpaudiopolicy,
stream,
index,
device);
}else{
returnmpaudiopolicy->set_stream_volume_index(mpaudiopolicy,stream,index);
}
}
函数内部,调用了 [cpp]view plaincopy
mpaudiopolicy->set_stream_volume_index_for_device 这里mpaudiopolicy后面讲解,疑点1,这里它调用的是audio_policy_hal.cpp中的方法;
四、
audio_policy_hal.cpp----system/core/libcutils/
[cpp]view plaincopy
staticintap_set_stream_volume_index(structaudio_policy*pol,
audio_stream_type_tstream,
intindex)
{
structlegacy_audio_policy*lap=to_lap(pol);
returnlap->apm->setstreamvolumeindex((audiosystem::stream_type)stream,
index,
audio_device_out_default);
}
五、audiopolicymanager
audiopolicymanagerbase.c----hardware/libhardware_legacy/audio
看到四中的apm就猜到调用的仕audiopolicymanagerbase中的函数,(疑点2),进入audiopolicymanagerbase.c中的函数
[cpp]view plaincopy
status_taudiopolicymanagerbase::setstreamvolumeindex(audiosystem::stream_typestream,
intindex,
audio_devices_tdevice)
{
if((indexmstreams[stream].mindexmax)){
returnbad_value;
}
if(!audio_is_output_device(device)){
returnbad_value;
}
//forcemaxvolumeifstreamcannotbemuted
if(!mstreams[stream].mcanbemuted)index=mstreams[stream].mindexmax;
alogv("setstreamvolumeindex()stream%d,device%04x,index%d",
stream,device,index);
//ifdeviceisaudio_device_out_defaultsetdefaultvalueand
//clearalldevicespecificvalues
if(device==audio_device_out_default){
mstreams[stream].mindexcur.clear();
}
mstreams[stream].mindexcur.add(device,index);
//computeandapplystreamvolumeonalloutputsaccordingtoconnecteddevice
status_tstatus=no_error;
for(size_ti=0;i audio_devices_tcurdevice=
getdeviceforvolume(moutputs.valueat(i)->device());
if((device==audio_device_out_default)||(device==curdevice)||
status_tvolstatus=checkandsetvolume(stream,index,moutputs.keyat(i),curdevice);
if(volstatus!=no_error){
status=volstatus;
}
}
}
returnstatus;
} 调用到函数checkandsetvolume函数:
[cpp]view plaincopy
status_taudiopolicymanagerbase::checkandsetvolume(intstream,
intindex,
audio_io_handle_toutput,
audio_devices_tdevice,
intdelayms,
boolforce)
{
。。。。
if(voicevolume!=mlastvoicevolume&&output==mprimaryoutput){
mpclientinterface->setvoicevolume(voicevolume,delayms);
mlastvoicevolume=voicevolume;
}
}
returnno_error;
} 里面的mpclientinterface->setvoicevolume,mpclientnterface实际上是audiopolicyservice,
即调用的是audiopolicyservice->setstreamvolume
六、audiopolicyservice
audiopolicyservice.cpp---frameworks/av/services/audioflinger
[cpp]view plaincopy
intaudiopolicyservice::setstreamvolume(audio_stream_type_tstream,
floatvolume,
audio_io_handle_toutput,
intdelayms)
{
return(int)maudiocommandthread->volumecommand(stream,volume,
output,delayms);
}
volumecommand函数也在这个文件内
[cpp]view plaincopy
status_taudiopolicyservice::audiocommandthread::volumecommand(audio_stream_type_tstream,
floatvolume,
audio_io_handle_toutput,
intdelayms)
{
status_tstatus=no_error;
audiocommand*command=newaudiocommand();
command->mcommand=set_volume;
volumedata*data=newvolumedata();
data->mstream=stream;
data->mvolume=volume;
data->mio=output;
command->mparam=data;
mutex::autolock_l(mlock);
insertcommand_l(command,delayms);
mwaitworkcv.signal();
if(command->mwaitstatus){
command->mcond.wait(mlock);
status=command->mstatus;
command->mcond.signal();
deletecommand;
}
returnstatus;
}
[cpp]view plaincopy
insertcommand_l(command,delayms); 加入线程队列中,即threadloop中;
[cpp]view plaincopy
boolaudiopolicyservice::audiocommandthread::threadloop()
{
nsecs_twaittime=int64_max;
mlock.lock();
while(!exitpending())
{
while(!maudiocommands.isempty()){
nsecs_tcurtime=systemtime();
if(maudiocommands[0]->mtime<=curtime){
audiocommand*command=maudiocommands[0];
maudiocommands.removeat(0);
mlastcommand=*command;
//sprd:deletecommandafterwaitingwasend
booldeleteaudiocommand=true;
switch(command->mcommand){
。。。。
caseset_volume:{
volumedata*data=(volumedata*)command->mparam;
alogv("audiocommandthread()processingsetvolumestream%d,\
volume%f,output%d",data->mstream,data->mvolume,data->mio);
command->mstatus=audiosystem::setstreamvolume(data->mstream,
data->mvolume,
data->mio);
if(command->mwaitstatus){
//sprd:deletecommandafterwaitingwasend
deleteaudiocommand=false;
command->mcond.signal();
command->mcond.waitrelative(mlock,kaudiocommandtimeout);
}
deletedata;
}break;
。。。。。
mlock.unlock();
returnfalse;
}
调到啊udiosystem的函数
七、audiosystem
audiosystem.c---frameworks/av/media/libmedia
[cpp]view plaincopy
status_taudiosystem::setstreamvolume(audio_stream_type_tstream,floatvalue,
audio_io_handle_toutput)
{
if(uint32_t(stream)>=audio_stream_cnt)returnbad_value;
constsp&af=audiosystem::get_audio_flinger();
if(af==0)returnpermission_denied;
af->setstreamvolume(stream,value,output);
returnno_error;
} 通过binder通信,调用audioflinger里的setstreamvolume
八、audioflinger
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
调用过程详细分析:
疑点1、mpaudiopolicy调用的是audio_policy_hal.cpp中的方法分析:
函数内部,使用mpaudiopolicy的方法,这就需要看下audiopolicyservice的构造函数;
[cpp]view plaincopy
audiopolicyservice::audiopolicyservice()
:bnaudiopolicyservice(),mpaudiopolicydev(null),mpaudiopolicy(null)
{
charvalue[property_value_max];
conststructhw_module_t*module;
intforced_val;
intrc;
mutex::autolock_l(mlock);
//starttoneplaybackthread
mtoneplaybackthread=newaudiocommandthread(string8("apmtone"),this);
//startaudiocommandsthread
maudiocommandthread=newaudiocommandthread(string8("apmaudio"),this);
//startoutputactivitycommandthread
moutputcommandthread=newaudiocommandthread(string8("apmoutput"),this);
/*instantiatetheaudiopolicymanager*/
rc=hw_get_module(audio_policy_hardware_module_id,&module);//1.1分析
if(rc)
return;
rc=audio_policy_dev_open(module,&mpaudiopolicydev);//1.2分析
aloge_if(rc,"couldn'topenaudiopolicydevice(%s)",strerror(-rc));
if(rc)
return;
rc=mpaudiopolicydev->create_audio_policy(mpaudiopolicydev,&aps_ops,this,
&mpaudiopolicy);//1.3分析
aloge_if(rc,"couldn'tcreateaudiopolicy(%s)",strerror(-rc));
if(rc)
return;
rc=mpaudiopolicy->init_check(mpaudiopolicy);
aloge_if(rc,"couldn'tinit_checktheaudiopolicy(%s)",strerror(-rc));
if(rc)
return;
/*sprd:maybesetthispropertybetter,butherejustchangethedefaultvalue@{*/
property_get("ro.camera.sound.forced",value,"1");
forced_val=strtol(value,null,0);
alogv("setforceuse()!forced_val=%d",!forced_val);
mpaudiopolicy->set_can_mute_enforced_audible(mpaudiopolicy,!forced_val);
/*@}*/
alogi("loadedaudiopolicyfrom%s(%s)",module->name,module->id);
//loadaudiopreprocessingmodules
if(access(audio_effect_vendor_config_file,r_ok)==0){
loadpreprocessorconfig(audio_effect_vendor_config_file);
}elseif(access(audio_effect_default_config_file,r_ok)==0){
loadpreprocessorconfig(audio_effect_default_config_file);
}
}
1.1分析hw_get_module(audio_policy_hardware_module_id, &module);
其中,#define audio_policy_hardware_module_id "audio_policy"
[cpp]view plaincopy
inthw_get_module(constchar*id,conststructhw_module_t**module)
上面函数调用hardware.c--------audio/hardware/libhardware/
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, null, module);}又调用hw_get_module_by_class,还在这个文件内;
[cpp]view plaincopy
inthw_get_module_by_class(constchar*class_id,constchar*inst,
conststructhw_module_t**module)//class_id保存"audio_policy",inst为null
{
intstatus;
inti;
conststructhw_module_t*hmi=null;
charprop[path_max];
charpath[path_max];
charname[path_max];
if(inst)//inst=null,走else
snprintf(name,path_max,"%s.%s",class_id,inst);
else
strlcpy(name,class_id,path_max);//将"audio_policy"拷贝到name中;
/*
*herewerelyonthefactthatcallingdlopenmultipletimeson
*thesame.sowillsimplyincrementarefcount(andnotload
*anewcopyofthelibrary).
*wealsoassumethatdlopen()isthread-safe.
*/
/*loopthroughtheconfigurationvariantslookingforamodule*/
for(i=0;i if(i if(property_get(variant_keys[i],prop,null)==0){
continue;
}
snprintf(path,sizeof(path),"%s/%s.%s.so",
hal_library_path2,name,prop);
if(access(path,r_ok)==0)break;
snprintf(path,sizeof(path),"%s/%s.%s.so",
hal_library_path1,name,prop);
if(access(path,r_ok)==0)break;
}else{
snprintf(path,sizeof(path),"%s/%s.default.so",
hal_library_path2,name);
if(access(path,r_ok)==0)break;
snprintf(path,sizeof(path),"%s/%s.default.so",
hal_library_path1,name);//#definehal_library_path1"/system/lib/hw"
//将"/system/lib/hw/audio_policy.default.so"拷贝到path中
if(access(path,r_ok)==0)break;//判断是否是可读文件,至此,已经确定加载audio_policy.default.so文件,下面的load将完成加载
}
}
status=-enoent;
if(i /*loadthemodule,ifthisfails,we'redoomed,andweshouldnottry
*toloadadifferentvariant.*/
status=load(class_id,path,module);//定义的load函数,下面分析
}
returnstatus;
} 这个函数,需要高清几个函数的使用:property_get,snprintf,access;dlopen,dlsym。这几个函数会在另外一篇文章中讲解。 [cpp]view plaincopy
/**
*loadthefiledefinedbythevariantandifsuccessful
*returnthedlopenhandleandthehmi.
*@return0=success,!0=failure.
*/
staticintload(constchar*id,
constchar*path,
conststructhw_module_t**phmi)
{
intstatus;
void*handle;
structhw_module_t*hmi;
/*
*loadthesymbolsresolvingundefinedsymbolsbefore
*dlopenreturns.sincertld_globalisnotor'dinwith
*rtld_nowtheexternalsymbolswillnotbeglobal
*/
handle=dlopen(path,rtld_now);//打开指定的文件,即audio_policy.default.so
if(handle==null){
charconst*err_str=dlerror();
aloge("load:module=%s\n%s",path,err_str?err_str:"unknown");
status=-einval;
gotodone;
}
/*gettheaddressofthestructhal_module_info.*/
constchar*sym=hal_module_info_sym_as_str;//#definehal_module_info_sym_as_str"hmi"
hmi=(structhw_module_t*)dlsym(handle,sym);//根据动态链接库操作句柄与符号,返回符号对应的地址保存给hmi
if(hmi==null){
aloge("load:couldn'tfindsymbol%s",sym);
status=-einval;
gotodone;
}
/*checkthattheidmatches*/
if(strcmp(id,hmi->id)!=0){
aloge("load:id=%s!=hmi->id=%s",id,hmi->id);
status=-einval;
gotodone;
}
hmi->dso=handle;
/*success*/
status=0;
done:
if(status!=0){
hmi=null;
if(handle!=null){
dlclose(handle);
handle=null;
}
}else{
alogv("loadedhalid=%spath=%shmi=%phandle=%p",
id,path,*phmi,handle);
}
*phmi=hmi;//将地址赋值给形参。至此,整个动态库so的加载完成,并将地址返回
returnstatus;
}
上一篇: IOS数据存储常用的5种方式
下一篇: ab压力测试工具
推荐阅读
-
Android设置TextView首行缩进示例代码
-
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
-
Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
-
Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
-
Android中给按钮同时设置背景和圆角示例代码
-
Android ArrayMap源代码分析
-
Android中给按钮同时设置背景和圆角示例代码
-
Android ArrayMap源代码分析
-
Android 多种简单的弹出框样式设置代码
-
Android 多种简单的弹出框样式设置代码