当前位置: 移动技术网 > IT编程>移动开发>Android > android volume设置 代码分析

android volume设置 代码分析

2018年09月18日  | 移动技术网IT编程  | 我要评论

山东人事信息网,日本美女人体,2010浙江高考英语

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;

}

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网