精华内容
下载资源
问答
  • Android_BlueDroid详细分析

    热门讨论 2015-11-03 10:18:39
    Android_BlueDroid详细分析
  • bluedroid协议栈源代码

    热门讨论 2014-10-05 13:55:15
    google在新版本的android系统中,用博通开源蓝牙协议栈bluedroid取代了古老强大的bluez。 本资源为bluedroid源代码,供大家学习参考。
  • 关键词:bluedroid initNativeenableNative BTIF_TASK BTU_TASKbt_hc_work_thread set_power preload GKI 作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!) 欢迎指正错误,共同学习、共同进步!! 一...

    关键词:bluedroid  initNative enableNative BTIF_TASK  BTU_TASKbt_hc_work_thread set_power  preload  GKI
    作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!)
    欢迎指正错误,共同学习、共同进步!!

     一、   蓝牙开启流程概述,如下图所示:init、enable

     

     

    和一般的函数调用相同,android上层通过APP-->Native-->JNI-->bluetoothinterface-->bluetooth HCIinterface。HCI interface中实现了init、set_power、preload相应函数
    init、enable函数主要实现的功能:
    (1)、创建:btif_task/BTIF_TASK
    (2)、初始化BTE
    (3)、创建:btu_task/BTU_TASK
    (4)、初始化HCI、串口相关,启动HCI工作主线程:bt_hc_callback,芯片上电、RF参数初始化、蓝牙地址名称相关设定;
    (5)、创建:bt_hc_worker_thread蓝牙工作主线程,发送接收命令;
    (6)、初始化蓝牙协议栈;
    二、initNative函数的的实现
            这部分主要启动相应sock、协议栈初始化、启动btif_task,监听处理蓝牙接口相关的状态消息。实现流程如下所示。

     1、应用部分函数调用(从adatper开始)
    packages\apps\Bluetooth\src\com\android\bluetooth\btservice\ AdapterService.java

     
    1. public void onCreate() {

    2. super.onCreate();

    3. if (DBG) debugLog("onCreate");

    4. mBinder = new AdapterServiceBinder(this);

    5. mAdapterProperties = new AdapterProperties(this);

    6. mAdapterStateMachine = AdapterState.make(this, mAdapterProperties);

    7. mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties);

    8. initNative();//调用initNative函数;

    9. mNativeAvailable=true;

    10. mCallbacks = new RemoteCallbackList<IBluetoothCallback>();

    11. //Load the name and address

    12. getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);

    13. getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);

    14. }

    15. private native boolean initNative();

     

    2、JNI函数的实现,这部分跟其他JNI实现相同。
    packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

     
    1. static JNINativeMethod sMethods[] = {

    2. /* name, signature, funcPtr */

    3. {"classInitNative", "()V", (void *) classInitNative},

    4. {"initNative", "()Z", (void *) initNative},//Native函数实现

    5. …………

    6. }

    7.  

     

    packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
    initNative函数的具体实现,通过bt_interface_t结构体,调用到C中的init函数实现。同时传入sBluetoothCallbacks回调函数结构体。这个函数结构体比较重要,底层的状态变化都是通过这个回调函数结构体中的函数实现。

     
    1. static const bt_interface_t *sBluetoothInterface = NULL;

    2. static bool initNative(JNIEnv* env, jobject obj) {

    3. sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

    4. if (sBluetoothInterface) {

    5. int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//调用到C的相应接口函数

    6. if (ret != BT_STATUS_SUCCESS) {//如果出错,错误处理;

    7. ALOGE("Error while setting the callbacks \n");

    8. sBluetoothInterface = NULL;

    9. return JNI_FALSE;

    10. }

    11. if ( (sBluetoothSocketInterface = (btsock_interface_t *)

    12. sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {

    13. ALOGE("Error getting socket interface");

    14. }

    15. return JNI_TRUE;

    16. }

    17. return JNI_FALSE;

    18. }

     

    3、JNI调用C中函数实现
    C语言实现了上层调用的函数,最终实现了JAVA调用C函数的动作。这是android系统对kernel操作的具体步骤。如果是初学者,建议把这部分内容搞清楚,整个android系统对底层的操作都是通过这种方法实现。
    external\bluetooth\bluedroid\btif\src\bluetooth.c

     
    1. static const bt_interface_t bluetoothInterface = {//蓝牙接口函数对应的函数

    2. sizeof(bluetoothInterface),

    3. init,//C函数中对init函数的实现;

    4. enable,

    5. disable,

    6. cleanup,

    7. get_adapter_properties,

    8. get_adapter_property,

    9. set_adapter_property,

    10. get_remote_device_properties,

    11. get_remote_device_property,

    12. set_remote_device_property,

    13. get_remote_service_record,

    14. get_remote_services,

    15. start_discovery,

    16. cancel_discovery,

    17. create_bond,

    18. remove_bond,

    19. cancel_bond,

    20. pin_reply,

    21. ssp_reply,

    22. get_profile_interface,

    23. dut_mode_configure,

    24. dut_mode_send,

    25. #if BLE_INCLUDED == TRUE

    26. le_test_mode,

    27. #else

    28. NULL,

    29. #endif

    30. config_hci_snoop_log

    31. };

     

    4、蓝牙接口函数中Init函数实现过程
    external\bluetooth\bluedroid\btif\src\bluetooth.c

     
    1. static int init(bt_callbacks_t* callbacks )

    2. {

    3. ALOGI("init");

    4. /* sanity check */

    5. if (interface_ready() == TRUE)//检查接口函数是否准备好;

    6. return BT_STATUS_DONE;

    7. /* store reference to user callbacks */

    8. bt_hal_cbacks = callbacks;//把相应的回调函数,保存,这个非常重要,刚开始看代码是忽略这部分,我们单独一节讲解这部分回调函数的实现和作用;

    9. /* add checks for individual callbacks ? */

    10. bt_utils_init();//工具集初始化,初始化一个互斥锁。

    11. /* init btif */

    12. btif_init_bluetooth();//初始化蓝牙接口bluetoothinterface

    13. return BT_STATUS_SUCCESS;

    14. }

     

    5、蓝牙接口初始化具体实现,btif_init_bluetooth创建BTIF任务,准备蓝牙开启相关调度程序。
    具体实现流程如下所示,我们下面对代码做详细解释。主要完成了:
    (1)、bt_config.xml文件中的蓝牙名称等处理;
    (2)、GKI初始化,这部分后面单一节做详细分析;
    (3)、BlueHCLibInterface初始化,实现power\preload\等函数,BlueDreoid  log等级设定;
    (4)、BTIF_TASK线程创建,这个部分也比较重要。

     

    external\bluetooth\bluedroid\btif\src\btif_core.c

     
    1. bt_status_t btif_init_bluetooth()

    2. {

    3. UINT8 status;

    4. btif_config_init();//创建sock线程,初始化初始化/data/misc/bluedroid/

    5. bt_config.xml中相关数据;

    6. bte_main_boot_entry();//(1)、BTE芯片协议栈入口API,蓝牙协议栈/芯片初始化,GKI init;

    7. /* As part of the init, fetch the local BD ADDR */

    8. memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t));//取蓝牙地址写入相关文件;

    9. btif_fetch_local_bdaddr(&btif_local_bd_addr);

    10. /* start btif task */

    11. status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,

    12. (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),

    13. sizeof(btif_task_stack));

    14. //(2)、Creates BTIF task and prepares BT scheduler for startup 创建蓝牙任务接口,为开启做调度准备

    15. if (status != GKI_SUCCESS)

    16. return BT_STATUS_FAIL;

    17. return BT_STATUS_SUCCESS;

    18. }

     

    (1)、BTE芯片协议栈入口API,蓝牙协议栈/芯片初始化,GKI init;
    external\bluetooth\bluedroid\main\bte_main.c

     
    1. void bte_main_boot_entry(void)

    2. {

    3. /* initialize OS */

    4. GKI_init();//1)、GKI初始化,只在初始化的时候调用一次。

    5.  
    6. bte_main_in_hw_init();//2)、初始化结构体static bt_hc_interface_t *bt_hc_if=NULL;

    7.  
    8. bte_load_conf(BTE_STACK_CONF_FILE);//3)、初始化bluedroid调试信息等级;

    9.  
    10. #if (BTTRC_INCLUDED == TRUE)//相关打印信息初始化;

    11. /* Initialize trace feature */

    12. BTTRC_TraceInit(MAX_TRACE_RAM_SIZE, &BTE_TraceLogBuf[0], BTTRC_METHOD_RAM);

    13. #endif

    14. }


    1)、GKI初始化,只在初始化的时候调用一次
    参考互斥锁:http://blog.csdn.net/kingmax26/article/details/5338065  ;
    external\bluetooth\bluedroid\gki\ulinux\gki_ulinux.c

     
    1. void GKI_init(void)

    2. {

    3. pthread_mutexattr_t attr;

    4. tGKI_OS *p_os;

    5.  
    6. memset (&gki_cb, 0, sizeof (gki_cb));

    7.  
    8. gki_buffer_init();//1))、GKI 缓冲、缓冲池初始化;

    9. gki_timers_init();//2))、GKI定时器初始化;

    10. gki_cb.com.OSTicks = (UINT32) times(0);

    11.  
    12. pthread_mutexattr_init(&attr);//3))、初始化pthread_mutexattr_t结构;

    13.  
    14. #ifndef __CYGWIN__

    15. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);//4))、设置互斥锁类型

    16. #endif

    17. p_os = &gki_cb.os;

    18. pthread_mutex_init(&p_os->GKI_mutex, &attr);//5))、初始化互斥量GKI_mutex;

    19. /* pthread_mutex_init(&GKI_sched_mutex, NULL); */

    20. #if (GKI_DEBUG == TRUE)

    21. pthread_mutex_init(&p_os->GKI_trace_mutex, NULL);// 6))、初始化互斥量GKI_trace_mutex;

    22. #endif

    23. /* pthread_mutex_init(&thread_delay_mutex, NULL); */ /* used in GKI_delay */

    24. /* pthread_cond_init (&thread_delay_cond, NULL); */

    25.  
    26. /* Initialiase GKI_timer_update suspend variables & mutexes to be in running state.

    27. * this works too even if GKI_NO_TICK_STOP is defined in btld.txt */

    28. p_os->no_timer_suspend = GKI_TIMER_TICK_RUN_COND;

    29. pthread_mutex_init(&p_os->gki_timer_mutex, NULL);7))、初始化互斥量gki_timer_mutex;

    30. #ifndef NO_GKI_RUN_RETURN

    31. pthread_cond_init(&p_os->gki_timer_cond, NULL);

    32. #endif

    33. }

     

    2)、初始化结构体static bt_hc_interface_t *bt_hc_if=NULL;
    bte_main_in_hw_init();
    给bt_hc_if赋值:

     
    1. static const bt_hc_interface_t bluetoothHCLibInterface = {

    2. sizeof(bt_hc_interface_t),

    3. init,//HCI LIB中init函数的实现;

    4. set_power,

    5. lpm,

    6. preload,

    7. postload,

    8. transmit_buf,

    9. set_rxflow,

    10. logging,

    11. cleanup

    12. };

     

    3)、初始化bluedroid调试信息等级
        bte_load_conf(BTE_STACK_CONF_FILE);
    解析bt_stack.conf文件中的配置信息。
    (2)、创建蓝牙任务接口,为开启做调度准备Creates BTIF task and prepares BT scheduler for startup  

     
    1. status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,

    2. (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),

    3. sizeof(btif_task_stack));

     

    6、btif_task进程相关处理函数
    external\bluetooth\bluedroid\btif\src\btif_dm.c

    btif_task 等待接收bta_sys_sendmsg发送的相应的状态做相应处理。

     
    1. static void btif_task(UINT32 params)

    2. {

    3. ………………

    4. for(;;)

    5. {

    6. /* wait for specified events */

    7. event = GKI_wait(0xFFFF, 0);//GKI进程间通信后面单开一节介绍;

    8. if (event == BT_EVT_TRIGGER_STACK_INIT)//协议栈初始化完成;

    9. …………

    10. if (event == BT_EVT_HARDWARE_INIT_FAIL)//硬件初始化错误

    11. …………

    12. if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))//收到关闭信息;

    13. …………

    14. if(event & TASK_MBOX_1_EVT_MASK)

    15. …………

    16. }

    17.  
    展开全文
  • Android下bluedroid、bluetooth apk介绍

    千次阅读 2020-04-27 16:53:17
    本文档主要介绍android平台下bluetooth的应用层软件,先介绍bluetooth应用层的框架,接着分别介绍Bluedroid层软件、Bluetooth应用程序(Bluetooth.apk),Bluetooth framework层,最后完整分析一些蓝牙的操作流程。...

    前言

    本文档主要介绍android平台下bluetooth的应用层软件,先介绍bluetooth应用层的框架,接着分别介绍Bluedroid层软件、Bluetooth应用程序(Bluetooth.apk),Bluetooth framework层,最后完整分析一些蓝牙的操作流程。基于android 5.1的平台,涉及的bluetooth硬件为realtek的蓝牙。文档主要针对蓝牙的初学者,提供基础的学习指导。

     

    1 Bluetooth应用层框架介绍

    要介绍android平台bluetooth应用层的软件,首先介绍一下bluetooth的应用层整体框架,如图1为android下的bluetooth的框架。 
     

    这里写图片描述

    图1  bluetooth应用层框架 
       Applications:Android蓝牙应用程序,就是使用蓝牙的API的程序; 
       java Framework:提供给应用使用的API,我们平时使用的BluetoothAdapter,BluetoothDevice,BluetoothSocket等; 
       BluetoothAPP:这个应该也是属于java framework范畴,不过由于它比较特殊,所以独立出来,提供所有的上层服务以及与Bluedroid底层进行交互。其中btAdapter主要提供蓝牙的基本操作,比如enable, disable, discovery, pair, unpair, createRfcomm等,其他的就都是Profile的各自的Service了; 
       Bluedroid:蓝牙协议栈,提供所有蓝牙的实际操作,开关蓝牙,蓝牙的管理,搜索管理,链路管理,各种profile的实现,包括HCI,ACL,SCO,L2CAP,各种profile等; 
    这里Bluedroid分为三部分: 
       BTIF(Bluetooth Interface):提供所有Bluetooth.apk需要的API(使用HAL) 
       BTA(Bluetooth Application):蓝牙应用,一般指蓝牙的Profile的Bluedroid实现。 
       Stack:实现所有蓝牙底层的操作,其中还要分为btm(Bluetooth manager),btu(Bluetooth Upper Layer)等。

     

    2 Bluedroid软件介绍

    在第一节的bluetooth应用层框架图中,已可看到bluedroid的一个架构,但bluedroid与底层的接口就没表示出来。图2为bluedroid各层交互的框架图。

    这里写图片描述

    图2 bluedroid框架图
    下面再看一下bluedroid下的目录结构及每个目录的功能。

    这里写图片描述

    图3  bluedroid目录结构 
       audio_a2dp_hw: Implements hal for bluedroid a2dp audio device。 a2dp在bluedroid中的hal层实现。它通过socket与stack通信(通信机制实现参考udv目录下的uipc); 
       bta:buetooth application layer,实现应用层的一些接口,但都由Btif层进行管理和调用。 
    Ag:audio gateway (AG) subsystem of BTA 
    Ar:implementation for the audio/video registration module. 
    Av:implementation of the API for the advanced audio/video (AV) 
        *  subsystem of BTA, Broadcom’s Bluetooth application layer for mobile 
        *  phones. 
    Dm:API implementation file for the BTA device manager 
    Fs: implementation file for the file system call-in functions. //phone 
    Gattr: the GATT server and client implementation 
    Hh:host hid 
       btif:all BTIF functions accessed from main bluetooth HAL(与android的Bluetooth apk的jni层通信的接口,真正的为app提供interface的接口); 
       conf:是Bluedroid的一些配置文件; 
       embdrv: 主要负责sbc编码,SBC是由蓝牙特别兴趣组(SIG)提出的一种用于蓝牙设备标准音频编解码器的高效编码方法。在蓝牙技术的A2DP的音频数据规格中,SBC是用来保持互连能力的一个十分重要的音频数据编码方法,它是MP3和MPEG-4 AAC的规定选项; 
       gki/osi:general kernel interface/os interface,针对os的移植层,包括多任务和timer实现,实际就是为stack代码提供一个抽象的多任务和时间控制环境,达到可移植的目的; 
       hci:host control interface,实现hci的协议,并连接stack层与底层通信的实现; 
       main:处理配置信息,各个模块的初始化,连接btif与hci,提供btif控制hci的接口; 
       stack: 协议栈代码,各种profile; 
       udrv:代码作用是跟a2dp端进行socket通信,处理命令和a2dp数据pcm流,media task调用这里的接口,实际就是跟audio_a2dp_hw 的audio hal通信; 
       utils:杂项,很简单,目前就是提高a2dp任务优先级的函数; 
       vnd: vendor specific feature for BLE;

    其中还有一个bt vendor没包含在bluedroid中,对于realtek的蓝牙,都是使用相同的bluedroid,但不同的蓝牙模块有不同的bt vendor库,该vendor库的功能是给蓝牙模块上、掉电,打开、关闭、配置串口,download fw(usb接口蓝牙的download fw在驱动内实现)。

    2.1 Bluedroid对上层接口

    Bluedroid与上层有多个接口, bluedroid\btif\src\bluetooth.c为一个主要接口,负责蓝牙的开关及基本控制, bluedroid\audio_a2dp_hw\audio_a2dp_hw.c专门针对a2dp的控制,还有部分profile也提供一些接口,这些接口为不同profile的独立接口。其中bluetooth.c实现一系列接口,由上层调用来控制蓝牙,同时在初始化的时候,上层会传递过来一个回调接口,当bluedroid有消息或结果需要通知上层时,就通过该回调接口。但像蓝牙的opp、hid等profile的数据就不是通过接口传递的,都是创建socket接口来交互数据的。

    \bluedroid\btif\src\bluetooth.c
    static const bt_interface_t bluetoothInterface = {
        sizeof(bluetoothInterface),
        init,
        enable,
        disable,
        get_recv_byte,
        get_send_byte,
        cleanup,
        get_adapter_properties,
        get_adapter_property,
        set_adapter_property,
        get_remote_device_properties,
        get_remote_device_property,
        set_remote_device_property,
        get_remote_service_record,
        get_remote_services,
        start_discovery,
        cancel_discovery,
        create_bond,
        remove_bond,
        cancel_bond,
        get_connection_state,
        pin_reply,
        ssp_reply,
        get_profile_interface,
        dut_mode_configure,
        dut_mode_send,
    #if BLE_INCLUDED == TRUE
        le_test_mode,
    #else
        NULL,
    #endif
        config_hci_snoop_log,
        set_os_callouts,
        read_energy_info,
    };
    hardware\libhardware\include\hardware\bluetooth.h
    typedef struct {                                /* 蓝牙接口结构体定义 */
        /** set to sizeof(bt_interface_t) */
        size_t size;
        /**
         * Opens the interface and provides the callback routines
         * to the implemenation of this interface.
         */
        int (*init)(bt_callbacks_t* callbacks );

        /** Enable Bluetooth. */
        int (*enable)(void);

        /** Disable Bluetooth. */
        int (*disable)(void);
        /** Get Bluetooth recv */
        int (*get_recv_byte)(void);

        ……  /* 省略中间代码 */

        int (*read_energy_info)();
    } bt_interface_t;
    \bluedroid\btif\src\bluetooth.c
    static int init(bt_callbacks_t* callbacks )   /* 初始化时,上层传递下来的回调接口结构体 */
    {
    ALOGI(“init”);

    /* sanity check */
    if (interface_ready() == TRUE)
            return BT_STATUS_DONE;

    /* store reference to user callbacks */
        Bt_hal_cbacks = callbacks; 

        /* add checks for individual callbacks ? */

        bt_utils_init();

        /* init btif */
        btif_init_bluetooth();

        return BT_STATUS_SUCCESS;
    }
    hardware\libhardware\include\hardware\bluetooth.h
    /** Bluetooth DM callback structure. */           /* 回调结构体 */
    typedef struct {
        /** set to sizeof(bt_callbacks_t) */
        size_t size;
        adapter_state_changed_callback adapter_state_changed_cb;
        adapter_properties_callback adapter_properties_cb;
        remote_device_properties_callback remote_device_properties_cb;
        device_found_callback device_found_cb;
        discovery_state_changed_callback discovery_state_changed_cb;
        pin_request_callback pin_request_cb;
        ssp_request_callback ssp_request_cb;
        bond_state_changed_callback bond_state_changed_cb;
        acl_state_changed_callback acl_state_changed_cb;
        callback_thread_event thread_evt_cb;
        dut_mode_recv_callback dut_mode_recv_cb;
        le_test_mode_callback le_test_mode_cb;
        energy_info_callback energy_info_cb;
    } bt_callbacks_t;
    其中在get_profile_interface函数中会返回各种profile提供的接口。
    \bluedroid\btif\src\bluetooth.c
    static const void* get_profile_interface (const char *profile_id)
    {
        ALOGI("get_profile_interface %s", profile_id);
        /* sanity check */
        if (interface_ready() == FALSE)
            return NULL;
        /* check for supported profile interfaces */
        if (is_profile(profile_id, BT_PROFILE_HANDSFREE_ID))
            return btif_hf_get_interface();
        if (is_profile(profile_id, BT_PROFILE_HANDSFREE_CLIENT_ID))
            return btif_hf_client_get_interface();
        if (is_profile(profile_id, BT_PROFILE_SOCKETS_ID))          /* rfcomm使用 */
            return btif_sock_get_interface();
        if (is_profile(profile_id, BT_PROFILE_PAN_ID))
            return btif_pan_get_interface();
        if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID))
            return btif_av_get_src_interface();
        if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_SINK_ID))
            return btif_av_get_sink_interface();
        if (is_profile(profile_id, BT_PROFILE_HIDHOST_ID))
            return btif_hh_get_interface();
        if (is_profile(profile_id, BT_PROFILE_HEALTH_ID))
            return btif_hl_get_interface();
        if (is_profile(profile_id, BT_PROFILE_MAP_CLIENT_ID))
            return btif_mce_get_interface();
    #if ( BTA_GATT_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
        if (is_profile(profile_id, BT_PROFILE_GATT_ID))
            return btif_gatt_get_interface();
    #endif
        if (is_profile(profile_id, BT_PROFILE_AV_RC_ID))
            return btif_rc_get_interface();
        if (is_profile(profile_id, BT_PROFILE_AV_RC_CTRL_ID))
            return btif_rc_ctrl_get_interface();
        return NULL;
    }
        下面为使用rfcomm通信时的使用的接口:
    \bluedroid\btif\src\btif_sock.c
    static btsock_interface_t sock_if = {
                    sizeof(sock_if),
                    btsock_listen,
                    btsock_connect
           };
    btsock_interface_t *btif_sock_get_interface()
    {
        return &sock_if;
    }

    audio_a2dp_hw.c的接口就没有看到回调函数,但audio_a2dp_hw.c中创建了2个socket接口,一个用于控制命令,一个用于a2dp数据的传输。
    \bluedroid\audio_a2dp_hw\audio_a2dp_hw.c
    static int adev_open(const hw_module_t* module, const char* name,
                         hw_device_t** device)
    {
        ……  /* 省略中间代码 */
        adev->device.get_parameters = adev_get_parameters;
        adev->device.get_input_buffer_size = adev_get_input_buffer_size;
        adev->device.open_output_stream = adev_open_output_stream;
        adev->device.close_output_stream = adev_close_output_stream;
        adev->device.open_input_stream = adev_open_input_stream;
        adev->device.close_input_stream = adev_close_input_stream;
        adev->device.dump = adev_dump;
      ……  /* 省略中间代码 */

    static struct hw_module_methods_t hal_module_methods = {
        .open = adev_open,
    };

    struct audio_module HAL_MODULE_INFO_SYM = {
        .common = {
            .tag = HARDWARE_MODULE_TAG,
            .version_major = 1,
            .version_minor = 0,
            .id = AUDIO_HARDWARE_MODULE_ID,
            .name = "A2DP Audio HW HAL",
            .author = "The Android Open Source Project",
            .methods = &hal_module_methods,
        },
    };
    \bluedroid\audio_a2dp_hw\audio_a2dp_hw.c
    static int adev_open_input_stream(struct audio_hw_device *dev,
                                      audio_io_handle_t handle,
                                      audio_devices_t devices,
                                      struct audio_config *config,
                                      struct audio_stream_in **stream_in,
                                      audio_input_flags_t flags __unused,
                                      const char *address __unused,
                                      audio_source_t source __unused)
    {
        ……  /* 省略中间代码 */
        in->stream.common.set_parameters = in_set_parameters;
        in->stream.common.get_parameters = in_get_parameters;
        in->stream.common.add_audio_effect = in_add_audio_effect;
        in->stream.common.remove_audio_effect = in_remove_audio_effect;
        in->stream.set_gain = in_set_gain;
        in->stream.read = in_read;   /* 该函数会打开data socket */
        in->stream.get_input_frames_lost = in_get_input_frames_lost;

        /* initialize a2dp specifics */
        a2dp_stream_common_init(&in->common);

        *stream_in = &in->stream;
        a2dp_dev->input = in;

        a2dp_open_ctrl_path(&in->common);
    \bluedroid\audio_a2dp_hw\audio_a2dp_hw.c
    static void a2dp_open_ctrl_path(struct a2dp_stream_common *common)
    {
        int i;

        /* retry logic to catch any timing variations on control channel */
        for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
        {
            /* connect control channel if not already connected */
            if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0)
            {
    \bluedroid\audio_a2dp_hw\audio_a2dp_hw.c
    static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
                           size_t bytes)
    {
        …… /* 省略中间代码 */
        /* only allow autostarting if we are in stopped or standby */
        if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
            (in->common.state == AUDIO_A2DP_STATE_STANDBY))
        {
            pthread_mutex_lock(&in->common.lock);

            if (start_audio_datapath(&in->common) < 0)
    \bluedroid\audio_a2dp_hw\audio_a2dp_hw.c
    static int start_audio_datapath(struct a2dp_stream_common *common)
    {
        …… /* 省略中间代码 */
        /* connect socket if not yet connected */
        if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
        {
            common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);

     

    2.2 Bluedroid中HCI层接口

    Hci层处于bluedroid架构的最下面,向下与bt-vendor、内核交互,向上与bluedroid核心层交互。

     

    2.2.1 Bluedroid中HCI与bt-vendor接口

    Bluedroid与下层的交互接口全由hci目录的代码实现,在vendor.c文件中加载bt-vendor库,使用bt-vendor提供的接口,并把一个回调结构体传递给bt-vendor。
     

    \bluedroid\hci\src\vendor.c
    static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";   /* 固定的bt-vendor库名 */

    bool vendor_open(const uint8_t *local_bdaddr) {
      assert(lib_handle == NULL);

      lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
      if (!lib_handle) {
        ALOGE("%s unable to open %s: %s", __func__, VENDOR_LIBRARY_NAME, dlerror());
        goto error;
      }

      vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
      if (!vendor_interface) {
        ALOGE("%s unable to find symbol %s in %s: %s", __func__, VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
        goto error;
      }

    /* 调用bt-vendor的初始化并传递回调结构体 */
      int status = vendor_interface->init(&vendor_callbacks, (unsigned char *)local_bdaddr);  
    \bluedroid\hci\include\bt_vendor_lib.h
    typedef struct {                             /* bt-vendor提供的3个接口 */
        /** Set to sizeof(bt_vndor_interface_t) */
    size_t          size;

        /**
         * Caller will open the interface and pass in the callback routines
         * to the implemenation of this interface.
         */
        int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);

        /**  Vendor specific operations */
        int (*op)(bt_vendor_opcode_t opcode, void *param);

        /** Closes the interface */
        void  (*cleanup)(void);
    } bt_vendor_interface_t;
    \bluedroid\hci\src\vendor.c
    static const bt_vendor_callbacks_t vendor_callbacks = {    /* hci传递给bt-vendor的回调结构体 */
      sizeof(vendor_callbacks),
      firmware_config_cb,
      sco_config_cb,
      low_power_mode_cb,
      sco_audiostate_cb,
      buffer_alloc,
      buffer_free,
      transmit_cb,
      epilog_cb
    };

    Bt-vendor库中,init和cleanup函数只是做开始时初始化及退出时清理的工作,主要工作都在op函数中实现。
    \modules\rtl8723bs\libbt\src\bt_vendor_rtk.c
    static int op(bt_vendor_opcode_t opcode, void *param)
    {
        switch(opcode)
        {
            case BT_VND_OP_POWER_CTRL:
                ……  /* 省略中间代码 */       /* 控制蓝牙模块的上掉电 */
                break;
            case BT_VND_OP_FW_CFG:
    /* uart接口蓝牙加载fw */ 
    /* usb接口蓝牙fw在驱动中加载,蓝牙上电时就自动加载,这里直接返回成功 */
                ……  /* 省略中间代码 */ 
                break;
            case BT_VND_OP_SCO_CFG:
                ……  /* 省略中间代码 */
                break;
            case BT_VND_OP_USERIAL_OPEN:
    /* 打开uart口,把打开的fd传回给hci层。无论是uart接口蓝牙,还是usb接口蓝牙(usb接口蓝牙在驱动层虚拟出一个uart口),对bt-vendor层都是打开一个串口,所以从bluedroid层看,与底层的数据收发就是对uart口的收发  */
                ……  /* 省略中间代码 */
                break;
            case BT_VND_OP_USERIAL_CLOSE:
                ……  /* 省略中间代码 */         /* 关闭uart口 */
                break;
            case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
                ……  /* 省略中间代码 */
                break;
            case BT_VND_OP_LPM_SET_MODE:
                ……  /* 省略中间代码 */
                break;
            case BT_VND_OP_LPM_WAKE_SET_STATE:
                ……  /* 省略中间代码 */
                break;
            case BT_VND_OP_EPILOG:            
    ……  /* 省略中间代码 */
                break;
        }
    \bluedroid\hci\src\userial.c
    bool userial_open(userial_port_t port) {
        /* hci层调用bt-vendor层打开uart口,返回uart口句柄,hci层对数据的收发就使用该句柄 */
    ……  /* 省略中间代码 */

        int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array);

        if (num_ports != 1) {
            ALOGE("%s opened wrong number of ports: got %d, expected 1.", __func__, num_ports);
            goto error;
        }

        userial_cb.fd = fd_array[0];

    2.2.2 Bluedroid中HCI层协议

    Hci层有两个功能,一个为实现hci层协议,就是所见的h4、h5协议,另一个为连接stack层与bt-vendor层,实现stack层与硬件的通信传递。 
    HCI有4种分组类型(有资料介绍通过uart传输时,还有错误消息分组和协商分组,但从现在的代码看,都没有使用了,只是增加了厂商自定义的操作码,用于发送错误消息或协商通信等),分组类型如表1,4种分组的数据格式如图4~图7。

    表1  HCI封包类型 
    这里写图片描述

    这里写图片描述

    这里写图片描述

    HCI本身的分组是不带包类型识别头的,在传输的时候就需要双方能识别出传输的分组类型,h4的协议就是在hci分组前增加一个字节的用于区别分组类型,现在使用的boardcom的蓝牙就是使用h4协议通过uart传输。从上面的各种分组结构看,都没有唯一的识别标志,在通过uart传输时,由于共用一个通道,就有数据同步问题,否则就无法找到分组头及解析数据分组。所以h4协议使用uart传输时,就需要有Error Recovery机制,只要通信双方有一个丢失同步,就需要进行同步恢复。如果h4协议使用usb传输,就不会存在该问题,usb通过不同的端点传输不同的分组类型,并且usb协议可以保证分组的完整。由于h4使用uart传输存在同步问题,后面有了h5协议,h5协议其实就是把h4协议的包重新封装一下,加入字符转换来实现唯一的分组头、分组尾标识,同时加入完整性校验,这样,即使一个分组数据出错了,下一个分组数据还是能正确解析的,不需要什么同步恢复机制。H5的封包如图8~图10。 
     

    这里写图片描述

    从上面可以看出,H5协议比H4协议在可靠性方面有增强,但同时需要处理的工作量也增多了,所以H5的传输效率会比H4低一些。
    H4或H5的协议都提供相同的使用接口,HCI层实际使用哪种协议,现在bluedroid的做法是在代码编译的时候就固定的,如下面代码所示。

    \bluedroid\hci\src\bt_hci_bdroid.c
    static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
    {
        …… /* 省略中间代码 */

        vendor_open(local_bdaddr);           /* 加载bt-vendor库 */

        utils_init();
    #ifdef HCI_USE_MCT
        extern tHCI_IF hci_mct_func_table;
        p_hci_if = &hci_mct_func_table;     
    #elif defined HCI_USE_RTK_H5
        extern tHCI_IF hci_h5_func_table;
        p_hci_if = &hci_h5_func_table;      /* 使用h5协议 */
    #else
        extern tHCI_IF hci_h4_func_table;
        p_hci_if = &hci_h4_func_table;      /* 使用h4协议 */
    #endif
    \bluedroid\hci\include\hci.h
    typedef struct {                  /* h4,h5的结构体 */
        tHCI_INIT init;
        tHCI_CLEANUP cleanup;
        tHCI_SEND send;     /* 发送接口 */
        tHCI_SEND_INT send_int_cmd;    /* 为厂商专用发送接口 */
        tHCI_ACL_DATA_LEN_HDLR get_acl_max_len;
    #ifdef HCI_USE_MCT
        tHCI_RCV evt_rcv;
        tHCI_RCV acl_rcv;
    #else
        tHCI_RCV rcv;     /* 接收接口 */
    #endif
    } tHCI_IF;
     

    2.2.3 Bluedroid中HCI与核心层接口

    Hci层与bluedroid的核心层的交互接口,也是通过把接口封装在一个结构体提供给核心层,同时核心层提供一个回调的结构体。

    \bluedroid\hci\src\bt_hci_bdroid.c
    static const bt_hc_interface_t bluetoothHCLibInterface = {
        sizeof(bt_hc_interface_t),
        init,            /* 加载bt-vendor库,选择使用的hci层协议 */
        set_power,      /* 蓝牙上掉电控制 */ 
        lpm,
        preload,        /* 打开uart,加载fw */
        postload,
        transmit_buf,     /* 发送数据 */
        logging,
        cleanup, 
        tx_hc_cmd,
    };

    const bt_hc_interface_t *bt_hc_get_interface(void)     /* 获取hci接口的结构体 */
    {
        return &bluetoothHCLibInterface;
    }
    \bluedroid\main\bte_main.c
    static void bte_main_in_hw_init(void)
    {
        if ( (bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()) \
             == NULL)

      …… /* 省略中间代码 */

    static void bte_hci_enable(void)
    {
        APPL_TRACE_DEBUG("%s", __FUNCTION__);

        preload_start_wait_timer();

        if (bt_hc_if)
    {
           /* 初始化hci接口,传递回调结构体 */
            int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);  
    \bluedroid\hci\include\bt_hci_lib.h
    typedef struct {
        /** set to sizeof(bt_hc_callbacks_t) */
        size_t         size;
        /* notifies caller result of preload request */
        preload_result_cb  preload_cb;
        /* notifies caller result of postload request */
        postload_result_cb  postload_cb;
        /* notifies caller result of lpm enable/disable */
        lpm_result_cb  lpm_cb;
        /* notifies hardware on host wake state */
        hostwake_ind_cb       hostwake_ind;
        /* buffer allocation request */
        alloc_mem_cb   alloc;
        /* buffer deallocation request */
        dealloc_mem_cb dealloc;
        /* notifies stack data is available */
        data_ind_cb data_ind;       /* hci层往上提交数据接口 */
        /* notifies caller when a buffer is transmitted (or failed) */
        tx_result_cb  tx_result;
    } bt_hc_callbacks_t;
     

    2.2.4 Bluedroid中HCI层流程例子

    如图11为HCI层初始化的流程,包含接口的初始化,给蓝牙上电,打开串口,加载fw,由于加载fw过程涉及多重回调,没放到下面的框图。

    这里写图片描述

    这里写图片描述

    这里写图片描述

    2.3 Bluedroid的核心层

    Bluedroid的核心层负责蓝牙的管理,蓝牙协议的处理,状态的管理等,整个核心层的运行都是由事件驱动的,由上层发送的事件,底层处理结果的事件,底层接收数据的事件,底层状态变化的事件,加上定时器的超时事件,维护着整个核心层的正常运行。由于蓝牙核心层还不能很好理清流程及整理一个直观的框图,这里没给出核心层的架构图,后面从代码流程及整体的运行流程从侧面了解一下核心层的架构。
     

    2.3.1 Bluedroid核心层的启动

    Bluedroid的整个功能及运行,都是从enable Bluetooth开始,到disable Bluetooth结束。

    \bluedroid\btif\src\bluetooth.c
    static int init(bt_callbacks_t* callbacks )
    {
        …… /* 省略中间代码 */
        bt_utils_init();

        /* init btif */
        btif_init_bluetooth();

        return BT_STATUS_SUCCESS;
    }
    \bluedroid\btif\src\btif_core.c
    bt_status_t btif_init_bluetooth()
    {
        UINT8 status;
        btif_config_init();        /* 配置初始化 */
        bte_main_boot_entry();   /* Entry point for BTE chip/stack initialization */

        /* As part of the init, fetch the local BD ADDR */
        memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t));
        btif_fetch_local_bdaddr(&btif_local_bd_addr);

        /* start btif task */
        status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,
                    (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),
                    sizeof(btif_task_stack));

        if (status != GKI_SUCCESS)
            return BT_STATUS_FAIL;

        return BT_STATUS_SUCCESS;
    }
    \bluedroid\btif\src\bluetooth.c
    static int enable( void ) 
    {
        ALOGI("enable");

        /* sanity check */
        if (interface_ready() == FALSE)
            return BT_STATUS_NOT_READY;

        return btif_enable_bluetooth();
    }
    \bluedroid\btif\src\btif_core.c
    bt_status_t btif_enable_bluetooth(void)
    {
        …… /* 省略中间代码 */
        /* Create the GKI tasks and run them */
        bte_main_enable();

        return BT_STATUS_SUCCESS;
    }
    \bluedroid\main\bte_main.c
    void bte_main_enable()
    {
        APPL_TRACE_DEBUG("%s", __FUNCTION__);

        /* Initialize BTE control block */
        BTE_Init();

        lpm_enabled = FALSE;

        GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
                        (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
                        sizeof(bte_btu_stack));

        bte_hci_enable();   /* 初始化hci层接口,上一节内容 */

        GKI_run();
    }
    \bluedroid\stack\btu\btu_task.c
    BTU_API UINT32 btu_task (UINT32 param)          /* 初始化工作及进行消息处理 */
    {
        …… /* 省略中间代码 */
        /* Initialize the mandatory core stack control blocks
           (BTU, BTM, L2CAP, and SDP)
         */
        btu_init_core();

        /* Initialize any optional stack components */
        BTE_InitStack();

    #if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
        bta_sys_init();
    #endif

        /* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init()
         * reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL
         */
    #if ( BT_USE_TRACES==TRUE )
        BTE_InitTraceLevels();
    #endif

        /* Send a startup evt message to BTIF_TASK to kickstart the init procedure */
        GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);

        prctl(PR_SET_NAME, (unsigned long)"BTU TASK", 0, 0, 0);

        raise_priority_a2dp(TASK_HIGH_BTU);

        /* Wait for, and process, events */
        for (;;)
    \bluedroid\btif\src\btif_core.c
    void btif_enable_bluetooth_evt(tBTA_STATUS status, BD_ADDR local_bd)  
    {   /* Bluetooth enable完成时收到事件,会调用该函数 */
        …… /* 省略中间代码 */
        bte_main_postload_cfg();
    #if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
        bte_main_enable_lpm(TRUE);
    #endif
        /* add passing up bd address as well ? */

        /* callback to HAL */
        if (status == BTA_SUCCESS)
        {
            /* initialize a2dp service */
            btif_av_init();

            /* init rfcomm & l2cap api */
            btif_sock_init();

            /* init pan */
            btif_pan_init();

            /* load did configuration */
            bte_load_did_conf(BTE_DID_CONF_FILE);
    \bluedroid\btif\src\btif_av.c
    bt_status_t btif_av_init()
    {
        if (btif_av_cb.sm_handle == NULL)
        {
            if (btif_a2dp_start_media_task() != GKI_SUCCESS)
                return BT_STATUS_FAIL;

            btif_enable_service(BTA_A2DP_SERVICE_ID);

            /* Also initialize the AV state machine */
            btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);

            btif_a2dp_on_init();
    \bluedroid\btif\src\btif_media_task.c
    int btif_a2dp_start_media_task(void)
    {
        …… /* 省略中间代码 */
        /* start a2dp media task */
        retval = GKI_create_task((TASKPTR)btif_media_task, A2DP_MEDIA_TASK,
                    A2DP_MEDIA_TASK_TASK_STR,
                    (UINT16 *) ((UINT8 *)a2dp_media_task_stack + A2DP_MEDIA_TASK_STACK_SIZE),
                    sizeof(a2dp_media_task_stack));
     

    前面说到整个蓝牙核心层由事件驱动,所有事件的处理全部由3个task来完成。 
    btu_task:处理发送给上层的事件,定时器超时事件,部分上层发送下来的事件,同时也会把部分事件转给btif_task处理; 
    btif_task:主要用于蓝牙协议处理,处理协议状态的流转,根据不同状态调用不同的处理函数; 
    btif_media_task:用于a2dp的控制及音频处理;
     

    2.3.2 Bluedroid核心层部分profile的流程

    对于A2DP的流程,只给出概要框图,如下图所示。

    这里写图片描述

    对于opp文件传输,在bluedroid层就是使用rfcomm协议,rfcomm协议实质就是在两个蓝牙设备之间提供一条逻辑的数据通道,上层只需要使用rfcomm提供的链路就可以在两个蓝牙设备之间传递数据。Opp文件传输过程,先是两个设备进行连接,然后建立一条rfcomm通道,同时创建rfcomm与上层传输数据的socket,后面就可以进行数据传输,设备的连接、rfcomm通道的建立在后面介绍。 
        对于蓝牙鼠标、蓝牙键盘这些输入设备,使用的是hid(human interface Device)profile,建立连接后,注册一个uhid(dev_path = “/dev/uhid”)设备,把输入设备发送过来的数据发给uhid设备,由内核的hid驱动负责进行输入事件的处理,下图给出一个输入数据的流程框图。
     

    3 Bluetooth应用程序介绍(Bluetooth.apk)

    Bluetooth应用程序的主要功能是负责蓝牙状态的管理,连接bluedroid,提供各种蓝牙服务。其中btservice提供蓝牙基本服务,各个profile提供自身独立的服务,除了opp和pabp自成一体外,其它的profile由btservice管理。

     

    3.1 Bluetooth应用程序框图及对外的接口

    由于opp与pbap实质都是文件传输,但涉及UI交互操作等,作为两个相对独立的service存在,后面给出opp的一个框架。
     

    这里写图片描述

     

    这里写图片描述

    3.2 Bluetooth应用程序与bluedroid的接口

    Bluetooth app与bluedroid通过jni接口交互,bluetooth app在开始时加载bluedroid库(bluetooth.default.so),使用bluedroid提供的操作接口,同时在调用bluedroid接口提供的init函数时,传递回调结构体给bluedroid。

    packages\apps\bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
    jint JNI_OnLoad(JavaVM *jvm, void *reserved) 
    {
        …… /* 省略中间代码 */
        if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
            ALOGE("jni adapter service registration failure, status: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
            ALOGE("jni hfp registration failure, status: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {
            ALOGE("jni hfp client registration failure, status: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
            ALOGE("jni a2dp source registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) {
            ALOGE("jni a2dp sink registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
            ALOGE("jni avrcp target registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_avrcp_controller(e)) < 0) {
            ALOGE("jni avrcp controller registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
            ALOGE("jni hid registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
            ALOGE("jni hdp registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
            ALOGE("jni pan registration failure: %d", status);
            return JNI_ERR;
        }
        if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
            ALOGE("jni gatt registration failure: %d", status);
            return JNI_ERR;
        }
    packages\apps\bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
    static JNINativeMethod sMethods[] = {        /* 各个Native接口 */
        /* name, signature, funcPtr */
        {"classInitNative", "()V", (void *) classInitNative},
        {"initNative", "()Z", (void *) initNative},
        {"cleanupNative", "()V", (void*) cleanupNative},
        {"enableNative", "()Z",  (void*) enableNative},
        {"disableNative", "()Z",  (void*) disableNative},
        {"getRecvByteNative", "()I",  (void*) getRecvByteNative},
        {"getSendByteNative", "()I",  (void*) getSendByteNative},
        {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
        {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
        {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
        {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
        {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
        {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
        {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
        {"createBondNative", "([BI)Z", (void*) createBondNative},
        {"removeBondNative", "([B)Z", (void*) removeBondNative},
        {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
        {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
        {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
        {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
        {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
        {"getRemoteMasInstancesNative", "([B)Z", (void*) getRemoteMasInstancesNative},
        {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
        {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
         (void*) createSocketChannelNative},
        {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
        {"alarmFiredNative", "()V", (void *) alarmFiredNative},
        {"readEnergyInfo", "()I", (void*) readEnergyInfo},
    };

    int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
    {
        return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
                                        sMethods, NELEM(sMethods));
    }
    packages\apps\bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
    static bool initNative(JNIEnv* env, jobject obj) {
        ALOGV("%s:",__FUNCTION__);

        sJniAdapterServiceObj = env->NewGlobalRef(obj);
        sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

        if (sBluetoothInterface) {
            int ret = sBluetoothInterface->init(&sBluetoothCallbacks);    /* 传递给bluedroid的回调接口 */
     

    3.3 Bluetooth 的状态图

    整个bluetooth存在多个状态机,除了有维护蓝牙开关的状态机及设备配对状态,还有部分profile使用状态机维护设备的连接状态。

    这里写图片描述

    这里写图片描述

    蓝牙Bond状态说明:

     

        /**
         * Indicates the remote device is not bonded (paired).
         * <p>There is no shared link key with the remote device, so communication
         * (if it is allowed at all) will be unauthenticated and unencrypted.
         */
        public static final int BOND_NONE = 10;
        /**
         * Indicates bonding (pairing) is in progress with the remote device.
         */
        public static final int BOND_BONDING = 11;
        /**
         * Indicates the remote device is bonded (paired).
         * <p>A shared link keys exists locally for the remote device, so
         * communication can be authenticated and encrypted.
         * <p><i>Being bonded (paired) with a remote device does not necessarily
         * mean the device is currently connected. It just means that the pending
         * procedure was completed at some earlier time, and the link key is still
         * stored locally, ready to use on the next connection.
         * </i>
         */
        public static final int BOND_BONDED = 12;
     

    两台平板配对,配对完成后,处于已配对状态,但还不是连接的状态,当需要传输文件时,才建立连接,文件传输完成后,连接会断开。
     当平板与蓝牙耳机或蓝牙输入设备(蓝牙鼠标、键盘)配对时,配对完成后,马上会建立连接,这是由于蓝牙耳机或输入设备随时有数据传输。

    这里写图片描述

    3.4 Bluetooth 部分操作的流程图

    这里写图片描述

    这里写图片描述

     

    4 Bluetooth framework层介绍

    Bluetooth framework层的作用只要是连接bluetooth service,为其它应用提供使用蓝牙的接口,起连接上下层的作用,没有太多的逻辑,下面只给出概要框图,不做过多描述。

    这里写图片描述

     

     

     

     

     

    展开全文
  • 目录 ESP32蓝⽛架构 BLUEDROID主机架构 BLUEDROID协议栈下HCI线程的数据处理流程。 ESP32蓝⽛架构 在 ESP32 的系统上,选择 BLUEDROID 为蓝⽛牙主机,并通过 VHCI(软件实现的虚拟 HCI 接⼝口)接⼝口,访问控制器器...

    目录

     

    ESP32蓝⽛架构

    BLUEDROID主机架构

    BLUEDROID协议栈下HCI线程的数据处理流程。


    ESP32蓝⽛架构

    在 ESP32 的系统上,选择 BLUEDROID 为蓝⽛牙主机,并通过 VHCI(软件实现的虚拟 HCI 接⼝口)接⼝口,访问控制器器。此场景下,BLUEDROID 和控制器器都运⾏在同⼀宿主上(即 ESP32 芯⽚)

    ESP-IDF 的默认运⾏行行环境为双核 FreeRTOS,ESP32 的蓝⽛牙可按照功能分为多个任务(task) 运⾏,不同任务的优先级也有不同,其中优先级最⾼高的为运⾏控制器的任务。控制任务对实时性的要求较⾼,在 FreeRTOS 系统中的优先级仅次于 IPC 任务(IPC 任务⽤于双核 CPU 的进程间通信)。BLUEDROID(ESP-IDF 默认蓝⽛牙主机)共包含 4 个任务,
    分别运行 BTC、BTU、HCI UPWARD,及 HCI DOWNWARD。

    BLUEDROID主机架构

    从上图可以看到,BLUEDROID 内部⼤致分为 2 层:BTU 层和 BTC 层(除去 HCI ),每个层都有对应的任务来处理。

    BTU 层主要负责蓝牙主机底层协议栈的处理,包括L2CAP、GATT/ATT、SMP、GAP 以及部分规范等,并向上提供以“bta”为前缀的接口;
    BTC 层主要负责向应⽤用层提供接⼝支持、处理理基于 GATT 的规范、处理杂项等,并向应⽤层提供以“esp”为前缀的接⼝。所有的 API 都在 ESP_API 层,开发者应当使⽤“esp”为前缀的蓝⽛牙 API(特殊的除外)。
    上图并未详细描述 HCI 部分,⽽事实上,HCI 具有 2 个任务(⾄少在 ESP-IDF V2.1 以前),分别处理 Downward 和 Upward 的数据。
    此框架的其中一条设计思路路是尽量量将蓝⽛牙相关的任务交给 BTC 来处理,从而避免和降低用户任务 (User Task) 的负载,也使结构上更加简洁。
    经典蓝⽛牙的部分规范,如 RFCOMM、A2DP 等,中层次偏协议偏底层的部分运行在 BTU 层,偏控制流程的以及需要提供 ESP-API 的运行在 BTC 层。
    蓝⽛牙低功耗的部分规范或偏底层的功能,如 6LowPan 或 Dynamic L2CAP Channel 的功能,将运行在 BTU 层,再通过 BTC 向应⽤层提供 ESP-API。

    BLUEDROID协议栈下HCI线程的数据处理流程。

    跟HCI相关的接口文件

    • hci_layer.c

    • hci_hal_h4.c

    ##### 初始化流程--- hci_start_up()
    
    static void bte_main_enable(void)
    {
        APPL_TRACE_DEBUG("Enable HCI\n");
        if (hci_start_up()) {
            APPL_TRACE_ERROR("Start HCI Host Layer Failure\n");
            return;
        }
    ​
        //Now Test Case Not Supported BTU
        BTU_StartUp();
    }
    ​
    int hci_start_up(void)
    {
        packet_fragmenter->init(&packet_fragmenter_callbacks); //分包与重组相关,发送相关
        hal->open(&hal_callbacks, hci_host_thread);//hal_callbacks()接收数据处理
    ​
    }
    hal_callbacks()
    -------->>>>hal_says_packet_ready()
    --------------------btu_task_post(SIG_BTU_HCI_MSG, packet)  //发送BTU层处理
    
    
    关于hal 和packet_fragmenter结构体初始化
    
    ​
    const hci_t *hci_layer_get_interface(void)
    {
        hal = hci_hal_h4_get_interface();   
        packet_fragmenter = packet_fragmenter_get_interface();
    ​
        init_layer_interface();
        return &interface;
    }
    ​
    ​
    ​
    static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thread)
    {
        assert(upper_callbacks != NULL);
        assert(task_thread != NULL);
       ##HAL-open---真实引用处理(callbacks 实际就是上层处理函数 hal_callbacks)
       
        callbacks = upper_callbacks;
    #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
        hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, BLE_ADV_REPORT_FLOW_CONTROL_NUM + L2CAP_HOST_FC_ACL_BUFS + QUEUE_SIZE_MAX); // adv flow control num + ACL flow control num + hci cmd numeber
    #else
        hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, QUEUE_SIZE_MAX);
    #endif
    ​
        hci_h4_thread = (osi_thread_t *)task_thread;
    ​
        //register vhci host cb
        //HCI交互消息接收的处理函数vhci_host_cb注册回调
        if (esp_vhci_host_register_callback(&vhci_host_cb) != ESP_OK) {
            return false;
        }
    ​
        return true;
    }
    ​
    static const esp_vhci_host_callback_t vhci_host_cb = {
        .notify_host_send_available = host_send_pkt_available_cb,
        .notify_host_recv = host_recv_pkt_cb,
    };
    ​
    
    
    HCI接口:RX接收处理
    
    static void hci_hal_env_init(
        size_t buffer_size,
        size_t max_buffer_count)
    {
        assert(buffer_size > 0);
        assert(max_buffer_count > 0);
    ​
        hci_hal_env.buffer_size = buffer_size;
        hci_hal_env.adv_free_num = 0;
    ​
        hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
        if (hci_hal_env.rx_q) {
            fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes);//注册接收处理
        } else {
            HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__);
        }
    ​
        return;
    }
    
    
    再结合上面流程,所有HCI接收的消息都会回调event_uart_has_bytes()进行处理
    
    static void event_uart_has_bytes(fixed_queue_t *queue)
    {
        BT_HDR *packet;
        while (!fixed_queue_is_empty(queue)) {
            packet = fixed_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
            hci_hal_h4_hdl_rx_packet(packet);
        }
    }
    //流程
    hci_hal_h4_hdl_rx_packet()
    -------->>>> callbacks->packet_ready(packet);此接口就是上层流程初始化引入Callback,将数据传给BTU
    ​
    ​
    
    
    HCI接口:TX接收处理
    
    
    
    看代码可以发现,event_command_ready和event_packet_ready 他们都会调用同一个接口来发送数据,packet_fragmenter模块里面的:
    
    static int hci_layer_init_env(void)
    {
          fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready);
          fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready);
    }
     //都会调用同一个接口如下:
     //packet_fragmenter->fragment_and_dispatch(wait_entry->command);
    也就是说,所有的数据都会先进行fragment以及dispatch的过程,我们这里主要关注数据的流向,那么也就是dispatch的流程:
    
    static void fragment_and_dispatch(BT_HDR *packet) 
    { 
      callbacks->fragmented(packet, true);
    }
    发现最后是通过回调函数来发送,追到真实的发送函数如下,hal的相关的接口:
    
    // Callback for the fragmenter to send a fragment
    static void transmit_fragment(BT_HDR *packet, bool send_transmit_finished)
    {
        uint16_t event = packet->event & MSG_EVT_MASK;
        serial_data_type_t type = event_to_data_type(event);
    ​
        hal->transmit_data(type, packet->data + packet->offset, packet->len);
    ​
        if (event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished) {
            osi_free(packet);
        }
    }
    ​
    static uint16_t transmit_data(serial_data_type_t type,
                                  uint8_t *data, uint16_t length)
    {
        uint8_t previous_byte;
    ​
        assert(data != NULL);
        assert(length > 0);
    ​
        if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
            HCI_TRACE_ERROR("%s invalid data type: %d", __func__, type);
            return 0;
        }
    ​
        // Write the signal byte right before the data
        --data;
        previous_byte = *data;
        *(data) = type;
        ++length;
    ​
        BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
    ​
        // TX Data to target
        esp_vhci_host_send_packet(data, length);
    ​
        // Be nice and restore the old value of that byte
        *(data) = previous_byte;
    ​
        return length - 1;
    }
    ​
    最后总结一下hci_thread处理的数据流程:
    1. 当hci向下发送数据的时候,会将数据放置到packet_queue,然后调用到fragment_and_dispatch,然后经过esp_vhci_host_send_packet(data, length);,最后抵达controller

    2. 当controller有数据上传的时候,hci_thread会一直poll这个节点,调用 hal_says_data_ready读出数据,数据经过 event_uart_has_bytes 将数据送到btu_hci_msg_queue,然后由btu 线程继续处理。

     

     

     

    展开全文
  • Android BlueDroid(一):BlueDroid概述

    千次阅读 2018-12-25 14:14:13
    (6)、bluedroid 整体协议栈架构: 整个系统的架构很简单,因为大多的事情都是在Bluedroid层里面做的,上层只管去Call和Callback就是了,这部分我们在后面分析代码做详细分析。 2、BlueZ 代码架构 和...

    https://blog.csdn.net/xubin341719/article/details/40378205

    一、名词解释:(有用信息增加中……)

    BTI F: Bluetooth Interface

    BTU : Bluetooth Upper Layer

    BTM: Bluetooth Manager

    BTE  :Bluetooth embedded system

    BRBTA  :Blueetooth application layerCO: call out\CI: call inHF : Handsfree ProfileHH: HID Host ProfileHL: Health Device ProfileAV:audio\vidioag: audio gateway ar: audio/video registrationgattc: GATT clientBLE:二、       BlueDroid  &&  BlueZ Android 4.2之前,Google一直使用的是Linux官方蓝牙协议栈BlueZ。BlueZ实际上是由高通公司在2001年5月基于GPL协议发布的一个开源项目,做为Linux 2.4.6内核的官方蓝牙协议栈。随着Android设备的流行,BlueZ也得到了极大的完善和扩展。例如Android 4.1中BlueZ的版本升级为4.93,它支持蓝牙核心规范4.0,并实现了绝大部分的Profiles。 从Android 4.2开始,Google便在Android源码中推出了它和博通公司一起开发的BlueDroid以替代BlueZ。BlueZ的创始者,高通公司也将在基于其芯片的Android参考设计中去除BlueZ,支持BlueDroid。 相比BlueZ,BlueDroid最值得称道的地方就是其框架结构变得更为简洁和清晰。对我们工程师来说这也是个不错的福利,清晰、简洁的架构使我们在debug过程中思路更清晰;1、Android 4.2中BlueDroid的框架结构图:(Google官方提供)。

    (1)、应用程序通过android.bluetooth package下的API来调用系统的Bluetooth功能。

    (2)、应用层空间增加了一个名为Bluetooth的App。它做为系统的bluetooth核心进程而存在。其内部将通过JNI来调用Bluetooth HAL层以完成各种蓝牙请求。

    (3)、Bluetooth HAL也属于Android 4.2新增模块,它由蓝牙核心规范硬件抽象层和蓝牙应用规范硬件抽象层组成。由于HAL层的隔离作用,上层代码可轻松移植到不同芯片平台。

    (4)、作为整个蓝牙服务的核心,Bluetooth Stack模块则由Bluetooth Application Layer(缩写为BTA)和Bluetooth Embedded System(缩写为BTE)两大部分组成。BTA实现了蓝牙设备管理、状态管理及一些应用规范。而BTE则通过HCI与厂商蓝牙芯片交互以实现了蓝牙协议栈的通用功能和相关协议。另外,BTE还包括一个统一内核接口(GKI),蓝牙芯片厂商可借助GKI快速轻松得移植蓝牙协议栈到其他操作系统或手机平台上。

    (5)、Vendor Extentions(厂商扩展):开发者可以添加自定义扩展以实现厂商特定的模块和组件。

    (6)、bluedroid 整体协议栈架构: 整个系统的架构很简单,因为大多的事情都是在Bluedroid层里面做的,上层只管去Call和Callback就是了,这部分我们在后面分析代码做详细分析。

    2、BlueZ 代码架构 和Bluedroid类似,BlueZ也是按照标准流程从应用一直走下来,不过两者唯一的区别是BlueZ的DBUS。blueDroid中取出DBUS是代码结构变的更加清晰,看起来跟顺畅。如下图蓝牙代码架构(Google官方提供):

    3、BlueDrod  PK  BlueZ      BlueDroid虽然对BlueZ大有取而代之的趋势,但现在它对蓝牙应用规范的支持还不够完善。例如BlueDroid仅支持AVRCP 1.0,而非最新的AVRCP 1.5。所以,国内某些芯片或手机厂商若能及早完成BlueZ相关模块到BlueDroid的移植工作,相信能帮助它们在竞争日趋白日化的移动世界中拔得先机。另外,作为一种成熟、低功耗无线通信技术的先锋,蓝牙未来在可穿戴设备领域中也将扮演越来越重要的作用。
    ---------------------
    作者:xubin341719
    来源:CSDN
    原文:https://blog.csdn.net/xubin341719/article/details/40378205
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • BlueDroid源码详细分析

    2019-07-30 11:27:06
    1.整体架构 1.1 名词解释 HAL :HardwareAbstraction Layer Btif :Bluetoothinterface Bta :Bluetoothapplication Btu :Bluetoothuper layer ...Bte :Bluetoothembedded layer ...Btm :Bluetooth devicemanager ...
  • Bluedroid: 蓝牙协议栈源码剖析

    千次阅读 2019-01-07 19:31:50
    BTE:bluedroid的内部处理,又细分为BTA,BTU,BTM和HCI BTA:bluedroid中各profile的逻辑实现和处理 BTU:承接BTA与HCI BTM:蓝牙配对与链路管理 HCI:读取或写入数据到蓝牙hw 二、代码分析(写...
  • Bluedroid中的线程介绍

    千次阅读 2017-09-22 17:29:22
    Bluedroid中的线程介绍 版权所有,转载时请注明出处 luowh0822@outlook.com本文基于android O的代码进行分析。通过本文档,能够了解bluedroid的线程结构和协议栈架构。线程的基本用法osi/src/thread.cc 对posix的...
  • 安卓系统蓝牙协议栈 bluedroid 使能流程分析 本文承接上篇文章《安卓中蓝牙系统服务层的使能流程分析》,接续分析协议栈层相关的使能流程,所以蓝牙协议栈bluedroid的使能始于JNI层enableNative()中调用协议栈接口...
  • Bluedroid: 蓝牙协议栈源码剖析 一、 基础知识介绍 1.缩略语 BTIF: Bluetooth Interface  BTU : Bluetooth Upper Layer  BTM: Bluetooth Manager  BTE: Bluetooth embedded system  BTA :Blueetooth ...
  • BlueDroid软件协议栈架构

    千次阅读 2019-02-21 12:42:27
    android蓝牙 架构 组件 说明 ...■实现JNI调用调用的HAL接口■维护JNI注册的回调■根据蓝牙应用层(BTA)堆栈的回调调用JNI回调■提供应用...BlueDroid堆栈 实现核心堆栈和协议 HCI层 ■构建为共享库(libbt-hci)
  • BlueDroid介绍

    千次阅读 2015-12-10 15:22:03
    自从Android 4.2开始,Android开始使用自己的蓝牙协议栈BlueDroid,而不是bluez BlueDroid可分为两层:  - BTE: Bluetooth Embedded System  - BTA: Bluetooth Application Layer BTE实现了核心的蓝牙功能...
  • 版权声明:本文为博主原创文章,未经博主允许不得转载。...关键词:bluedroid bluez 作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!) 欢迎指正错误,共同学习、共同进步!! 一、名词解释:(有用信息...
  • bluedroid a2dp sink播放流程

    千次阅读 2019-05-21 19:35:47
    路径为:/data/misc/bluedroid/output_sample.pcm 来数据时 bta_av_sink_data_cback 发送 BTA_AV_SINK_MEDIA_DATA_EVT 事件, bta_av_sink_data_cback 这里可以将frame number :p_pkt->layer_specific打印出来,...
  • bluedroid thread

    2018-10-07 12:15:52
    bluedroid的消息传递机制 1 创建一个队列: btu_bta_msg_queue = fixed_queue_new(SIZE_MAX); fixed_queue_t *ret = osi_calloc(sizeof(fixed_queue_t)); //队列里面最大的容量 ret-&gt;capacity = capacity...
  • 要完全分析清楚估计得花老长时间了,先一步步来吧,BlueDroid 代码结构BlueDroid 扫描的调用流程BlueDroid 的一些重要数据结构BlueDroid 代码结构先看下Android 里BlueDroid里的代码结构: 很多目录吧,...
  • Android Bluedroid source code analysis 图1:应用层到协议层 Android的bt整体结构如图1所示: 应用层:使用蓝牙协议的各种应用,例如:蓝牙电话、音乐等。 Framework层:主要是android系统向应用层开放...
  • Bluedroid 的代码结构分析 system/bt 的主要文件结构及相应功能介绍如下。 main bte_main.cc 该功能涉及BTE核心栈的初始化和卸载。 bte_main_in_hw_init:负责芯片硬件的初始化 bte_main_boot_entry:调用 GKI_init...
  • BlueDroid HFP 源码分析笔记(1)

    千次阅读 2020-07-16 14:18:33
    BlueDroid 代码分析 对部分代码一眼无法知道运行结果的地方备注。 HPF Connect 可以理解为闭包吧!将参数和方法打包在一起传入队列中等待执行。最终执行的就是 connect_init(),参数就是bd_addr, connect_init。 ...
  • 关键词:bluedroid enableNative BTIF_TASK BTU_TASK bt_hc_work_thread set_power preloadGKI作者:xubin341719(欢迎转载。请注明作者,请尊重版权,谢谢!)画图工具:Edraw Maindmap欢迎指正错误。共同学习、共同...
  • Bluedroid 打开蓝牙流程

    2021-07-16 15:55:56
    1、bluetooth.cc enable执行打开蓝牙 static int enable(bool start_restricted) { LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted); restricted_mode = start_restricted;...
  • 1、从btsnoop.cc中可以看到有个btsnoop_mode
  • 前言本文档主要介绍android平台下bluetooth的应用层软件,先介绍bluetooth应用层的框架,接着分别介绍Bluedroid层软件、Bluetooth应用程序(Bluetooth.apk),Bluetooth framework层,最后完整分析一些蓝牙的操作...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,725
精华内容 690
关键字:

bluedroid