日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android4.3 Bluetooth(le)分析之startLeScan分析

發布時間:2024/4/17 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android4.3 Bluetooth(le)分析之startLeScan分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

BluetoothAdapter.java中有low?enery(le)的一些方法,android提供了這些方法,但源碼中并未找到這些方法的調用之處。本文檔主要分析這類方法的執行流程,來了解下le到底做了些什么。

?

本文主要就是分析下startLeScan方法(兩個重載方法)。

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)

public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) {GattService service = getService();if (service == null) return; service.registerClient(uuid.getUuid(), callback);}

接著會調用GattService服務的同名方法

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方法。

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);語句

(1)sGattIf是一個靜態變量,定義是static?const?btgatt_interface_t?*sGattIf?=?NULL;

?

又是這種類型的變量。第一反應就是去找btgatt_interface_t結構體定義的頭文件(一般在hardware目錄),然后再搜索調用的c文件(一般在external/bluetooth/bluedroid,有時找到的c文件與頭文件同名)。

btgatt_interface_t結構體的定義:hardware/libhardware/include/hardware/bt_gatt.h

/** 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.c

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 == TRUEAPPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event)); #endifswitch (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(); #endifreturn 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_ENVsCallbackEnv->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)

?

總結

以上是生活随笔為你收集整理的android4.3 Bluetooth(le)分析之startLeScan分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。