BluetoothAdapter.java中有low enery(le)的一些方法,android提供了這些方法,但源碼中並未找到這些方法的調用之處。本文檔主要分析這類方法的執行流程,來了解下le到底作了些什麼。java
本文主要就是分析下startLeScan方法(兩個重載方法)。android
public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); } public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) { if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids); synchronized(mLeScanClients) { if (mLeScanClients.containsKey(callback)) { if (DBG) Log.e(TAG, "LE Scan has already started"); return false; } try { //獲取BluetoothGattBinder類的實例,該類的定義在GattService.java中 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); if (iGatt == null) { // BLE is not supported return false; } UUID uuid = UUID.randomUUID(); GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids); //重點分析該方法。做用是爲本地設備進行註冊,以及啓動掃描 //wrapper是GattCallbackWrapper類的對象。該類註冊了一些Gatt協議的回調方法 iGatt.registerClient(new ParcelUuid(uuid), wrapper); if (wrapper.scanStarted()) { mLeScanClients.put(callback, wrapper); return true; } } catch (RemoteException e) { Log.e(TAG,"",e); } } return false; }
下面來分析下iGatt.registerClient(new ParcelUuid(uuid), wrapper)方法,路徑以下:(packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java::BluetoothGattBinder)api
public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { GattService service = getService(); if (service == null) return; service.registerClient(uuid.getUuid(), callback); }
接着會調用GattService服務的同名方法app
void registerClient(UUID uuid, IBluetoothGattCallback callback) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); mClientMap.add(uuid, callback); gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); }
接下來會調用jni層com_android_bluetooth_gatt.cpp文件中的gattClientRegisterAppNative方法。dom
static void gattClientRegisterAppNative(JNIEnv* env, jobject object, jlong app_uuid_lsb, jlong app_uuid_msb ) { bt_uuid_t uuid; if (!sGattIf) return; set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb); sGattIf->client->register_client(&uuid); }
分析sGattIf->client->register_client(&uuid);語句ide
(1)sGattIf是一個靜態變量,定義是static const btgatt_interface_t *sGattIf = NULL;函數
又是這種類型的變量。第一反應就是去找btgatt_interface_t結構體定義的頭文件(通常在hardware目錄),而後再搜索調用的c文件(通常在external/bluetooth/bluedroid,有時找到的c文件與頭文件同名)。ui
btgatt_interface_t結構體的定義:hardware/libhardware/include/hardware/bt_gatt.hthis
/** Represents the standard Bluetooth GATT interface. */ typedef struct { /** Set to sizeof(btgatt_interface_t) */ size_t size; /** * Initializes the interface and provides callback routines */ bt_status_t (*init)( const btgatt_callbacks_t* callbacks ); /** Closes the interface */ void (*cleanup)( void ); /** Pointer to the GATT client interface methods.*/ const btgatt_client_interface_t* client; /** Pointer to the GATT server interface methods.*/ const btgatt_server_interface_t* server; } btgatt_interface_t;
btgatt_interface_t結構體的對象:external/bluetooth/bluedroi/btif/src/btif_gatt.cspa
static const btgatt_interface_t btgattInterface = { sizeof(btgattInterface), btif_gatt_init, btif_gatt_cleanup, &btgattClientInterface, &btgattServerInterface, };
回到sGattIf->client->register_client(&uuid);語句,它調用了sGattIf結構體對象中的client對象的register_client函數,那麼就是btgattClientInterface對象的register_client函數。
由結構體的定義可知client對象的類型是btgatt_client_interface_t結構體。同理分析可得如下結果,
btgatt_client_interface_t結構體的定義:hardware/libhardware/include/hardware/ bt_gatt_client.h
typedef struct { /** Registers a GATT client application with the stack */ bt_status_t (*register_client)( bt_uuid_t *uuid ); /** Unregister a client application from the stack */ bt_status_t (*unregister_client)(int client_if ); ...... }
btgatt_client_interface_t結構體的對象:external/bluetooth/bluedroi/btif/src/btif_gatt_client.c
const btgatt_client_interface_t btgattClientInterface = { btif_gattc_register_app, btif_gattc_unregister_app, btif_gattc_scan, ...... };
所以client->register_client就是調用了btif_gattc_register_app方法[-->btif_gatt_client.c]。
static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid) { CHECK_BTGATT_INIT(); btif_gattc_cb_t btif_cb; memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t)); return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP, (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL); }
分析btgattc_handle_event函數
static void btgattc_handle_event(uint16_t event, char* p_param) { ...... btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param; if (!p_cb) return; switch (event) { case BTIF_GATTC_REGISTER_APP: btif_to_bta_uuid(&uuid, &p_cb->uuid); //爲uuid註冊回調函數 BTA_GATTC_AppRegister(&uuid, bte_gattc_cback); break; ....... } }
分析BTA_GATTC_AppRegister函數
-------------------------------------------------------------------------------------------------------
void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb) { tBTA_GATTC_API_REG *p_buf; /* register with BTA system manager */ GKI_sched_lock(); //註冊Gatt客戶端主事件處理函數bta_gattc_hdl_event,在bta_gatt_reg結構體中定義。 bta_sys_register(BTA_ID_GATTC, &bta_gatt_reg); GKI_sched_unlock(); if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL) { p_buf->hdr.event = BTA_GATTC_API_REG_EVT; if (p_app_uuid != NULL) memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID)); p_buf->p_cback = p_client_cb; bta_sys_sendmsg(p_buf); } return; }
(a)經過bta_sys_register函數註冊了bta_gatt_reg結構體中定義的客戶端主事件處理函數bta_gattc_hdl_event;而後設置event爲BTA_GATTC_API_REG_EV,觸發bta_gattc_hdl_event函數。
BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) { tBTA_GATTC_CB *p_cb = &bta_gattc_cb; tBTA_GATTC_CLCB *p_clcb = NULL; #if BTA_GATT_DEBUG == TRUE APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event)); #endif switch (p_msg->event) { case BTA_GATTC_API_REG_EVT: bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg); break; ...... } }
(b)調用bta_gattc_register函數。該函數用來註冊一個客戶端Gatt應用程序。
void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) { ...... /* callback with register event */ if (p_data->api_reg.p_cback) { (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT, (tBTA_GATTC *)&cb_data); } }
調用相關event(BTA_GATTC_REG_EVT)的回調函數。
到此,BTA_GATTC_AppRegister函數分析完畢,接下來分析BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);中的參數部分。
ps:上述的回調函數就是這裏的參數:bte_gattc_cback函數。那麼BTA_GATTC_REG_EVT事件就調用該函數處理了。
-------------------------------------------------------------------------------------------------------
分析回調函數bte_gattc_cback
static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) { bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), NULL); ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status); }
分析btif_gattc_upstreams_evt函數,在該函數中會處理BTA_GATTC_REG_EVT事件。
static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) { tBTA_GATTC *p_data = (tBTA_GATTC*)p_param; switch (event) { case BTA_GATTC_REG_EVT: { bt_uuid_t app_uuid; bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid); HAL_CBACK(bt_gatt_callbacks, client->register_client_cb , p_data->reg_oper.status , p_data->reg_oper.client_if , &app_uuid ); break; } ...... } }
bt_gatt_callbacks對象的類型是btgatt_callbacks_t,其定義在hardware/libhardware/include/hardware/bt_gatt.h文件中。如今對bt_gatt_callbacks對象從頭開始分析其來源。
在GattService.java::start()方法中,調用了initializeNative方法。繼而調用JNI層initializeNative方法。貼出該方法。
static const btgatt_interface_t *sGattIf = NULL; static const bt_interface_t* btIf; ...... static void initializeNative(JNIEnv *env, jobject object) { /* getBluetoothInterface 函數返回sBluetoothInterface對象,在android4.3 bt 掃描分析.docx中已說明該對象的來源*/ if ( (btIf = getBluetoothInterface()) == NULL) { error("Bluetooth module is not loaded"); return; } ...... //(a) // BT_PROFILE_GATT_ID的值是」gatt」 if ( (sGattIf = (btgatt_interface_t *) btIf->get_profile_interface(BT_PROFILE_GATT_ID)) == NULL) { error("Failed to get Bluetooth GATT Interface"); return; } bt_status_t status; //(b) /* sGattCallbacks的定義 static const btgatt_callbacks_t sGattCallbacks = { sizeof(btgatt_callbacks_t), &sGattClientCallbacks, &sGattServerCallbacks };*/ if ( (status = sGattIf->init(&sGattCallbacks)) != BT_STATUS_SUCCESS) { error("Failed to initialize Bluetooth GATT, status: %d", status); sGattIf = NULL; return; } mCallbacksObj = env->NewGlobalRef(object); }
(a) 分析
static const void* get_profile_interface (const char *profile_id) { ...... #if BTA_GATT_INCLUDED == TRUE if (is_profile(profile_id, BT_PROFILE_GATT_ID)) return btif_gatt_get_interface(); #endif return NULL; }
分析btif_gatt_get_interface函數
const btgatt_interface_t *btif_gatt_get_interface() { return &btgattInterface; }
btgattInterface對象的類型是btgatt_interface_t結構體。再貼一遍該結構體的定義,以下:
typedef struct { /** Set to sizeof(btgatt_interface_t) */ size_t size; /** * Initializes the interface and provides callback routines */ bt_status_t (*init)( const btgatt_callbacks_t* callbacks ); /** Closes the interface */ void (*cleanup)( void ); /** Pointer to the GATT client interface methods.*/ const btgatt_client_interface_t* client; /** Pointer to the GATT server interface methods.*/ const btgatt_server_interface_t* server; } btgatt_interface_t;
另,btgattInterface對象定義以下:
static const btgatt_interface_t btgattInterface = { sizeof(btgattInterface), btif_gatt_init, btif_gatt_cleanup, &btgattClientInterface, &btgattServerInterface, };
因此sGattIf 就是btgattInterface對象。
(b) 接下來調用sGattIf->init函數。由上可知,即爲btif_gatt_init函數。
static bt_status_t btif_gatt_init( const btgatt_callbacks_t* callbacks ) { /*bt_gatt_callbacks由參數賦值,該參數是sGattCallbacks。 sGattCallbacks的定義 static const btgatt_callbacks_t sGattCallbacks = { sizeof(btgatt_callbacks_t), &sGattClientCallbacks, &sGattServerCallbacks };*/ bt_gatt_callbacks = callbacks; BTA_GATTC_Init(); BTA_GATTS_Init(); return BT_STATUS_SUCCESS; }
到此爲止,調用語句中bt_gatt_callbacks對象咱們已經清楚了,就是sGattCallbacks對象。如今分析client->register_client_cb。
HAL_CBACK(bt_gatt_callbacks, client->register_client_cb , p_data->reg_oper.status , p_data->reg_oper.client_if , &app_uuid );
client對象是在btgatt_callbacks_t結構體中定義的一個變量,其初始化是在bt_gatt_callbacks對象(即sGattCallbacks對象)中。
btgatt_callbacks_t結構體以下:
typedef struct { /** Set to sizeof(btgatt_callbacks_t) */ size_t size; /** GATT Client callbacks */ const btgatt_client_callbacks_t* client; /** GATT Server callbacks */ const btgatt_server_callbacks_t* server; } btgatt_callbacks_t;
所以client對應的就是sGattCallbacks對象中的sGattClientCallbacks對象。sGattClientCallbacks對象定義以下(在JNI層的com_android_bluetooth_gatt.cpp文件中定義):
static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_register_app_cb, btgattc_scan_result_cb, ...... };
而sGattClientCallbacks對象的類型是btgatt_client_callbacks_t結構體,以下
typedef struct { register_client_callback register_client_cb; scan_result_callback scan_result_cb; connect_callback open_cb; disconnect_callback close_cb; ...... } btgatt_client_callbacks_t;
所以,client->register_client_cb就是調用了sGattClientCallbacks 對象中的btgattc_register_app_cb函數。
void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid) { CHECK_CALLBACK_ENV sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status, clientIf, UUID_PARAMS(app_uuid)); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); }
JNI層的method_onClientRegistered 函數對應java層的onClientRegistered方法[-->GattService.java]。
void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) throws RemoteException { UUID uuid = new UUID(uuidMsb, uuidLsb); if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); ClientMap.App app = mClientMap.getByUuid(uuid); if (app != null) { app.id = clientIf; app.linkToDeath(new ClientDeathRecipient(clientIf)); app.callback.onClientRegistered(status, clientIf); } }
此callback實際上是GattCallbackWrapper類的對象。
分析mClientMap對象,在registerClient方法中調用了ClientMap的父類ContextMap::add方法,將GattCallbackWrapper類對象wrapper做爲callback參數添加到mClientMap對象中。
接下來從新分析:
onClientRegistered方法[--->BluetoothAdapter::GattCallbackWrapper類]
public void onClientRegistered(int status, int clientIf) { if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf); synchronized(this) { if (mLeHandle == -1) { if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled"); } if (status == BluetoothGatt.GATT_SUCCESS) { mLeHandle = clientIf; IBluetoothGatt iGatt = null; try { BluetoothAdapter adapter = mBluetoothAdapter.get(); if (adapter != null) { iGatt = adapter.getBluetoothManager().getBluetoothGatt(); //調用startLeScan方法時,傳遞過來的參數爲null,執行此處 if (mScanFilter == null) { iGatt.startScan(mLeHandle, false); } else { ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; for(int i = 0; i != uuids.length; ++i) { uuids[i] = new ParcelUuid(mScanFilter[i]); } iGatt.startScanWithUuids(mLeHandle, false, uuids); } } else { Log.e(TAG, "onClientRegistered, BluetoothAdapter null"); mLeHandle = -1; } } catch (RemoteException e) { Log.e(TAG, "fail to start le scan: " + e); mLeHandle = -1; } ...... }
接下來分析startScan方法,在GattService.java中。
void startScan(int appIf, boolean isServer) { ...... if (getScanClient(appIf, isServer) == null) { if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf); mScanQueue.add(new ScanClient(appIf, isServer)); } gattClientScanNative(appIf, true); }
JNI層gattClientScanNative函數
static void gattClientScanNative(JNIEnv* env, jobject object, jint clientIf, jboolean start) { if (!sGattIf) return; sGattIf->client->scan(clientIf, start); }
同以前分析register_client的步驟,分析的scan函數對應btif_gattc_scan函數。
static bt_status_t btif_gattc_scan( int client_if, bool start ) { CHECK_BTGATT_INIT(); btif_gattc_cb_t btif_cb; btif_cb.client_if = (uint8_t) client_if; return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP, (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL); }
在btgattc_handle_event函數中處理BTIF_GATTC_SCAN_START事件
case BTIF_GATTC_SCAN_START: btif_gattc_init_dev_cb(); // BTA_DmBleObserve發出消息,包含BTA_DM_API_BLE_OBSERVE_EVT事件 BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb); break;
調用bte_scan_results_cb函數,
static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { btif_gattc_cb_t btif_cb; uint8_t len; switch (event) { case BTA_DM_INQ_RES_EVT: ...... case BTA_DM_INQ_CMPL_EVT: ...... btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATT_OBSERVE_EVT, (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL); }
在btif_gattc_upstreams_evt函數中處理BTIF_GATT_OBSERVE_EVT事件。
case BTIF_GATT_OBSERVE_EVT: { btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param; if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address)) { btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type); btif_gattc_update_properties(p_btif_cb); } HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb, &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value); break; }
同分析register_client_cb函數,在JNI層com_android_bluetooth_gatt.cpp文件中定義,分析得scan_result_cb對應函數btgattc_scan_result_cb。
void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data) { ...... sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanResult , address, rssi, jb); ...... }
對應java層文件GattService類onScanResult方法。
void onScanResult(String address, int rssi, byte[] adv_data) { for (ScanClient client : mScanQueue) { ...... if (!client.isServer) { ClientMap.App app = mClientMap.getById(client.appIf); if (app != null) { try { app.callback.onScanResult(address, rssi, adv_data); } catch (RemoteException e) { Log.e(TAG, "Exception: " + e); mClientMap.remove(client.appIf); mScanQueue.remove(client); } } } ...... } }
callback爲GattCallbackWrapper類的對象,所以調用GattCallbackWrapper類中的onScanResult方法。
public void onScanResult(String address, int rssi, byte[] advData) { ...... try { BluetoothAdapter adapter = mBluetoothAdapter.get(); if (adapter == null) { Log.d(TAG, "onScanResult, BluetoothAdapter null"); return; } mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData); } catch (Exception ex) { Log.w(TAG, "Unhandled exception: " + ex); } }
mLeScanCb對象爲LeScanCallback接口的對象,不過源碼中並無類來實現該接口,故只能分析到這裏了。掃描到此結束,over~~
-------------------------------------------------------------------------------------------------------------
貼出流程圖,see see,5個步驟:
1.startLeScan(JAVA-->JNI)
-------------------------------------------------------------------------------------------------------------
2.startLeScan(藍牙棧)
-------------------------------------------------------------------------------------------------------------
3.startLeScan(JNI-->JAVA)
-------------------------------------------------------------------------------------------------------------
4.startLeScan(藍牙棧)
-------------------------------------------------------------------------------------------------------------
5.startLeScan(JNI-->JAVA)
-------------------------------------------------------------------------------------------------------------