欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android volume设置 代码分析

程序员文章站 2022-05-25 15:50:09
android volume设置 代码分析。 volume设置,跳过binder部分(binder请独立理解) 没有采用深度优先的方法,容易绕来绕去,就不知道再看什么了。 采用不断透调的方法讲解,一...

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);

}

}

android volume设置 代码分析

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;

}