蓝牙代码基本结构分析

来源:互联网 发布:linux如何删除目录 编辑:程序博客网 时间:2024/05/22 06:11

蓝牙代码总体结构分析

在Android框架代码中,有两个重要接口IBluetoothIBluetoothManager
这两个接口之间的类图关系如下:
img1
总体来讲,对于应用程序通过BluetoothManagerBluetoothAdapter来操作蓝牙相关接口。
其中IBluetoothManager定义了如下一些接口:

interface IBluetoothManager{    IBluetooth registerAdapter(in IBluetoothManagerCallback callback);    void unregisterAdapter(in IBluetoothManagerCallback callback);    void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);    void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);    boolean isEnabled();    boolean enable();    boolean enableNoAutoConnect();    boolean disable(boolean persist);    IBluetoothGatt getBluetoothGatt();    String getAddress();    String getName();}

上述接口主要跟蓝牙设备的管理有关,其中一些接口如enable实际会还是要依赖IBluetooth接口
提供的方法。

BluetoothManager
用于获取BluetoothAdapter的一个实例,以及执行一些全局性的蓝牙管理行为。
获取BluetoothAdapter的方式如下:

public TestActivity extends Activity {    ...    private BluetoothManager bluetoothManager = null;    private BluetoothAdapter BluetoothAdapter = null;    protected void onCreate(Bundle savedInstances) {        ...        bluetoothManager = this.getSystemService(Context.BLUETOOTH_SERVICE);        bluetoothAdapter = bluetoothManager.getAdapter();        ...    }    ...}

BluetoothAdapter
该类代表本地端的一个蓝牙适配器,提供了一系列操作蓝牙设备的接口,如初始化蓝牙设备,
扫描蓝牙设备以及获取已配对蓝牙设备列表等等操作。除上通过BluetoothManager类获取该类的
一个实例引用外,还可以使用该类本身提供的一个静态成员方法获取该类的一个实例引用:

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

此类的大部分方法都会通过IBluetoothManagerIBluetooth操作提供的方法调用到底层。

上述三个类代码位于:frameworks\base\core\java\android\bluetooth目录下。

BluetoothManagerService
此类是接口IBluetoothManager的具体实现类,它从IBluetoothManager.Stub抽象类中继承而来。
它的大部分方法都通过IBluetooth往底层传递,此外,通过它还可以访问IBluetoothGatt接口。
该类的代码位于:frameworks\base\services\java\com\android\server目录下。

AdapterServiceBinder
该类实现了IBluetooth接口,它从IBluetooth.Stub抽象类中继承而来。它是AdapterService的一个私有静态
内部类。为什么要实现为一个静态内部类呢?
实际上,它的一些接口实现最终调用的是它的外部类AdapterService的方法,并通过这些方法调用到JNI层。
该类的代码位于:packages\apps\Bluetooth\src\com\android\bluetooth\btservice目录下。

JNI层
在JNI层,一个重要的数据结构是bt_interface_t,对应了一个此类型的全局变量,在JNI代码中,可以通过
接口getBluetoothInterface来获取该变量的引用。
下面是AdapterService类对应的JNI层的代码,我们看下如何通过HAL来初始化该全局变量。

static void classInitNative(JNIEnv* env, jclass clazz) {    int err;    hw_module_t* module;    ...    char value[PROPERTY_VALUE_MAX];    property_get("bluetooth.mock_stack", value, "");    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);    err = hw_get_module(id, (hw_module_t const**)&module);    if (err == 0) {        hw_device_t* abstraction;        err = module->methods->open(module, id, &abstraction);        if (err == 0) {            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;            sBluetoothInterface = btStack->get_bluetooth_interface();        } else {           ALOGE("Error while opening Bluetooth library");        }    } else {        ALOGE("No Bluetooth Library found");    }}

从上述代码可以看到,通过HAL的接口,我们得到了bt_interface_t类型的全局变量的引用,并通过该变量,
将上层的一些操作通过HAL层传递到底层。
相关代码位于:packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

HAL层
基本数据结构定义在如下路径:hardware\libhardware\include\bluetooth.h.

typedef struct {    struct hw_device_t common;    const bt_interface_t* (*get_bluetooth_interface)();} bluetooth_device_t;typedef bluetooth_device_t bluetooth_module_t;

可以看到,定义了一个bluetooth_device_t的结构体,它提供了一个get_bluetooth_interface函数指针。
那实际注册HAL的代码位于如下路径:
external\bluetooth\bluedroid\btif\src\bluetooth.c
HAL层注册了蓝牙协议栈,它作为一个HAL层的“设备”为上层服务,其定义如下:

static struct hw_module_methods_t bt_stack_module_methods = {    .open = open_bluetooth_stack,};struct hw_module_t HAL_MODULE_INFO_SYM = {    .tag = HARDWARE_MODULE_TAG,    .version_major = 1,    .version_minor = 0,    .id = BT_HARDWARE_MODULE_ID,    .name = "Bluetooth Stack",    .author = "The Android Open Source Project",    .methods = &bt_stack_module_methods};

在open方法中,初始化了bluetooth_device_t结构体成员,特别地,它初始化了get_bluetooth_interface,
这样framework层就可以间接通过这个接口来操作蓝牙设备了。

总结

最后,我们再次看一下蓝牙模块功能的调用过程。

  • 获取蓝牙模块的接口
    通过hw_get_module获取蓝牙模块的接口,并调用它的open标准接口
    获得hw_device_t的设备指针,再通过其get_bluetooth_interface获取
    蓝牙接口bt_interface_t

  • 获取Profile接口
    通过bt_interface_t接口的方法get_profile_interface获取对应Profile的接口指针。

如下是一些初始化过程:

Created with Raphaël 2.1.2AdapterServiceAdapterServicecom_android_bluetooth_btservice_AdapterService.cppcom_android_bluetooth_btservice_AdapterService.cppbt_interface_tbt_interface_tbluetooth.cbluetooth.conCreateinitNativeinitNativeinitinit
Created with Raphaël 2.1.2com_android_bluetooth_btservice_AdapterService.cppcom_android_bluetooth_btservice_AdapterService.cppbluetooth.cbluetooth.cbt_utils.cbt_utils.cbtif_core.cbtif_core.cbtif_config.cbtif_config.cbte_main.cbte_main.cgki_ulinux.cgki_ulinux.cinitbt_utils_initbtif_init_bluetoothbtif_config_initbte_main_boot_entrybtif_fetch_local_bdaddrGKI_create_task
0 0