• 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相关流程。
  • 相关阅读:
    【leetcode】1630. Arithmetic Subarrays
    【leetcode】1629. Slowest Key
    【leetcode】1624. Largest Substring Between Two Equal Characters
    【leetcode】1620. Coordinate With Maximum Network Quality
    【leetcode】1619. Mean of Array After Removing Some Elements
    【leetcode】1609. Even Odd Tree
    【leetcode】1608. Special Array With X Elements Greater Than or Equal X
    【leetcode】1603. Design Parking System
    【leetcode】1598. Crawler Log Folder
    Java基础加强总结(三)——代理(Proxy)Java实现Ip代理池
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4848439.html
Copyright © 2020-2023  润新知