- discoverServices()。把连接时存储在HAL层的gatt db存储到GattService、BluetoothGatt,并通过回调onServicesDiscovered,告知app这个过程完成了。会依次回调JNI注册的两个函数:btgattc_search_complete_cb、btgattc_get_gatt_db_cb。当HAL已从peripheral读出gatt db后,会回调第一个btgattc_search_complete_cb,JNI会在新建线程反向调用HAL的btif_gattc_get_gatt_db。在此函数,HAL把gatt db复制到自开辟的内存块db_ptr,复制完后,以这内存块地址为参数回调第二个btgattc_get_gatt_db_cb。在此回调中,JNI从db_ptr读gatt db。完成btgattc_get_gatt_db_cb后,HAL、GattService、BluetoothGatt,都各自存储了gatt db。另外,btgattc_get_gatt_db_cb在各自存储gatt db后,会回调app层的onServicesDiscovered。
- disconnect()。如果调用了该方法后可以调用connect()进行重连,这样还可以继续进行断开前的操作。
- close()。一但调用了该方法,如果想再次连接,必须调用BluetoothDevice.connectGatt()。因为close()方法将释放BluetootheGatt的所有资源。
- 当你需要手动断开时,调用disconnect(),此时断开成功后会回调onConnectionStateChange。在这个函数中再调用close()释放资源。如果在disconnect后立即调用close,会导致无法回调onConnectionStateChange。
- 对同一个periperal,disconnect()后、close()之前,不要调用BluetoothDevice.connectGatt。否则app可能会收到一个不是由connectGatt导致的“带外”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange,于是程序混乱。
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothGatt.java ------ public final class BluetoothGatt implements BluetoothProfile { public void close() { if (DBG) Log.d(TAG, "close()"); // unregisterApp()会调用mService.unregisterClient(mClientIf, mAttributionSource); unregisterApp(); mConnState = CONN_STATE_CLOSED; mAuthRetryState = AUTH_RETRY_STATE_IDLE; } public void disconnect() { if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return; try { mService.clientDisconnect(mClientIf, mDevice.getAddress(), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "", e); } } public boolean connect() { try { // autoConnect is inverse of "isDirect" mService.clientConnect(mClientIf, mDevice.getAddress(), false, mTransport, mOpportunistic, mPhy, mAttributionSource); return true; } catch (RemoteException e) { Log.e(TAG, "", e); return false; } } public boolean discoverServices() { if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; mServices.clear(); try { mService.discoverServices(mClientIf, mDevice.getAddress(), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "", e); return false; } return true; } public boolean refresh() { if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; try { mService.refreshDevice(mClientIf, mDevice.getAddress(), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "", e); return false; } return true; } }
一、discoverServices()
discoverServices内中是调用mService.discoverServices(),该操作最终会调用bt协议栈的btif_gattc_search_service。它通过MessageLoopThread机制,切换到bt_jni_thread线程执行BTA_GATTC_ServiceSearchRequest。
<aosp>/system/bt/btif/src/btif_gatt_client.cc ------ static bt_status_t btif_gattc_search_service(int conn_id, const Uuid* filter_uuid) { CHECK_BTGATT_INIT(); if (filter_uuid) { Uuid* uuid = new Uuid(*filter_uuid); return do_in_jni_thread( Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid))); } else { return do_in_jni_thread( Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr)); } }
对BTA_GATTC_ServiceSearchRequest,如果只是想获取整个gatt数据库,参数p_srvc_uuid会填nullptr。
<aosp>/system/bt/bta/gatt/bta_gattc_api.cc ------ void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id, const Uuid* p_srvc_uuid) { const size_t len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(Uuid); tBTA_GATTC_API_SEARCH* p_buf = (tBTA_GATTC_API_SEARCH*)osi_calloc(len); p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT; p_buf->hdr.layer_specific = conn_id; if (p_srvc_uuid) { p_buf->p_srvc_uuid = (Uuid*)(p_buf + 1); *p_buf->p_srvc_uuid = *p_srvc_uuid; } else { p_buf->p_srvc_uuid = NULL; } bta_sys_sendmsg(p_buf); }
接下查看event=BTA_GATTC_API_SEARCH_EVT时的bta_gattc_hdl_event,它进入“default”入口。
<aosp>/system/bt/bta/gatt/bta_gattc_main.c ------ bool bta_gattc_hdl_event(BT_HDR_RIGID* p_msg) { tBTA_GATTC_CLCB* p_clcb = NULL; bool rt = true; switch (p_msg->event) { ... default: if (p_msg->event == BTA_GATTC_INT_CONN_EVT) p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA*)p_msg); else if (p_msg->event == BTA_GATTC_INT_DISCONN_EVT) p_clcb = bta_gattc_find_int_disconn_clcb((tBTA_GATTC_DATA*)p_msg); else p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific); if (p_clcb != NULL) { // 此时有效状态或是BTA_GATTC_DISCOVER_ST,或是BTA_GATTC_CONN_ST // hdr.event是BTA_GATTC_API_SEARCH_EVT。 rt = bta_gattc_sm_execute(p_clcb, p_msg->event, (const tBTA_GATTC_DATA*)p_msg); } else { VLOG(1) << "Ignore unknown conn ID: " << +p_msg->layer_specific; } break; } return rt; }
执行bta_gattc_sm_execute时,当前有效状态可能或是BTA_GATTC_DISCOVER_ST,或是BTA_GATTC_CONN_ST。先分析第一种:BTA_GATTC_DISCOVER_ST。
如果处于这种,通常发生在bt协议栈回调到app注册的BluetoothGattCallback.onConnectionStateChange(status==STATE_CONNECTED)时,app立即在这里调用了discoverServices()。由于bta从peripheral读取gatt数据库需要点时间,于是discoverServices执行这里时,状态机还处在BTA_GATTC_DISCOVER_ST。
针对此刻的状态转换,bta_gattc_sm_execute要使用的状态表是bta_gattc_st_discover,收到BTA_GATTC_API_SEARCH_EVT事件,查表可知action是BTA_GATTC_Q_CMD,下一个状态依旧是BTA_GATTC_DISCOVER_ST。action是BTA_GATTC_Q_CMD时执行的函数是bta_gattc_q_cmd。
<aosp>/system/bt/bta/gatt/bta_gattc_act.cc ------ void bta_gattc_q_cmd(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { bta_gattc_enqueue(p_clcb, p_data); } <aosp>/system/bt/bta/gatt/bta_gattc_utils.cc ------ bool bta_gattc_enqueue(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { if (p_clcb->p_q_cmd == NULL) { p_clcb->p_q_cmd = p_data; return true; } LOG(ERROR) << __func__ << ": already has a pending command"; /* skip the callback now. ----- need to send callback ? */ return false; }
bta_gattc_q_cmd只是简单地把BTA_GATTC_API_SEARCH_EVT命令放到p_clcb->p_q_cmd。放完之后会发生什么?——回看“BLE(4/6):连接之bta_gattc_start_discover”末尾,在生成完整gatt数据库,状态进入BTA_GATTC_CONN_ST后,会调用bta_gattc_disc_cmpl。它会检查p_clcb->p_q_cmd,如果发现不是nullptr,那它会以这个p_q_cmd执行bta_gattc_sm_execute,而这也正是上面提到的执行bta_gattc_sm_execute时的第二种情况:当状态处于BTA_GATTC_CONN_ST时。
状态是BTA_GATTC_CONN_ST时。针对此刻的状态转换,bta_gattc_sm_execute使用的状态表是bta_gattc_st_connected,收到BTA_GATTC_API_SEARCH_EVT事件,查表可知action是BTA_GATTC_SEARCH,下一个状态依旧是BTA_GATTC_CONN_ST。action是BTA_GATTC_SEARCH时执行的函数是bta_gattc_search。
<aosp>/system/bt/bta/gatt/bta_gattc_cache.cc ------ void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) { for (const Service& service : p_clcb->p_srcb->gatt_database.Services()) { if (p_uuid && *p_uuid != service.uuid) continue; if (!p_clcb->p_rcb->p_cback) continue; tBTA_GATTC cb_data; memset(&cb_data, 0, sizeof(tBTA_GATTC)); cb_data.srvc_res.conn_id = p_clcb->bta_conn_id; cb_data.srvc_res.service_uuid.inst_id = service.handle; cb_data.srvc_res.service_uuid.uuid = service.uuid; (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data); } } <aosp>/system/bt/bta/gatt/bta_gattc_act.cc ------ void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) { tGATT_STATUS status = GATT_INTERNAL_ERROR; tBTA_GATTC cb_data; if (p_clcb->p_srcb && !p_clcb->p_srcb->gatt_database.IsEmpty()) { status = GATT_SUCCESS; /* search the local cache of a server device */ bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid); } cb_data.search_cmpl.status = status; cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id; /* end of search or no server cache available */ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT, &cb_data); }
bta_gattc_search会用p_clcb->p_rcb->p_cback依次执行两类回调。
- BTA_GATTC_SEARCH_RES_EVT。这发生在bta_gattc_search_service,如果p_srvc_uuid是nullptr,那它不会发生。
- BTA_GATTC_SEARCH_CMPL_EVT。向上层报告此次gatt数据库的发现结果。
这里不深入BTA_GATTC_SEARCH_RES_EVT,让看肯定会上报的BTA_GATTC_SEARCH_CMPL_EVT。
p_clcb->p_rcb->p_cback指向来自registerClient时调用BTA_GATTC_AppRegister传入的参数bta_gattc_cback,关于它的描述在“BLE(2/6):连接之BluetoothDevice.connectGatt”搜“bta_gattc_cback”。bta_gattc_cback会使用fixed_queue_enqueus机制实现在bt_jni_workqueue_thread线程执行btif_gattc_upstreams_evt。这里发送的event是BTA_GATTC_SEARCH_CMPL_EVT。
<aosp>/system/bt/btif/src/btif_gatt_client.c ------ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) { ALOGD("%s: Event %d", __FUNCTION__, event); tBTA_GATTC *p_data = (tBTA_GATTC*)p_param; switch (event) { case BTA_GATTC_SEARCH_CMPL_EVT: { HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb , p_data->search_cmpl.conn_id, p_data->search_cmpl.status); break; } } btapp_gattc_free_req_data(event, p_data); }
client->search_complete_cb对应JNI层的btgattc_search_complete_cb。它将一路向上回调:GattService.onSearchCompleted。和其它回调有不一样,它没继续向上,而是又向下了。
<aosp>\packages\apps\Bluetooth\src\com\android\bluetooth\gatt\GattService.java ------ public class GattService extends ProfileService { void onSearchCompleted(int connId, int status) throws RemoteException { if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); // Gatt DB is ready! // This callback was called from the jni_workqueue thread. If we make request to the stack // on the same thread, it might cause deadlock. Schedule request on a new thread instead. Thread t = new Thread(new Runnable() { public void run() { gattClientGetGattDbNative(connId); } }); t.start(); } }
将在一个新线程执行JNI操作:gattClientGetGattDbNative。
static void gattClientGetGattDbNative(JNIEnv* env, jobject object, jint conn_id) { if (!sGattIf) return; sGattIf->client->get_gatt_db(conn_id); }
在HAL层,get_gatt_db对应btif_gattc_get_gatt_db。类似btif_gattc_register_app、btif_gattc_open,btif_gattc_get_gatt_db也是调用btif_transfer_context,通过fixed_queue_enqueus机制,切换到bt_jni_workqueue_thread线程执行btgattc_handle_event,参数event值BTIF_GATTC_GET_GATT_DB。
<aosp>/system/bt/btif/src/btif_gatt_client.c ------ static void btgattc_handle_event(uint16_t event, char* p_param) { tBTA_GATT_STATUS status; tBT_UUID uuid; ... btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param; if (!p_cb) return; switch (event) { case BTIF_GATTC_GET_GATT_DB: { btgatt_db_element_t *db = NULL; int count = 0; BTA_GATTC_GetGattDb(p_cb->conn_id, 0x0000, 0xFFFF, &db, &count); HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb, p_cb->conn_id, db, count); osi_free(db); break; } ... } }
BTIF_GATTC_GET_GATT_DB执行两个操人。一是BTA_GATTC_GetGattDb,把之前discover出的gatt放入新建变量db。二是回调client->get_gatt_db_cb,它对应JNI层的btgattc_get_gatt_db_cb。btgattc_get_gatt_db_cb解析HAL上传的db,把它放入Java层Ljava/util/ArrayList变量,并以它为参数调用method_onGetGattDb,即GattService.onGetGattDb。
<aosp>\packages\apps\Bluetooth\src\com\android\bluetooth\gatt\GattService.java ------ public class GattService extends ProfileService { void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { String address = mClientMap.addressByConnId(connId); if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address); ClientMap.App app = mClientMap.getByConnId(connId); if (app == null || app.callback == null) { Log.e(TAG, "app or callback is null"); return; } List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>(); BluetoothGattService currSrvc = null; BluetoothGattCharacteristic currChar = null; for (GattDbElement el: db) { // 枚举db中单元,把它们放入db_out } // Search is complete when there was error, or nothing more to process gattClientDatabases.put(connId, db_out); app.callback.onSearchComplete(address, db_out, 0 /* status */); } }
至此,discover出的db放入了GattService内的成员gattClientDatabases。之后一路向上回调BluetoothGatt.onSearchComplete --> app层的onServicesDiscovered。
BluetoothGatt.onSearchComplete在回调app层的onServicesDiscovered之前,会把gatt db存储成员mServices,也就是说,discover后,HAL、GattService、BluetoothGatt,都各自存储了gatt db。
二、disconnect()、close()
想明白这两个函数有什么区别,抄下“BLE(2/6):连接之BluetoothDevice.connectGatt”中写的。
BluetoothDevice.connectGatt会执行的两个函数。mService.registerClient()和mService.clientConnect()。对mService.registerClient(),主要两个操作。1)向GATT协议栈注册,并获得新的client_if。此过程只是在gatt_cb.cl_rcb得到一个可用位置,不会触发蓝牙数据传输。2)调用JNI注册的回调函数:btgattc_register_app_cb,进而回调BluetoothGatt.mBluetoothGattCallback.onClientRegistered。onClientRegistered不会回调到app,而是“向下”执行connectGatt的第二个函数:mService.clientConnect()。
disconnect()。断开连接,对应着mService.clientConnect()的逆操作。BluetoothDevice.connect()就是调用mService.clientConnect(),因而调用disconnect()之后可以调用connect()进行重连。此操作会回调bt_gatt_callbacks->client->close_cb、bt_hal_cbacks->acl_state_changed_cb。第一个close_cb会回调app的onConnectionStateChange,第二个acl_state_changed_cb则表示,销毁了btif_gattc_open时用L2CA_ConnectFixedChnl()在l2cap层分配的channel。
I/bt_btif: HAL bt_gatt_callbacks->client->close_cb I/bt_btif: btif_dm_upstreams_evt: ev: BTA_DM_LINK_DOWN_EVT D/bt_btif: BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED I/bt_btif: HAL bt_hal_cbacks->acl_state_changed_cb ------ 虽然第二个是bt_hal_cbacks,和其它的bt_gatt_callbacks不一样,但回调运行在一样的线程。
close()。对应着mService.registerClient()逆操作。它会向GATT协议栈注销此次申请到的client_if。因为close()已将registerClient()时申请到的clint_if还给GATT协议栈,一但调用了该方法,想再次连接必须调用BluetoothDevice.connectGatt()。
类似BluetoothDevice.connectGatt一个函数就包括mService.registerClient()、mService.clientConnect(),建议app“一个函数”凋用disconnect、close。“一个函数”加引号,是因为中间必须处理参数newState是 BluetoothProfile.STATE_DISCONNECTED的onConnectionStateChange。必须在onConnectionStateChange处理完私有任务后,再调用close。于是disconnect、close会这么个流程。
- 想断开连接了,app调用disconnect()。
- 某个时刻,app层的onConnectionStateChange被调用。函数首先处理私有操作,像告知主线程此次连接已安全断开,然后调用close(),释放client_if。
如果在disconnect后立即调用close,即不等onConnectionStateChange,会导致无法回调onConnectionStateChange。
三、mService.unregisterClient(mClientIf)
disconnect后,虽然已没了L2CAP通道,但clientIf还是有效,unregisterClient目的是要回收这个clientIf。依据之前的mServier分析方法,很容就能定位到它会执行JNI层的gattClientUnregisterAppNative。
<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp ------ static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clientIf) { if (!sGattIf) return; sGattIf->client->unregister_client(clientIf); }
针对JNI层中的“sGattIf->client->unregister_client(clientIf)”,sGattIf对应着HAL中的btgattInterface,sGattIf->client对应着btgattClientInterface,unregister_client是btif_gattc_unregister_app。
类似btif_gattc_register_app,btif_gattc_unregister_app也是调用btif_transfer_context,通过fixed_queue_enqueus机制,切换到bt_jni_workqueue_thread线程执行btgattc_handle_event,参数event值BTIF_GATTC_UNREGISTER_APP。
<aosp>/system/bt/btif/src/btif_gatt_client.c ------ static void btgattc_handle_event(uint16_t event, char* p_param) { tBTA_GATT_STATUS status; tBT_UUID uuid; ... btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param; if (!p_cb) return; switch (event) { case BTIF_GATTC_UNREGISTER_APP: btif_gattc_clear_clientif(p_cb->client_if, TRUE); btif_gattc_decr_app_count(); BTA_GATTC_AppDeregister(p_cb->client_if); break; ... } }
进入BTA_GATTC_AppDeregister。
<aosp>\system\bt\bta\gatt\bta_gattc_api.c ------ void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if) { tBTA_GATTC_API_DEREG *p_buf = (tBTA_GATTC_API_DEREG *)osi_malloc(sizeof(tBTA_GATTC_API_DEREG)); p_buf->hdr.event = BTA_GATTC_API_DEREG_EVT; p_buf->client_if = client_if; bta_sys_sendmsg(p_buf); }
bta_sys_sendmsg使用fixed_queue_enqueus机制,触发在bt_workqueue_thread线程执行之前注册的bta_gattc_hdl_event。
<aosp>/system/bt/bta/gatt/bta_gattc_main.c ------ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) { tBTA_GATTC_CB *p_cb = &bta_gattc_cb; tBTA_GATTC_CLCB *p_clcb = NULL; tBTA_GATTC_RCB *p_clreg; switch (p_msg->event) { case BTA_GATTC_API_DEREG_EVT: p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->api_dereg.client_if); bta_gattc_deregister(p_cb, p_clreg); break; ... } return rt; }
进入bta_gattc_deregister。
<aosp>/system/bt/bta/gatt/bta_gattc_act.c ------ void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg) { UINT8 i; BT_HDR buf; if (p_clreg != NULL) { if (p_clreg->num_clcb > 0) { ... } else { // p_clreg->num_clcb值是0,进这个入口 bta_gattc_deregister_cmpl(p_clreg); } } else { APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif"); } }
p_clreg->num_clcb值是0,执行bta_gattc_deregister_cmpl。
<aosp>/system/bt/bta/gatt/bta_gattc_act.c ------ static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg) { ... GATT_Deregister(p_clreg->client_if); ... }
bta_gattc_deregister_cmpl会调用mService.registerClient()中GATT_Register的逆操作:GATT_Deregister。
<aosp>/system/bt/stack/gatt/gatt_api.c ------ void GATT_Deregister (tGATT_IF gatt_if) { tGATT_REG *p_reg = gatt_get_regcb(gatt_if); ... // 此个memset会把p_reg->in_use置为false。 memset (p_reg, 0, sizeof(tGATT_REG)); }
GATT_Deregister末尾执行的memset会把p_reg->in_use置为false,至此此个tGATT_REG变成空闲,后绪BluetoothDevice.connectGatt可再次使用它了。
四、refresh()
refresh用于删除连接过程中生成的、存储着gatt db的cache文件。主要应用场景是针对配置了OAD升级功能的BLE设备以及平常的开发调试。
BluetoothGatt.refresh -[HAL]-> btif_gattc_refresh --> BTA_GATTC_Refresh --> bta_gattc_process_api_refresh --> bta_gattc_cache_reset <aosp>/system/bt/bta/gatt/bta_gattc_cache.c ------ void bta_gattc_cache_reset(BD_ADDR server_bda) { BTIF_TRACE_DEBUG("%s", __func__); char fname[255] = {0}; bta_gattc_generate_cache_file_name(fname, server_bda); unlink(fname); }
在连接连过程中,如果有把gatt db存储在cache文件,bta_gattc_cache_reset将删除这文件。
五、为免麻烦,“一次性”调用disocnnect()、close()
对同一个periperal,disconnect()后、close()之前,不要调用BluetoothDevice.connectGatt。否则app可能会收到一个不是由connectGatt导致的“带外”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange,于是程序混乱。
假设disconnect()的client_if=5,新connectGatt申请出的client_if=6。若该peripheral触发notification,由于存在个处于GATTC_IDLE_ST状态的client_if=5,android认为它应该接收此个notification,会自动进行重联让进入GATTC_CONN_ST,相应地,app会收到一个“莫名其妙”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange。下面分析这个过程。
peripernal发来ACL数据后,client会回调gatt_client_handle_server_rsp。此时op_code值是GATT_HANDLE_VALUE_NOTIF(0x1B),“case GATT_HANDLE_VALUE_NOTIF”时,调用gatt_process_notification。
<aosp>/system/bt/stack/gatt/gatt_cl.c ------ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { ... for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value); } } }
gatt_process_notification为确定应该由哪个/些conn_id(client_if)处理这个notification,于是检查所有(GATT_MAX_APPS)conn_if。对conn_id=5或6,p_cmpl_cb指向bta_gattc_cmpl_cback。此时op==GATTC_OPTYPE_NOTIFICATION,调用bta_gattc_process_indicate。
<aosp>/system/bt/bta/gatt/bta_gattc_act.c ------ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data) { ... /* if non-service change indication/notification, forward to application */ if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, ¬ify, &p_data->att_value)) { /* if app registered for the notification */ if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) { /* connection not open yet */ // conn_id=5或6都会进入这里。 if (p_clcb == NULL) { // 对于5,由于已经被BluetoothGatt.disconnect,p_clcb值是null,要重新得到这值。 p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport); if (p_clcb == NULL) { APPL_TRACE_ERROR("No resources"); return; } p_clcb->bta_conn_id = conn_id; p_clcb->transport = transport; // 此时gattc状态是GATTC_IDLE_ST,收到BTA_GATTC_INT_CONN_EVT后,进入GATTC_CONN_ST。这里会回调JNI的open_cb。 // GATTC State Change: [GATTC_IDLE_ST] -> [GATTC_CONN_ST] after Event [BTA_GATTC_INT_CONN_EVT] bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL); } if (p_clcb != NULL) bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify); } /* no one intersted and need ack? */ else if (op == GATTC_OPTYPE_INDICATION) { APPL_TRACE_DEBUG("%s no one interested, ack now", __func__); GATTC_SendHandleValueConfirm(conn_id, handle); } } }
对于5,由于已经被BluetoothGatt.disconnect,p_clcb值是null,于是要调用bta_gattc_clcb_alloc重新得到这值。此时gattc状态是GATTC_IDLE_ST,收到BTA_GATTC_INT_CONN_EVT后,进入GATTC_CONN_ST。当中会回调JNI的open_cb,进而回调app中newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange。