[Android 源碼解析]bluez中幾個重要plugin的初始化–audio,input,network,health

本來隻想分析一下hciops的初始化就不再管瞭,後來發現別的plugin的初始化在後面還是會有涉及,心中想,既然已經分析瞭這麼多,咋就索性都分析瞭算瞭,反正也不差這一點代碼,其它的plugin還有audio,input,network,health。我們隻看兩個函數init或者setup。所以看起來應該會比較簡單一點。

 

 

 

2.3.7.1 audio的init分析

 

 audio 這個插件的分析

 

[cpp]  

static int audio_init(void)  

{  

    GKeyFile *config;  

    gboolean enable_sco;  

    //得到系統的dbus  

    connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);  

    if (connection == NULL)  

        return -EIO;  

    //得到audio.config文件  

    config = load_config_file(CONFIGDIR "/audio.conf");  

    //根據config來進行init  

    if (audio_manager_init(connection, config, &enable_sco) < 0)  

        goto failed;  

//沒有使能sco,就直接return瞭,我們這裡的確沒有使能sco,所以,沒什麼好說的,直接return吧  

    if (!enable_sco)  

        return 0;  

……  

  

    return -EIO;  

}  

1)audio.conf的內容簡介如下:

 

[plain]  

[General]  

Enable=Sink,Control  

Disable=Headset,Gateway,Source  

Master=false  

FastConnectable=false  

[A2DP]  

SBCSources=1  

MPEG12Sources=0  

  

[AVRCP]  

InputDeviceName=AVRCP  

2)根據config來進行init

 

[cpp]  

int audio_manager_init(DBusConnection *conn, GKeyFile *conf,  

                            gboolean *enable_sco)  

{  

    char **list;  

    int i;  

    gboolean b;  

    GError *err = NULL;  

    //dbus的connection的ref+1  

    connection = dbus_connection_ref(conn);  

    //沒有config文件,直接結束  

    if (!conf)  

        goto proceed;  

    //config是一個全局變量  

    config = conf;  

    /* 

    //從上面1)中可以得到 

    Enable=Sink,Control 

    Disable=Headset,Gateway,Source 

*/  

    list = g_key_file_get_string_list(config, "General", "Enable",  

                        NULL, NULL);  

    //enable的有哪些,加粗的就是enable的  

    for (i = 0; list && list[i] != NULL; i++) {  

        if (g_str_equal(list[i], "Headset"))  

            enabled.headset = TRUE;  

        else if (g_str_equal(list[i], "Gateway"))  

            enabled.gateway = TRUE;  

        else if (g_str_equal(list[i], "Sink"))  

            enabled.sink = TRUE;  

        else if (g_str_equal(list[i], "Source"))  

            enabled.source = TRUE;  

        else if (g_str_equal(list[i], "Control"))  

            enabled.control = TRUE;  

        else if (g_str_equal(list[i], "Socket"))  

            enabled.socket = TRUE;  

        else if (g_str_equal(list[i], "Media"))  

            enabled.media = TRUE;  

    }  

    g_strfreev(list);  

    //再看disable的,加粗的就是disable的  

    list = g_key_file_get_string_list(config, "General", "Disable",  

                        NULL, NULL);  

    for (i = 0; list && list[i] != NULL; i++) {  

        if (g_str_equal(list[i], "Headset"))  

            enabled.headset = FALSE;  

        else if (g_str_equal(list[i], "Gateway"))  

            enabled.gateway = FALSE;  

        else if (g_str_equal(list[i], "Sink"))  

            enabled.sink = FALSE;  

        else if (g_str_equal(list[i], "Source"))  

            enabled.source = FALSE;  

        else if (g_str_equal(list[i], "Control"))  

            enabled.control = FALSE;  

        else if (g_str_equal(list[i], "Socket"))  

            enabled.socket = FALSE;  

        else if (g_str_equal(list[i], "Media"))  

            enabled.media = FALSE;  

    }  

//除瞭上面這些設置,下面就還有幾個默認的  

/* 

//這裡是一些默認 

//hsp是沒有的,hfp有的 

static struct enabled_interfaces enabled = { 

    .hfp        = TRUE, 

    .headset    = TRUE, 

    .gateway    = FALSE, 

    .sink       = TRUE, 

    .source     = FALSE, 

    .control    = TRUE, 

    .socket     = TRUE, //主要就是這個沒有配置瞭 

    .media      = FALSE 

}; 

*/  

    b = g_key_file_get_boolean(config, "General", "AutoConnect", &err);  

    if (err) { //沒有,所以就是not found,使用默認值,是true  

        DBG("audio.conf: %s", err->message);  

        g_clear_error(&err);  

    } else  

        auto_connect = b;   

  

    b = g_key_file_get_boolean(config, "Headset", "HFP",  

                    &err);  

    if (err)  

        g_clear_error(&err);  

    else  

        enabled.hfp = b; //默認是true是支持的  

  

    err = NULL;  

    i = g_key_file_get_integer(config, "Headset", "MaxConnected",  

                    &err);  

    if (err) {  

        DBG("audio.conf: %s", err->message);  

        g_clear_error(&err);  

    } else  

        max_connected_headsets = i; //沒有設置,默認是1  

proceed:  

    //socket是肯定要的  

    if (enabled.socket)  

        unix_init();  

    //media默認是false  

    if (enabled.media)  

        btd_register_adapter_driver(&media_server_driver);  

    //headset也是false  

    if (enabled.headset)  

        btd_register_adapter_driver(&headset_server_driver);  

    //gateway也是flase的  

    if (enabled.gateway)  

        btd_register_adapter_driver(&gateway_server_driver);  

    //這兩個是enable的,把對應的driver加入到adapter_drivers列表中,並調用driver的probe函數,同時把這個driver加入到adapter->loaded_drivers列表中。然而這些有一個前提就是adapter需要up,若是沒有也是不會做的,後面自然會有分析他們的地方,我們到時再繼續分析。  

    if (enabled.source || enabled.sink)  

        btd_register_adapter_driver(&a2dp_server_driver);  

    //control也是enable的  

    if (enabled.control)  

        btd_register_adapter_driver(&avrcp_server_driver);  

    //audio也是enable的,不過這是一個device driver  

    btd_register_device_driver(&audio_driver);  

    //這裡是false,sco是沒有enable的  

    *enable_sco = (enabled.gateway || enabled.headset);  

  

    return 0;  

}  

 

 

 

所以,這裡一共是3個driver註冊瞭。

 

3)unix_init分析

 

[cpp]  

//這裡其實是新建一個本地的socket,作為server端,後期會有client可以通過這裡進行交互和通信。  

int unix_init(void)  

{  

    GIOChannel *io;  

    struct sockaddr_un addr = {  

        AF_UNIX, BT_IPC_SOCKET_NAME  

    };  

  

    int sk, err;  

    //新建一個stram的socket  

    sk = socket(PF_LOCAL, SOCK_STREAM, 0);  

    if (sk < 0) {  

        err = errno;  

        error("Can't create unix socket: %s (%d)", strerror(err), err);  

        return -err;  

    }  

    //和這個地址綁定在一起  

    if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {  

        error("Can't bind unix socket: %s (%d)", strerror(errno),  

                errno);  

        close(sk);  

        return -1;  

    }  

    //設置為non block  

    set_nonblocking(sk);  

    //最大連接數為1  

    if (listen(sk, 1) < 0) {  

        error("Can't listen on unix socket: %s (%d)",  

                        strerror(errno), errno);  

        close(sk);  

        return -1;  

    }  

  

    unix_sock = sk;  

    //這邊加一個io的watch,有瞭數據後就會去調用accept  

    io = g_io_channel_unix_new(sk);  

    //server_cb中會accept  

    g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,  

                            server_cb, NULL);  

    g_io_channel_unref(io);  

  

    DBG("Unix socket created: %d", sk);  

  

    return 0;  

}  

 

 

 

2.3.7.2 input的init函數分析

 

input 這個插件的初始化

 

[cpp] 

static int input_init(void)  

  

{  

  

         GKeyFile *config;  

  

         //老規矩,不多說  

  

         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);  

  

         if (connection == NULL)  

  

                   return -EIO;  

  

         //加載input.conf,內容見1)  

  

         config = load_config_file(CONFIGDIR "/input.conf");  

  

         //根據config進行初始化  

  

         if (input_manager_init(connection, config) < 0) {  

  

                   dbus_connection_unref(connection);  

  

                   return -EIO;  

  

         }  

  

   

  

         if (config)  

  

                   g_key_file_free(config);  

  

   

  

         return 0;  

  

}  

 

 

 

1)input.conf的內容

 

內容簡單的分析就如下:

 

[General]

 

別的什麼都沒有瞭,他其實能有的也就一個參數#IdleTimeout=30,這裡用的是默認值。

 

2)input_manager_init分析

 

[cpp]  

int input_manager_init(DBusConnection *conn, GKeyFile *config)  

  

{  

  

         GError *err = NULL;  

  

         //得到idle的timeout參數,沒有設置,就是默認值0  

  

         if (config) {  

  

                   idle_timeout = g_key_file_get_integer(config, "General",  

  

                                                        "IdleTimeout", &err);  

  

                   if (err) {  

  

                            DBG("input.conf: %s", err->message);  

  

                            g_error_free(err);  

  

                   }  

  

         }  

  

         //dbus的ref+1  

  

         connection = dbus_connection_ref(conn);  

  

         //初始化瞭input server,同樣因為adapter沒有up,所以沒有做對應的probe  

  

         btd_register_adapter_driver(&input_server_driver);  

  

         //註冊瞭兩個device driver  

  

         btd_register_device_driver(&input_hid_driver);  

  

         btd_register_device_driver(&input_headset_driver);  

  

   

  

         return 0;  

  

}  

 

 

 

2.3.7.3 network的init函數分析

 

[cpp] 

static int network_init(void)  

{  

    connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);  

    if (connection == NULL)  

        return -EIO;  

    //根據network.conf來進行各種配置  

    if (network_manager_init(connection) < 0) {  

        dbus_connection_unref(connection);  

        return -EIO;  

    }  

  

    return 0;  

}  

  

int network_manager_init(DBusConnection *conn)  

{  

//讀取network.conf文件,network.conf裡面也沒有內容,設置conf_security,默認為true  

    read_config(CONFIGDIR "/network.conf");  

    //新建一個bnep的socket  

    if (bnep_init()) {  

        error("Can't init bnep module");  

        return -1;  

    }  

  

    /* 

     * There is one socket to handle the incomming connections. NAP, 

     * GN and PANU servers share the same PSM. The initial BNEP message 

     * (setup connection request) contains the destination service 

     * field that defines which service the source is connecting to. 

     */  

    //初始化security  

    if (server_init(conn, conf_security) < 0)  

        return -1;  

    //加入到adapter_drivers列表中  

    /* Register network server if it doesn't exist */  

    btd_register_adapter_driver(&network_server_driver);  

    //dbus connection  

    if (connection_init(conn) < 0)  

        return -1;  

    //初始化瞭3個device driver  

    btd_register_device_driver(&network_panu_driver);  

    btd_register_device_driver(&network_gn_driver);  

    btd_register_device_driver(&network_nap_driver);  

  

    connection = dbus_connection_ref(conn);  

  

    return 0;  

}  

 

 

 

2.3.7.4 health的init

 

health總得來說用得還是蠻少的,不過android4.0也是支持瞭,我們來看一下吧:

 

[cpp]  

static int hdp_init(void)  

{  

    connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);  

    if (connection == NULL)  

        return -EIO;  

    //就是這個函數瞭  

    if (hdp_manager_init(connection) < 0) {  

        dbus_connection_unref(connection);  

        return -EIO;  

    }  

  

    return 0;  

}  

int hdp_manager_init(DBusConnection *conn)  

{  

    //就是註冊瞭一個health_manager_methods的接口,裡面有creatapplication和destroyapplication兩個函數  

    if (hdp_manager_start(conn))  

        return -1;  

  

    connection = dbus_connection_ref(conn);  

    //註冊一個adapter drvier和一個device driver。  

    btd_register_adapter_driver(&hdp_adapter_driver);  

    btd_register_device_driver(&hdp_device_driver);  

  

    return 0;  

}  

 

 

 

至此,所有的plugin都已經完成瞭。總共註冊瞭一下幾個adapter_driver:a2dp_server_driver,avrcp_server_driver,input_server_driver,network_server_driver,hdp_adapter_driver。另外還有幾個devcie driver:audio_driver,input_hid_driver,input_headset_driver,network_panu_driver,network_gn_driver,network_nap_driver,hdp_device_driver。在後面adapter up之後我們會加載這些driver,到時我們再來詳細分析他們各自都做瞭些什麼。

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *