1. 程式人生 > >藍芽程式碼基本結構分析

藍芽程式碼基本結構分析

藍芽程式碼總體結構分析

在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