android5.0(Lollipop) BLE Peripheral深入理解系统篇之提高篇
生活随笔
收集整理的這篇文章主要介紹了
android5.0(Lollipop) BLE Peripheral深入理解系统篇之提高篇
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一篇文章講到了廣播之前系統需要進行的準備工作,那接下來我們就來真正的啟動廣播。首先還是先看一下上一篇文章結束的地方:@Override
public void onClientRegistered(int status, int clientIf) { Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf); synchronized (this) { if (status == BluetoothGatt.GATT_SUCCESS) { mClientIf = clientIf; try { mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertisement, mScanResponse, mSettings); return; } catch (RemoteException e) { Log.e(TAG, "failed to start advertising", e); } } // Registration failed. mClientIf = -1; notifyAll(); }
}
現在讓我們繼續追蹤mBluetoothGatt.startMultiAdvertising,但是我們發現mBluetoothGatt是通過AIDL來定義的:private final IBluetoothGatt mBluetoothGatt;
到這里,我們就不去看IBluetoothGatt的內容了,因為都是一些接口函數,我們比較關心的是IBluetoothGatt是誰的接口呢,在android如果遇到這種情況,我們肯定要去找service了,那我們現在基本可以確定,我們找的是GattService了,那我們去驗證一下,到底是不是這樣的:private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder
看到這里我們應該可以確認tartMultiAdvertising的實現是在這里,那我們找一下它的實現:@Override
public void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, AdvertiseData scanResponse, AdvertiseSettings settings) { GattService service = getService(); if (service == null) return; service.startMultiAdvertising(clientIf, advertiseData, scanResponse, settings);
}
終于找到它的實現了,它卻有用了GattService自己內部的實現,那我們繼續看一下:void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, AdvertiseData scanResponse, AdvertiseSettings settings) { enforceAdminPermission(); mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, scanResponse));
}
到這里,我們有可以比較順利的追蹤了,那我們繼續看一下AdvertiserManager是怎樣定義它的:void startAdvertising(AdvertiseClient client) { if (client == null) { return; } Message message = new Message(); message.what = MSG_START_ADVERTISING; message.obj = client; mHandler.sendMessage(message);
}
到這里,發現竟然只是發了一個handler message,那我們就去看看這個handler是怎么處理
@Override public void handleMessage(Message msg) { logd("message : " + msg.what); AdvertiseClient client = (AdvertiseClient) msg.obj; switch (msg.what) { case MSG_START_ADVERTISING: handleStartAdvertising(client); break; case MSG_STOP_ADVERTISING: handleStopAdvertising(client); break; default: // Shouldn't happen. Log.e(TAG, "recieve an unknown message : " + msg.what); break; } }
private void handleStartAdvertising(AdvertiseClient client) { Utils.enforceAdminPermission(mService); int clientIf = client.clientIf; if (mAdvertiseClients.contains(clientIf)) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); return; } if (mAdvertiseClients.size() >= maxAdvertiseInstances()) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS); return; } if (!mAdvertiseNative.startAdverising(client)) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); return; } mAdvertiseClients.add(client); postCallback(clientIf, AdvertiseCallback.ADVERTISE_SUCCESS); } 到這里了,我們也看到了關鍵函數mAdvertiseNative.startAdvertising函數:boolean startAdverising(AdvertiseClient client) { if (!mAdapterService.isMultiAdvertisementSupported() && !mAdapterService.isPeripheralModeSupported()) { return false; } if (mAdapterService.isMultiAdvertisementSupported()) { return startMultiAdvertising(client); } return startSingleAdvertising(client); } 這里我們就選擇任意一個函數就講解,就選擇startSingleAdvertising來講好了:boolean startSingleAdvertising(AdvertiseClient client) { logd("starting single advertising"); resetCountDownLatch(); enableAdvertising(client); if (!waitForCallback()) { return false; } setAdvertisingData(client, client.advertiseData, false); return true; } 這里面有兩個關鍵點,一個是使能Advertising,另一個是設置AdvertisingData要發的數據。我們先來看一下enableAdvertising:private void enableAdvertising(AdvertiseClient client) { int clientIf = client.clientIf; int minAdvertiseUnit = (int) getAdvertisingIntervalUnit(client.settings); int maxAdvertiseUnit = minAdvertiseUnit + ADVERTISING_INTERVAL_DELTA_UNIT; int advertiseEventType = getAdvertisingEventType(client); int txPowerLevel = getTxPowerLevel(client.settings); int advertiseTimeoutSeconds = (int) TimeUnit.MILLISECONDS.toSeconds( client.settings.getTimeout()); if (mAdapterService.isMultiAdvertisementSupported()) { Log.i(TAG, "gattClientEnableAdvNative(" + clientIf + ",...);"); gattClientEnableAdvNative( clientIf, minAdvertiseUnit, maxAdvertiseUnit, advertiseEventType, ADVERTISING_CHANNEL_ALL, txPowerLevel, advertiseTimeoutSeconds); } else { Log.i(TAG, "gattAdvertiseNative(" + client.clientIf + ",true);"); gattAdvertiseNative(client.clientIf, true); } } 這里面主要是在設置一些參數,比如最大廣播間隔設置的是10ms+設置的最小間隔,TxPower的級別等等。這里面對于多廣播和單廣播調用的底層是不一樣的。我們這里看看單廣播gattAdvertiseNative(client.clientIf, true);實現如下:static void gattAdvertiseNative(JNIEnv *env, jobject object, jint client_if, jboolean start) { if (!sGattIf) return; sGattIf->client->listen(client_if, start); } 這里的映射關系我就不再介紹了,上一篇文章已經都介紹一次了,我們這里直接看看listen函數:static bt_status_t btif_gattc_listen(int client_if, bool start) { CHECK_BTGATT_INIT(); btif_gattc_cb_t btif_cb; btif_cb.client_if = (uint8_t) client_if; btif_cb.start = start ? 1 : 0; return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_LISTEN, (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL); } 直接看實現: static void btgattc_handle_event(uint16_t event, char* p_param) { …… switch (event) { case BTIF_GATTC_LISTEN: #if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE)) BTA_GATTC_Listen(p_cb->client_if, p_cb->start, NULL); #else BTA_GATTC_Broadcast(p_cb->client_if, p_cb->start); #endif break; …… 目前我用的設備BLE_PERIPHERAL_MODE_SUPPORT是true,所以我們進入BTA_GATTC_Listen:void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda) { tBTA_GATTC_API_LISTEN *p_buf; if ((p_buf = (tBTA_GATTC_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL) { p_buf->hdr.event = BTA_GATTC_API_LISTEN_EVT; p_buf->client_if = client_if; p_buf->start = start; if (target_bda) { p_buf->remote_bda = (UINT8*)(p_buf + 1); memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN); } else p_buf->remote_bda = NULL; bta_sys_sendmsg(p_buf); } return; } 這里是開始進入廣播且監聽一個client設備的連接請求。這里要注意一下event時間,這個時間會被觸發:BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) { …… case BTA_GATTC_API_LISTEN_EVT: bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg); break; …… [cpp] view plaincopy void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg) { tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if); tBTA_GATTC cb_data; UNUSED(p_cb); cb_data.reg_oper.status = BTA_GATT_ERROR; cb_data.reg_oper.client_if = p_msg->api_listen.client_if; if (p_clreg == NULL) { APPL_TRACE_ERROR("bta_gattc_listen failed, unknown client_if: %d", p_msg->api_listen.client_if); return; } /* mark bg conn record */ if (bta_gattc_mark_bg_conn(p_msg->api_listen.client_if, (BD_ADDR_PTR) p_msg->api_listen.remote_bda, p_msg->api_listen.start, TRUE)) { if (!GATT_Listen(p_msg->api_listen.client_if, p_msg->api_listen.start, p_msg->api_listen.remote_bda)) { APPL_TRACE_ERROR("Listen failure"); (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); } else { cb_data.status = BTA_GATT_OK; (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); if (p_msg->api_listen.start) { /* if listen to a specific target */ if (p_msg->api_listen.remote_bda != NULL) { /* if is a connected remote device */ if (L2CA_GetBleConnRole(p_msg->api_listen.remote_bda) == HCI_ROLE_SLAVE && bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if, p_msg->api_listen.remote_bda, BTA_GATT_TRANSPORT_LE) == NULL) { bta_gattc_init_clcb_conn(p_msg->api_listen.client_if, p_msg->api_listen.remote_bda); } } /* if listen to all */ else { APPL_TRACE_ERROR("Listen For All now"); /* go through all connected device and send callback for all connected slave connection */ bta_gattc_process_listen_all(p_msg->api_listen.client_if); } } } } } 到這里,剩下的全是連接相關,我自己都有點繞,所以暫時就不講解了。這塊后期再補上。
private void setAdvertisingData(AdvertiseClient client, AdvertiseData data, boolean isScanResponse) { if (data == null) { return; } boolean includeName = data.getIncludeDeviceName(); boolean includeTxPower = data.getIncludeTxPowerLevel(); int appearance = 0; byte[] manufacturerData = getManufacturerData(data); byte[] serviceData = getServiceData(data); byte[] serviceUuids; if (data.getServiceUuids() == null) { serviceUuids = new byte[0]; } else { ByteBuffer advertisingUuidBytes = ByteBuffer.allocate( data.getServiceUuids().size() * 16) .order(ByteOrder.LITTLE_ENDIAN); for (ParcelUuid parcelUuid : data.getServiceUuids()) { UUID uuid = parcelUuid.getUuid(); // Least significant bits first as the advertising UUID should be in // little-endian. advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) .putLong(uuid.getMostSignificantBits()); } serviceUuids = advertisingUuidBytes.array(); } if (mAdapterService.isMultiAdvertisementSupported()) { Log.i(TAG, "gattClientSetAdvDataNative(" + client.clientIf + ",...);"); gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName, includeTxPower, appearance, manufacturerData, serviceData, serviceUuids); } else { Log.i(TAG, "gattSetAdvDataNative(" + client.clientIf + ",...);"); gattSetAdvDataNative(client.clientIf, isScanResponse, includeName, includeTxPower, 0, 0, appearance, manufacturerData, serviceData, serviceUuids); } }
static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if, jboolean setScanRsp, jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData, jbyteArray serviceData, jbyteArray serviceUuid) { if (!sGattIf) return; jbyte* arr_data = env->GetByteArrayElements(manufacturerData, NULL); uint16_t arr_len = (uint16_t) env->GetArrayLength(manufacturerData); jbyte* service_data = env->GetByteArrayElements(serviceData, NULL); uint16_t service_data_len = (uint16_t) env->GetArrayLength(serviceData); jbyte* service_uuid = env->GetByteArrayElements(serviceUuid, NULL); uint16_t service_uuid_len = (uint16_t) env->GetArrayLength(serviceUuid); sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower, minInterval, maxInterval, appearance, arr_len, (char*)arr_data, service_data_len, (char*)service_data, service_uuid_len, (char*)service_uuid); env->ReleaseByteArrayElements(manufacturerData, arr_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceData, service_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceUuid, service_uuid, JNI_ABORT); } 那我們就來主要看看set_adv_data函數:static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, bool include_name, bool include_txpower, int min_interval, int max_interval, int appearance, uint16_t manufacturer_len, char* manufacturer_data, uint16_t service_data_len, char* service_data, uint16_t service_uuid_len, char* service_uuid) { CHECK_BTGATT_INIT(); bt_status_t status =0; btif_adv_data_t adv_data; btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, include_txpower, min_interval, max_interval, appearance, manufacturer_len, manufacturer_data, service_data_len, service_data, service_uuid_len, service_uuid, &adv_data); status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA, (char*) &adv_data, sizeof(btif_adv_data_t), NULL); if (NULL != adv_data.p_service_data) GKI_freebuf(adv_data.p_service_data); if (NULL != adv_data.p_service_uuid) GKI_freebuf(adv_data.p_service_uuid); if (NULL != adv_data.p_manufacturer_data) GKI_freebuf(adv_data.p_manufacturer_data); return status; } 其中btif_gattc_adv_data_packager直接到了GKI,所以我們來看一下btgattc_handle_event觸發的event事件:case BTIF_GATTC_SET_ADV_DATA: { btif_adv_data_t *p_adv_data = (btif_adv_data_t*) p_param; int cbindex = CLNT_IF_IDX; if (cbindex >= 0 && NULL != p_adv_data) { btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); if (!btif_gattc_copy_datacb(cbindex, p_adv_data, false)) return; if (!p_adv_data->set_scan_rsp) { BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask, &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback); } else { BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask, &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback); } break; } } 這里我們主要是走了BTA_DmBleSetAdvConfig:void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg, tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback) { tBTA_DM_API_SET_ADV_CONFIG *p_msg; if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL) { p_msg->hdr.event = BTA_DM_API_BLE_SET_ADV_CONFIG_EVT; p_msg->data_mask = data_mask; p_msg->p_adv_data_cback = p_adv_data_cback; p_msg->p_adv_cfg = p_adv_cfg; bta_sys_sendmsg(p_msg); } } 這里實際會走到
void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data) { tBTA_STATUS status = BTA_FAILURE; if (BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask, (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS) { status = BTA_SUCCESS; } if (p_data->ble_set_adv_data.p_adv_data_cback) (*p_data->ble_set_adv_data.p_adv_data_cback)(status); }
tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p_data) { tBTM_BLE_LOCAL_ADV_DATA *p_cb_data = &btm_cb.ble_ctr_cb.inq_var.adv_data; UINT8 *p; tBTM_BLE_AD_MASK mask = data_mask; BTM_TRACE_EVENT ("BTM_BleWriteAdvData "); if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) return BTM_ILLEGAL_VALUE; memset(p_cb_data, 0, sizeof(tBTM_BLE_LOCAL_ADV_DATA)); p = p_cb_data->ad_data; p_cb_data->data_mask = data_mask; p_cb_data->p_flags = btm_ble_build_adv_data(&mask, &p, p_data); p_cb_data->p_pad = p; if (mask != 0) { BTM_TRACE_ERROR("Partial data write into ADV"); } p_cb_data->data_mask &= ~mask; if (btsnd_hcic_ble_set_adv_data((UINT8)(p_cb_data->p_pad - p_cb_data->ad_data), p_cb_data->ad_data)) return BTM_SUCCESS; else return BTM_NO_RESOURCES; }
BOOLEAN btsnd_hcic_ble_set_adv_data (UINT8 data_len, UINT8 *p_data) { BT_HDR *p; UINT8 *pp; if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1)) == NULL) return (FALSE); pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1; p->offset = 0; UINT16_TO_STREAM (pp, HCI_BLE_WRITE_ADV_DATA); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); memset(pp, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA); if (p_data != NULL && data_len > 0) { if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA) data_len = HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA; UINT8_TO_STREAM (pp, data_len); ARRAY_TO_STREAM (pp, p_data, data_len); } btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); } 后面已經直接在btu通信了,我們也就不深入了。 所以步驟跑完,在callback就會獲得onSuccess中。廣播就結束了,后面我會繼續更新Central相關流程。
@Override public void handleMessage(Message msg) { logd("message : " + msg.what); AdvertiseClient client = (AdvertiseClient) msg.obj; switch (msg.what) { case MSG_START_ADVERTISING: handleStartAdvertising(client); break; case MSG_STOP_ADVERTISING: handleStopAdvertising(client); break; default: // Shouldn't happen. Log.e(TAG, "recieve an unknown message : " + msg.what); break; } }
private void handleStartAdvertising(AdvertiseClient client) { Utils.enforceAdminPermission(mService); int clientIf = client.clientIf; if (mAdvertiseClients.contains(clientIf)) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); return; } if (mAdvertiseClients.size() >= maxAdvertiseInstances()) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS); return; } if (!mAdvertiseNative.startAdverising(client)) { postCallback(clientIf, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); return; } mAdvertiseClients.add(client); postCallback(clientIf, AdvertiseCallback.ADVERTISE_SUCCESS); } 到這里了,我們也看到了關鍵函數mAdvertiseNative.startAdvertising函數:boolean startAdverising(AdvertiseClient client) { if (!mAdapterService.isMultiAdvertisementSupported() && !mAdapterService.isPeripheralModeSupported()) { return false; } if (mAdapterService.isMultiAdvertisementSupported()) { return startMultiAdvertising(client); } return startSingleAdvertising(client); } 這里我們就選擇任意一個函數就講解,就選擇startSingleAdvertising來講好了:boolean startSingleAdvertising(AdvertiseClient client) { logd("starting single advertising"); resetCountDownLatch(); enableAdvertising(client); if (!waitForCallback()) { return false; } setAdvertisingData(client, client.advertiseData, false); return true; } 這里面有兩個關鍵點,一個是使能Advertising,另一個是設置AdvertisingData要發的數據。我們先來看一下enableAdvertising:private void enableAdvertising(AdvertiseClient client) { int clientIf = client.clientIf; int minAdvertiseUnit = (int) getAdvertisingIntervalUnit(client.settings); int maxAdvertiseUnit = minAdvertiseUnit + ADVERTISING_INTERVAL_DELTA_UNIT; int advertiseEventType = getAdvertisingEventType(client); int txPowerLevel = getTxPowerLevel(client.settings); int advertiseTimeoutSeconds = (int) TimeUnit.MILLISECONDS.toSeconds( client.settings.getTimeout()); if (mAdapterService.isMultiAdvertisementSupported()) { Log.i(TAG, "gattClientEnableAdvNative(" + clientIf + ",...);"); gattClientEnableAdvNative( clientIf, minAdvertiseUnit, maxAdvertiseUnit, advertiseEventType, ADVERTISING_CHANNEL_ALL, txPowerLevel, advertiseTimeoutSeconds); } else { Log.i(TAG, "gattAdvertiseNative(" + client.clientIf + ",true);"); gattAdvertiseNative(client.clientIf, true); } } 這里面主要是在設置一些參數,比如最大廣播間隔設置的是10ms+設置的最小間隔,TxPower的級別等等。這里面對于多廣播和單廣播調用的底層是不一樣的。我們這里看看單廣播gattAdvertiseNative(client.clientIf, true);實現如下:static void gattAdvertiseNative(JNIEnv *env, jobject object, jint client_if, jboolean start) { if (!sGattIf) return; sGattIf->client->listen(client_if, start); } 這里的映射關系我就不再介紹了,上一篇文章已經都介紹一次了,我們這里直接看看listen函數:static bt_status_t btif_gattc_listen(int client_if, bool start) { CHECK_BTGATT_INIT(); btif_gattc_cb_t btif_cb; btif_cb.client_if = (uint8_t) client_if; btif_cb.start = start ? 1 : 0; return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_LISTEN, (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL); } 直接看實現: static void btgattc_handle_event(uint16_t event, char* p_param) { …… switch (event) { case BTIF_GATTC_LISTEN: #if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE)) BTA_GATTC_Listen(p_cb->client_if, p_cb->start, NULL); #else BTA_GATTC_Broadcast(p_cb->client_if, p_cb->start); #endif break; …… 目前我用的設備BLE_PERIPHERAL_MODE_SUPPORT是true,所以我們進入BTA_GATTC_Listen:void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda) { tBTA_GATTC_API_LISTEN *p_buf; if ((p_buf = (tBTA_GATTC_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL) { p_buf->hdr.event = BTA_GATTC_API_LISTEN_EVT; p_buf->client_if = client_if; p_buf->start = start; if (target_bda) { p_buf->remote_bda = (UINT8*)(p_buf + 1); memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN); } else p_buf->remote_bda = NULL; bta_sys_sendmsg(p_buf); } return; } 這里是開始進入廣播且監聽一個client設備的連接請求。這里要注意一下event時間,這個時間會被觸發:BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) { …… case BTA_GATTC_API_LISTEN_EVT: bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg); break; …… [cpp] view plaincopy void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg) { tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if); tBTA_GATTC cb_data; UNUSED(p_cb); cb_data.reg_oper.status = BTA_GATT_ERROR; cb_data.reg_oper.client_if = p_msg->api_listen.client_if; if (p_clreg == NULL) { APPL_TRACE_ERROR("bta_gattc_listen failed, unknown client_if: %d", p_msg->api_listen.client_if); return; } /* mark bg conn record */ if (bta_gattc_mark_bg_conn(p_msg->api_listen.client_if, (BD_ADDR_PTR) p_msg->api_listen.remote_bda, p_msg->api_listen.start, TRUE)) { if (!GATT_Listen(p_msg->api_listen.client_if, p_msg->api_listen.start, p_msg->api_listen.remote_bda)) { APPL_TRACE_ERROR("Listen failure"); (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); } else { cb_data.status = BTA_GATT_OK; (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); if (p_msg->api_listen.start) { /* if listen to a specific target */ if (p_msg->api_listen.remote_bda != NULL) { /* if is a connected remote device */ if (L2CA_GetBleConnRole(p_msg->api_listen.remote_bda) == HCI_ROLE_SLAVE && bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if, p_msg->api_listen.remote_bda, BTA_GATT_TRANSPORT_LE) == NULL) { bta_gattc_init_clcb_conn(p_msg->api_listen.client_if, p_msg->api_listen.remote_bda); } } /* if listen to all */ else { APPL_TRACE_ERROR("Listen For All now"); /* go through all connected device and send callback for all connected slave connection */ bta_gattc_process_listen_all(p_msg->api_listen.client_if); } } } } } 到這里,剩下的全是連接相關,我自己都有點繞,所以暫時就不講解了。這塊后期再補上。
private void setAdvertisingData(AdvertiseClient client, AdvertiseData data, boolean isScanResponse) { if (data == null) { return; } boolean includeName = data.getIncludeDeviceName(); boolean includeTxPower = data.getIncludeTxPowerLevel(); int appearance = 0; byte[] manufacturerData = getManufacturerData(data); byte[] serviceData = getServiceData(data); byte[] serviceUuids; if (data.getServiceUuids() == null) { serviceUuids = new byte[0]; } else { ByteBuffer advertisingUuidBytes = ByteBuffer.allocate( data.getServiceUuids().size() * 16) .order(ByteOrder.LITTLE_ENDIAN); for (ParcelUuid parcelUuid : data.getServiceUuids()) { UUID uuid = parcelUuid.getUuid(); // Least significant bits first as the advertising UUID should be in // little-endian. advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) .putLong(uuid.getMostSignificantBits()); } serviceUuids = advertisingUuidBytes.array(); } if (mAdapterService.isMultiAdvertisementSupported()) { Log.i(TAG, "gattClientSetAdvDataNative(" + client.clientIf + ",...);"); gattClientSetAdvDataNative(client.clientIf, isScanResponse, includeName, includeTxPower, appearance, manufacturerData, serviceData, serviceUuids); } else { Log.i(TAG, "gattSetAdvDataNative(" + client.clientIf + ",...);"); gattSetAdvDataNative(client.clientIf, isScanResponse, includeName, includeTxPower, 0, 0, appearance, manufacturerData, serviceData, serviceUuids); } }
static void gattSetAdvDataNative(JNIEnv *env, jobject object, jint client_if, jboolean setScanRsp, jboolean inclName, jboolean inclTxPower, jint minInterval, jint maxInterval, jint appearance, jbyteArray manufacturerData, jbyteArray serviceData, jbyteArray serviceUuid) { if (!sGattIf) return; jbyte* arr_data = env->GetByteArrayElements(manufacturerData, NULL); uint16_t arr_len = (uint16_t) env->GetArrayLength(manufacturerData); jbyte* service_data = env->GetByteArrayElements(serviceData, NULL); uint16_t service_data_len = (uint16_t) env->GetArrayLength(serviceData); jbyte* service_uuid = env->GetByteArrayElements(serviceUuid, NULL); uint16_t service_uuid_len = (uint16_t) env->GetArrayLength(serviceUuid); sGattIf->client->set_adv_data(client_if, setScanRsp, inclName, inclTxPower, minInterval, maxInterval, appearance, arr_len, (char*)arr_data, service_data_len, (char*)service_data, service_uuid_len, (char*)service_uuid); env->ReleaseByteArrayElements(manufacturerData, arr_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceData, service_data, JNI_ABORT); env->ReleaseByteArrayElements(serviceUuid, service_uuid, JNI_ABORT); } 那我們就來主要看看set_adv_data函數:static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, bool include_name, bool include_txpower, int min_interval, int max_interval, int appearance, uint16_t manufacturer_len, char* manufacturer_data, uint16_t service_data_len, char* service_data, uint16_t service_uuid_len, char* service_uuid) { CHECK_BTGATT_INIT(); bt_status_t status =0; btif_adv_data_t adv_data; btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, include_txpower, min_interval, max_interval, appearance, manufacturer_len, manufacturer_data, service_data_len, service_data, service_uuid_len, service_uuid, &adv_data); status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA, (char*) &adv_data, sizeof(btif_adv_data_t), NULL); if (NULL != adv_data.p_service_data) GKI_freebuf(adv_data.p_service_data); if (NULL != adv_data.p_service_uuid) GKI_freebuf(adv_data.p_service_uuid); if (NULL != adv_data.p_manufacturer_data) GKI_freebuf(adv_data.p_manufacturer_data); return status; } 其中btif_gattc_adv_data_packager直接到了GKI,所以我們來看一下btgattc_handle_event觸發的event事件:case BTIF_GATTC_SET_ADV_DATA: { btif_adv_data_t *p_adv_data = (btif_adv_data_t*) p_param; int cbindex = CLNT_IF_IDX; if (cbindex >= 0 && NULL != p_adv_data) { btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); if (!btif_gattc_copy_datacb(cbindex, p_adv_data, false)) return; if (!p_adv_data->set_scan_rsp) { BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask, &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback); } else { BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask, &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback); } break; } } 這里我們主要是走了BTA_DmBleSetAdvConfig:void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg, tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback) { tBTA_DM_API_SET_ADV_CONFIG *p_msg; if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL) { p_msg->hdr.event = BTA_DM_API_BLE_SET_ADV_CONFIG_EVT; p_msg->data_mask = data_mask; p_msg->p_adv_data_cback = p_adv_data_cback; p_msg->p_adv_cfg = p_adv_cfg; bta_sys_sendmsg(p_msg); } } 這里實際會走到
void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data) { tBTA_STATUS status = BTA_FAILURE; if (BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask, (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS) { status = BTA_SUCCESS; } if (p_data->ble_set_adv_data.p_adv_data_cback) (*p_data->ble_set_adv_data.p_adv_data_cback)(status); }
tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p_data) { tBTM_BLE_LOCAL_ADV_DATA *p_cb_data = &btm_cb.ble_ctr_cb.inq_var.adv_data; UINT8 *p; tBTM_BLE_AD_MASK mask = data_mask; BTM_TRACE_EVENT ("BTM_BleWriteAdvData "); if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1])) return BTM_ILLEGAL_VALUE; memset(p_cb_data, 0, sizeof(tBTM_BLE_LOCAL_ADV_DATA)); p = p_cb_data->ad_data; p_cb_data->data_mask = data_mask; p_cb_data->p_flags = btm_ble_build_adv_data(&mask, &p, p_data); p_cb_data->p_pad = p; if (mask != 0) { BTM_TRACE_ERROR("Partial data write into ADV"); } p_cb_data->data_mask &= ~mask; if (btsnd_hcic_ble_set_adv_data((UINT8)(p_cb_data->p_pad - p_cb_data->ad_data), p_cb_data->ad_data)) return BTM_SUCCESS; else return BTM_NO_RESOURCES; }
BOOLEAN btsnd_hcic_ble_set_adv_data (UINT8 data_len, UINT8 *p_data) { BT_HDR *p; UINT8 *pp; if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1)) == NULL) return (FALSE); pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1; p->offset = 0; UINT16_TO_STREAM (pp, HCI_BLE_WRITE_ADV_DATA); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); memset(pp, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA); if (p_data != NULL && data_len > 0) { if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA) data_len = HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA; UINT8_TO_STREAM (pp, data_len); ARRAY_TO_STREAM (pp, p_data, data_len); } btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); } 后面已經直接在btu通信了,我們也就不深入了。 所以步驟跑完,在callback就會獲得onSuccess中。廣播就結束了,后面我會繼續更新Central相關流程。
?
轉載于:https://www.cnblogs.com/Free-Thinker/p/4848439.html
總結
以上是生活随笔為你收集整理的android5.0(Lollipop) BLE Peripheral深入理解系统篇之提高篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈Linux中的信号处理机制(三)
- 下一篇: 浮点类型的精度问题