本篇文章将会从总体流程上解释一下每一个函数的意义,具体的每一个函数的解释将是一个很长的过程,后面的文章中我将会针对每一个有意义的函数来具体分析。
在具体分析bluetoothdservice的启动之前,我们先来看一下bluetoothd service究竟是什么,他同样定义在init.rc中:
servicebluetoothd /system/bin/bluetoothd -n
所以,很清楚,他就是执行bluetoothd这个应用。那么bluetoothd是由哪个文件编译出来的呢,搜索一下就会在bluez下面的src中的Android.mk发现其踪迹:
- #
- #bluetoothd
- #
- include$(CLEAR_VARS)
- LOCAL_SHARED_LIBRARIES:=\
- libbluetoothd
- LOCAL_MODULE:=bluetoothd
所以,很清楚了,我们就在src目录下面看一下了,作为一个应用程序,第一个映入我们眼帘的肯定就是main了,正好下面有一个main.c,然后里面还有一个main函数,哈哈,你懂的:
- intmain(intargc,char*argv[])
- {
- GOptionContext*context;
- GError*err=NULL;
- structsigactionsa;
- uint16_tmtu=0;
- GKeyFile*config;
- //这个函数就是用来设置uid和capability的,他主要是使得该应用在访问kernel的时候能够有权限
- //从注册可以看到,说目前的androidinitrc并不支持权限的赋予,所以只能出此下策,毫无疑问,我们需要走到这个ifdef中
- //当然我们也可以从理论上去check一下,在Android.mk中是有这个宏的define的
- #ifdefANDROID_SET_AID_AND_CAP
- /*UnfortunatelyAndroid'sinit.rcdoesnotyetsupportapplying
- *capabilities.Sowemustdoitin-process.*/
- void*android_set_aid_and_cap(void);
- //这个就是设置uid为AID_BLUETOOTH,
- //设置capbility为CAP_NET_RAW|CAP_NET_ADMIN|CAP_NET_BIND_SERVICE
- android_set_aid_and_cap();
- #endif
- //默认的初始化,详细分析见2.2.1
- init_defaults();
- //既然我们上面已经想法设法得到权限了,这里就必然不会再把权限释放了。
- //这个ifdef是不会进去了
- #ifdefHAVE_CAPNG
- /*Dropcapabilities*/
- capng_clear(CAPNG_SELECT_BOTH);
- capng_updatev(CAPNG_ADD,CAPNG_EFFECTIVE|CAPNG_PERMITTED,
- CAP_NET_BIND_SERVICE,CAP_NET_ADMIN,
- CAP_NET_RAW,CAP_IPC_LOCK,-1);
- capng_apply(CAPNG_SELECT_BOTH);
- #endif
- //这里是解析命令项
- //使用的是glib命令行解析库
- context=g_option_context_new(NULL);
- //就是根据options定义的内容,自动解析到对应的变量中了
- //详细见2.2.2
- g_option_context_add_main_entries(context,options,NULL);
- if(g_option_context_parse(context,&argc,&argv,&err)==FALSE){
- if(err!=NULL){
- g_printerr("%s\n",err->message);
- g_error_free(err);
- }else
- g_printerr("Anunknownerroroccurred\n");
- exit(1);
- }
- g_option_context_free(context);
- //下面就是根据上面解析得到的值来看是否需要做一些对应的操作
- //从initrc中,我们可以看到只有一个-n的参数,但是,我们看是G_OPTION_FLAG_REVERS,猜猜看吧,是的,就是反转的意思,所以option_detach还是false,其它的就都可以忽略了
- if(option_version==TRUE){
- printf("%s\n",VERSION);
- exit(0);
- }
- if(option_udev==TRUE){
- interr;
- option_detach=TRUE;
- err=connect_dbus();
- if(err<0){
- if(err==-EALREADY)
- exit(0);
- exit(1);
- }
- }
- //后台运行,这里也就不去
- if(option_detach==TRUE&&option_udev==FALSE){
- if(daemon(0,0)){
- perror("Can'tstartdaemon");
- exit(1);
- }
- }
- //重新设置权限
- umask(0077);
- //btlog的初始化,这里就不关心了,android中若想打印log需要重新修改
- __btd_log_init(option_debug,option_detach);
- //设置一个signal的处理函数,不一一看了,关系不大
- memset(&sa,0,sizeof(sa));
- sa.sa_flags=SA_NOCLDSTOP;
- sa.sa_handler=sig_term;
- sigaction(SIGTERM,&sa,NULL);
- sigaction(SIGINT,&sa,NULL);
- sa.sa_handler=sig_debug;
- sigaction(SIGUSR2,&sa,NULL);
- sa.sa_handler=SIG_IGN;
- sigaction(SIGPIPE,&sa,NULL);
- //加载配置文件
- config=load_config(CONFIGDIR"/main.conf");
- //解析配置文件,这里就是根据main.conf中的配置进行相应的设置
- //详细分析见2.2.3
- parse_config(config);
- //这里就是初始化dbus
- agent_init();
- if(option_udev==FALSE){
- //连接dbus
- if(connect_dbus()<0){
- error("UnabletogetonD-Bus");
- exit(1);
- }
- }else{
- if(daemon(0,0)){
- perror("Can'tstartdaemon");
- exit(1);
- }
- }
- //启动sdpserver,详细分析见2.2.4
- start_sdp_server(mtu,main_opts.deviceid,SDP_SERVER_COMPAT);
- //在main.conf中attrib_server=false,所以这里就不进入了
- if(main_opts.attrib_server){
- if(attrib_server_init()<0)
- error("Can'tinitializeattributeserver");
- }
- /*LoadingpluginshastobedoneafterD-Bushasbeensetupsince
- *thepluginsmightwannaexposesomepathsonthebus.Howeverthe
- *bestorderofhowtoinitvarioussubsystemsoftheBluetooth
- *daemonneedstobere-worked.*/
- //从注释来看,plugins的加载最好是在D-Bus已经建立完成的基础上。
- //他们也认为这个地方做好再重写一下,我们就先将就着看看吧
- //这里的option_plugin和option_noplugin都是null,因为我们的bluetoothd中并没有他们的参数
- //包含了hciops,audio,input,network,health
- //具体参见2.2.5中
- plugin_init(config,option_plugin,option_noplugin);
- //创建主循环
- event_loop=g_main_loop_new(NULL,FALSE);
- //adapter的ops的建立,详细分析见2.2.6
- if(adapter_ops_setup()<0){
- error("adapter_ops_setupfailed");
- exit(1);
- }
- //会根据remember_powered参数来决定是否需要做什么,我们这里是是false,所以,没有做什么,直接ruturn。
- rfkill_init();
- DBG("Enteringmainloop");
- //进入主循环,就卡在这边了。
- //对主循环的影响都在上面的那些signal的处理函数中,我们可以理解,没有什么异常就会卡在这边了,知道蓝牙关闭才会退出了
- g_main_loop_run(event_loop);
- //之后的内容就不再详细分析了
- ……
- }