2018年5月10日 星期四

[android源碼分析]bluetoothd service的啟動的總體流程分析

原文 https://blog.csdn.net/u011960402/article/details/12966787

本篇文章將會從總體流程上解釋一下每一個函數的意義,具體的每一個函數的解釋將是一個很長的過程,後面的文章中我將會針對每一個有意義的函數來具體分析。
在具體分析bluetoothdservice的啟動之前,我們先來看一下bluetoothd service究竟是什麼,他同樣定義在init.rc中:
servicebluetoothd /system/bin/bluetoothd -n
         所以,很清楚,他就是執行bluetoothd這個應用。那麼bluetoothd是由哪個文件編譯出來的呢,搜索一下就會在bluez下面的src中的Android.mk發現其踪跡:
[plain] view plaincopy 
  1. #  
  2. # bluetoothd  
  3. #  
  4.   
  5. include $(CLEAR_VARS)  
  6.   
  7. LOCAL_SHARED_LIBRARIES := \  
  8.     libbluetoothd  
  9.   
  10. LOCAL_MODULE:=bluetoothd  
所以,很清楚了,我們就在src目錄下面看一下了,作為一個應用程序,第一個映入我們眼簾的肯定就是main了,正好下面有一個main.c,然後裡面還有一個main函數,哈哈,你懂的:
[cpp] view plaincopy 
  1. int  main( int  argc,  char  *argv[])  
  2. {  
  3.     GOptionContext *context;  
  4.     GError *err = NULL;  
  5.     struct  sigaction sa;  
  6.     uint16_t mtu = 0;  
  7.     GKeyFile *config;  
  8. //這個函數就是用來設置uid和capability的,他主要是使得該應用在訪問kernel的時候能夠有權限  
  9. //從註冊可以看到,說目前的android init rc並不支持權限的賦予,所以只能出此下策,毫無疑問,我們需要走到這個ifdef中  
  10. //當然我們也可以從理論上去check一下,在Android.mk中是有這個宏的define的  
  11. #ifdef ANDROID_SET_AID_AND_CAP  
  12.     /* Unfortunately Android's init.rc does not yet support applying 
  13.      * capabilities. So we must do it in-process. */  
  14.     void  *android_set_aid_and_cap( void );  
  15.     //這個就是設置uid為AID_BLUETOOTH,  
  16.     //設置capbility為CAP_NET_RAW| CAP_NET_ADMIN| CAP_NET_BIND_SERVICE  
  17.     android_set_aid_and_cap();  
  18. #endif  
  19.     //默認的初始化,詳細分析見2.2.1  
  20.     init_defaults();  
  21. //既然我們上面已經想法設法得到權限了,這裡就必然不會再把權限釋放了。  
  22. //這個ifdef是不會進去了  
  23. #ifdef HAVE_CAPNG  
  24.     /* Drop capabilities */  
  25.     capng_clear(CAPNG_SELECT_BOTH);  
  26.     capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,  
  27.                     CAP_NET_BIND_SERVICE, CAP_NET_ADMIN,  
  28.                         CAP_NET_RAW, CAP_IPC_LOCK, -1);  
  29.     capng_apply(CAPNG_SELECT_BOTH);  
  30. #endif  
  31.     //這裡是解析命令項  
  32.     //使用的是glib命令行解析庫  
  33.     context = g_option_context_new(NULL);  
  34.     //就是根據options定義的內容,自動解析到對應的變量中了  
  35.     //詳細見2.2.2  
  36.     g_option_context_add_main_entries(context, options, NULL);  
  37.   
  38.     if  (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {  
  39.         if  (err != NULL) {  
  40.             g_printerr( "%s\n" , err->message);  
  41.             g_error_free(err);  
  42.         }  else  
  43.             g_printerr( "An unknown error occurred\n" );  
  44.         exit(1);  
  45.     }  
  46.   
  47.     g_option_context_free(context);  
  48.     //下面就是根據上面解析得到的值來看是否需要做一些對應的操作  
  49.     //從init rc中,我們可以看到只有一個-n的參數,但是,我們看是G_OPTION_FLAG_REVERS,猜猜看吧,是的,就是反轉的意思,所以option_detach還是false,其它的就都可以忽略了  
  50.     if  (option_version == TRUE) {  
  51.         printf( "%s\n" , VERSION);  
  52.         exit(0);  
  53.     }  
  54.   
  55.     if  (option_udev == TRUE) {  
  56.         int  err;  
  57.   
  58.         option_detach = TRUE;  
  59.         err = connect_dbus();  
  60.         if  (err < 0) {  
  61.             if  (err == -EALREADY)  
  62.                 exit(0);  
  63.             exit(1);  
  64.         }  
  65.     }  
  66.     //後台運行,這裡也就不去  
  67.     if  (option_detach == TRUE && option_udev == FALSE) {  
  68.         if  (daemon(0, 0)) {  
  69.             perror( "Can't start daemon" );  
  70.             exit(1);  
  71.         }  
  72.     }  
  73.     //重新設置權限  
  74.     umask(0077);  
  75.     //bt log的初始化,這裡就不關心了,android中若想打印log需要重新修改  
  76.     __btd_log_init(option_debug, option_detach);  
  77.     //設置一個signal的處理函數,不一一看了,關係不大  
  78.     memset(&sa, 0,  sizeof (sa));  
  79.     sa.sa_flags = SA_NOCLDSTOP;  
  80.     sa.sa_handler = sig_term;  
  81.     sigaction(SIGTERM, &sa, NULL);  
  82.     sigaction(SIGINT, &sa, NULL);  
  83.   
  84.     sa.sa_handler = sig_debug;  
  85.     sigaction(SIGUSR2, &sa, NULL);  
  86.   
  87.     sa.sa_handler = SIG_IGN;  
  88.     sigaction(SIGPIPE, &sa, NULL);  
  89.     //加載配置文件  
  90.     config = load_config(CONFIGDIR  "/main.conf" );  
  91.     //解析配置文件,這裡就是根據main.conf中的配置進行相應的設置  
  92.     //詳細分析見2.2.3  
  93.     parse_config(config);  
  94.     //這裡就是初始化dbus  
  95.     agent_init();  
  96.   
  97.     if  (option_udev == FALSE) {  
  98.         //連接dbus  
  99.         if  (connect_dbus() < 0) {  
  100.             error( "Unable to get on D-Bus" );  
  101.             exit(1);  
  102.         }  
  103.     }  else  {  
  104.         if  (daemon(0, 0)) {  
  105.             perror( "Can't start daemon" );  
  106.             exit(1);  
  107.         }  
  108.     }  
  109.     //啟動sdp server,詳細分析見2.2.4  
  110.     start_sdp_server(mtu, main_opts.deviceid, SDP_SERVER_COMPAT);  
  111.     //在main.conf中attrib_server=false,所以這裡就不進入了  
  112.     if  (main_opts.attrib_server) {  
  113.         if  (attrib_server_init() < 0)  
  114.             error( "Can't initialize attribute server" );  
  115.     }  
  116.     /* Loading plugins has to be done after D-Bus has been setup since 
  117.      * the plugins might wanna expose some paths on the bus. However the 
  118.      * best order of how to init various subsystems of the Bluetooth 
  119.      * daemon needs to be re-worked. */  
  120. //從註釋來看,plugins的加載最好是在D-Bus已經建立完成的基礎上。  
  121. //他們也認為這個地方做好再重寫一下,我們就先將就著看看吧  
  122. //這裡的option_plugin和option_noplugin都是null,因為我們的bluetoothd中並沒有他們的參數  
  123. //包含了hciops,audio,input,network,health  
  124. //具體參見2.2.5中  
  125.     plugin_init(config, option_plugin, option_noplugin);  
  126.     //創建主循環  
  127.     event_loop = g_main_loop_new(NULL, FALSE);  
  128.     //adapter的ops的建立,詳細分析見2.2.6  
  129.     if  (adapter_ops_setup() < 0) {  
  130.         error( "adapter_ops_setup failed" );  
  131.         exit(1);  
  132.     }  
  133.     //會根據remember_powered參數來決定是否需要做什麼,我們這裡是是false,所以,沒有做什麼,直接ruturn。  
  134.     rfkill_init();  
  135.   
  136.     DBG( "Entering main loop" );  
  137.     //進入主循環,就卡在這邊了。  
  138.     //對主循環的影響都在上面的那些signal的處理函數中,我們可以理解,沒有什麼異常就會卡在這邊了,知道藍牙關閉才會退出了  
  139.     g_main_loop_run(event_loop);  
  140.     //之後的內容就不再詳細分析了  
  141.     ……  
  142. }  

沒有留言: