A: How to do the createBond oper

作者: ZafirTab | 来源:发表于2017-09-21 16:36 被阅读0次
    • 导语
      该篇文章,主要介绍createBond操作在Android的调用流程,Android7.0为例。
    1. 调用流程图
    framework->HAL bluedroid stack内部
    2. 调用详解
    • 具体的蓝牙应用APP下发createBond操作;
    • 调用到framework层的createBond()方法,该方法通过AIDL进行进程间通信,继续调用;
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
        public boolean createBond() {
            if (sService == null) {
                Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
                return false;
            }
            try {
                Log.i(TAG, "createBond() for device " + getAddress() +
                        " called by pid: " + Process.myPid() +
                        " tid: " + Process.myTid());
                return sService.createBond(this, TRANSPORT_AUTO);   //此处为跳转代码
            } catch (RemoteException e) {Log.e(TAG, "", e);}
            return false;
        }
    
    private static IBluetooth sService;    //IBluetooth AIDL定义
    
    • BluetoothDevice.java中还有一个createBondOutOfBand()方法,该方法用于带外传输(非2.4GHz)。如通过NFC来实现蓝牙MAC和link key的交换,以达到“不用配对”的用户体验;
        public boolean createBondOutOfBand(int transport, OobData oobData) {
            try {
                return sService.createBondOutOfBand(this, transport, oobData);
            } catch (RemoteException e) {Log.e(TAG, "", e);}
            return false;
        }
    
    • createBond()方法中的transport参数,0代表未知设备类型,1代表BR/EDR,2代表LE;
    • createBond()会进入到AdapterService中的createBond()方法;
    private static class AdapterServiceBinder extends IBluetooth.Stub {
    
         boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                "Need BLUETOOTH ADMIN permission");
            DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
            if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
                return false;
            }
    
            // Pairing is unreliable while scanning, so cancel discovery
            // Note, remove this when native stack improves
            cancelDiscoveryNative();     //取消扫描操作
    
            Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
            msg.obj = device;
            msg.arg1 = transport;
    
            if (oobData != null) {   //使用带外传输,完成绑定过程
                Bundle oobDataBundle = new Bundle();
                oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
                msg.setData(oobDataBundle);
            }
            mBondStateMachine.sendMessage(msg);   //发送信息给状态机
            return true;
        }
    
    
    • BondStateMachine接收到CREATE_BOND消息会会调用其内部的createBond方法;
        private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
                                   boolean transition) {
            if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
                infoLog("Bond address is:" + dev);
                byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
                boolean result;
                if (oobData != null) {
                    result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
                } else {
                    result = mAdapterService.createBondNative(addr, transport);  //JNI
                }
    
                if (!result) {
                    sendIntent(dev, BluetoothDevice.BOND_NONE,
                               BluetoothDevice.UNBOND_REASON_REMOVED);
                    return false;
                } else if (transition) {
                    transitionTo(mPendingCommandState);
                }
                return true;
            }
            return false;
        }
    
    • 进行JNI调用,接着到createBondNative方法;
    static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
        ALOGV("%s:",__FUNCTION__);
    
        jbyte *addr;
        jboolean result = JNI_FALSE;
    
        if (!sBluetoothInterface) return result;
    
        addr = env->GetByteArrayElements(address, NULL);
        if (addr == NULL) {
            jniThrowIOException(env, EINVAL);
            return result;
        }
    
        int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);      //调用HAL层接口
        env->ReleaseByteArrayElements(address, addr, 0);   
        result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    
        return result;
    }
    
    
    • createBondNative方法调用到HAL层的接口;
        /** Create Bluetooth Bonding */
        int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport);
    

    • 至此会进入BlueDroid,继续进行调用;
    static int create_bond(const bt_bdaddr_t *bd_addr, int transport)
    {
        /* sanity check */
        if (interface_ready() == FALSE)
            return BT_STATUS_NOT_READY;
    
        return btif_dm_create_bond(bd_addr, transport);   //next
    }
    
    • 此处的btif_dm_create_bond函数不会进行实际bond操作,只是将事件抛出去,由其他的线程进行处理;

    此处的设计很巧妙,因为如果上层所有的蓝牙相关操作事件下发下来,在此就进行处理,在实际编码中必然要加上很多的互斥操作,这就增加了设计的复杂性。

    bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr, int transport)
    {
        btif_dm_create_bond_cb_t create_bond_cb;
        create_bond_cb.transport = transport;
        bdcpy(create_bond_cb.bdaddr.address, bd_addr->address);
    
        bdstr_t bdstr;
        BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__, bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport);
        if (pairing_cb.state != BT_BOND_STATE_NONE)
            return BT_STATUS_BUSY;
    
        btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CREATE_BOND, pairing_cb.state);
    
        btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND,
                              (char *)&create_bond_cb, sizeof(btif_dm_create_bond_cb_t), NULL);
    
        return BT_STATUS_SUCCESS;
    }
    
    • btif_dm_generic_evt函数会接收这个事件并进行后续处理;
            case BTIF_DM_CB_CREATE_BOND:
            {
                pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
                btif_dm_create_bond_cb_t *create_bond_cb = (btif_dm_create_bond_cb_t*)p_param;
                btif_dm_cb_create_bond(&create_bond_cb->bdaddr, create_bond_cb->transport);
            }
            break;
    
    • btif_dm_cb_create_bond函数会对绑定事件进行处理,此处对HID设备进行了特别的处理;
    static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transport)
    {
        BOOLEAN is_hid = check_cod(bd_addr, COD_HID_POINTING);
        bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
    
    #if BLE_INCLUDED == TRUE
        int device_type;
        int addr_type;
        bdstr_t bdstr;
        bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr));
        if (transport == BT_TRANSPORT_LE)
        {
            if (!btif_config_get_int((char const *)&bdstr,"DevType", &device_type))
            {
                btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
            }
            if (btif_storage_get_remote_addr_type(bd_addr, &addr_type) != BT_STATUS_SUCCESS)
            {
                btif_storage_set_remote_addr_type(bd_addr, BLE_ADDR_PUBLIC);
            }
        }
        if((btif_config_get_int((char const *)&bdstr,"DevType", &device_type) &&
           (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
           (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) || (transport == BT_TRANSPORT_LE))
        {
            BTA_DmAddBleDevice(bd_addr->address, addr_type, device_type);
        }
    #endif
    // --ZafirTab-- 对HID设备的特殊处理
    #if BLE_INCLUDED == TRUE
        if(is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0)
    #else
        if(is_hid)
    #endif
        {
            int status;
            status = btif_hh_connect(bd_addr);
            if(status != BT_STATUS_SUCCESS)
                bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
        }
        else
        {
            BTA_DmBondByTransport((UINT8 *)bd_addr->address, transport);    // --ZafirTab--  next
        }
        /*  Track  originator of bond creation  */
        pairing_cb.is_local_initiated = TRUE;
    
    }
    
    
    • 此处我们直接看HID设备的bond;
    void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport)
    {
        tBTA_DM_API_BOND *p_msg =
            (tBTA_DM_API_BOND *)osi_malloc(sizeof(tBTA_DM_API_BOND));
    
        p_msg->hdr.event = BTA_DM_API_BOND_EVT;    //抛出的事件
        bdcpy(p_msg->bd_addr, bd_addr);
        p_msg->transport = transport;
    
        bta_sys_sendmsg(p_msg);
    }
    
    • BTA_DmBondByTransport函数也没有对事件进行直接处理,又将事件抛出去了;
      BTA_DM_API_BOND_EVT事件对应的是bta_dm_bond操作;
    /* action function list */
    const tBTA_DM_ACTION bta_dm_action[] =
    {
    
        /* device manager local device API events */
        bta_dm_enable,            /* 0  BTA_DM_API_ENABLE_EVT */
        bta_dm_disable,           /* 1  BTA_DM_API_DISABLE_EVT */
        bta_dm_set_dev_name,      /* 2  BTA_DM_API_SET_NAME_EVT */
        bta_dm_set_visibility,    /* 3  BTA_DM_API_SET_VISIBILITY_EVT */
        bta_dm_acl_change,        /* 8  BTA_DM_ACL_CHANGE_EVT */
        bta_dm_add_device,        /* 9  BTA_DM_API_ADD_DEVICE_EVT */
        bta_dm_close_acl,        /* 10  BTA_DM_API_ADD_DEVICE_EVT */
    
        /* security API events */
        bta_dm_bond,              /* 11  BTA_DM_API_BOND_EVT */
        bta_dm_bond_cancel,       /* 12  BTA_DM_API_BOND_CANCEL_EVT */
    
    • bta_dm_bond函数会调用btm_sec_bond_by_transport函数来启动SSP或者SMP;此处分支较多,我们后续以2.1 即BR/EDR继续分析;
    tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
                                           UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
    {
        tBTM_SEC_DEV_REC *p_dev_rec;
        tBTM_STATUS      status;
        UINT8            *p_features;
        UINT8            ii;
        tACL_CONN        *p= btm_bda_to_acl(bd_addr, transport);
        BTM_TRACE_API ("btm_sec_bond_by_transport BDA: %02x:%02x:%02x:%02x:%02x:%02x",
                        bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
    
        BTM_TRACE_DEBUG("btm_sec_bond_by_transport: Transport used %d" , transport);
    
        /* Other security process is in progress */
        if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
        {
            BTM_TRACE_ERROR ("BTM_SecBond: already busy in state: %s", btm_pair_state_descr(btm_cb.pairing_state));
            return(BTM_WRONG_MODE);
        }
    
        if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL)
        {
            return(BTM_NO_RESOURCES);
        }
    
        BTM_TRACE_DEBUG ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
    
        /* Finished if connection is active and already paired */
        if ( ((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR
             &&  (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))
    #if (BLE_INCLUDED == TRUE)
            ||((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) && transport == BT_TRANSPORT_LE
             &&  (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))
    #endif
    
             )
        {
            BTM_TRACE_WARNING("BTM_SecBond -> Already Paired");
            return(BTM_SUCCESS);
        }
    
        /* Tell controller to get rid of the link key if it has one stored */
        if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS)
            return(BTM_NO_RESOURCES);
    
        /* Save the PIN code if we got a valid one */
        if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0))
        {
            btm_cb.pin_code_len = pin_len;
            p_dev_rec->pin_code_length = pin_len;
            memcpy (btm_cb.pin_code, p_pin, PIN_CODE_LEN);
        }
    
        memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
    
        btm_cb.pairing_flags = BTM_PAIR_FLAGS_WE_STARTED_DD;
    
        p_dev_rec->security_required = BTM_SEC_OUT_AUTHENTICATE;
        p_dev_rec->is_originator     = TRUE;
        if (trusted_mask)
            BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
    
    #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
        if (transport == BT_TRANSPORT_LE)
        {
            btm_ble_init_pseudo_addr (p_dev_rec, bd_addr);
            p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
    
            if (SMP_Pair(bd_addr) == SMP_STARTED)
            {
                btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
                p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
                btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
                return BTM_CMD_STARTED;
            }
    
            btm_cb.pairing_flags = 0;
            return(BTM_NO_RESOURCES);
        }
    #endif
    
        p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
                                      | BTM_SEC_ROLE_SWITCHED  | BTM_SEC_LINK_KEY_AUTHED);
    
        BTM_TRACE_DEBUG ("after update sec_flags=0x%x", p_dev_rec->sec_flags);
        if (!controller_get_interface()->supports_simple_pairing())
        {
            /* The special case when we authenticate keyboard.  Set pin type to fixed */
            /* It would be probably better to do it from the application, but it is */
            /* complicated */
            if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL)
                && (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD)
                && (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED))
            {
                btm_cb.pin_type_changed = TRUE;
                btsnd_hcic_write_pin_type (HCI_PIN_TYPE_FIXED);
            }
        }
    
        for (ii = 0; ii <= HCI_EXT_FEATURES_PAGE_MAX; ii++)
        {
            p_features = p_dev_rec->features[ii];
            BTM_TRACE_EVENT("  remote_features page[%1d] = %02x-%02x-%02x-%02x",
                             ii, p_features[0], p_features[1], p_features[2], p_features[3]);
            BTM_TRACE_EVENT("                              %02x-%02x-%02x-%02x",
                                 p_features[4], p_features[5], p_features[6], p_features[7]);
        }
    
        BTM_TRACE_EVENT ("BTM_SecBond: Remote sm4: 0x%x  HCI Handle: 0x%04x", p_dev_rec->sm4, p_dev_rec->hci_handle);
    
    #if BTM_SEC_FORCE_RNR_FOR_DBOND == TRUE
        p_dev_rec->sec_flags &= ~BTM_SEC_NAME_KNOWN;
    #endif
    
        /* If connection already exists... */
        if (p && p->hci_handle != BTM_SEC_INVALID_HANDLE)
        {
            if (!btm_sec_start_authentication (p_dev_rec))
                return(BTM_NO_RESOURCES);
    
            btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
    
            /* Mark lcb as bonding */
            l2cu_update_lcb_4_bonding (bd_addr, TRUE);
            return(BTM_CMD_STARTED);
        }
    
        BTM_TRACE_DEBUG ("sec mode: %d sm4:x%x", btm_cb.security_mode, p_dev_rec->sm4);
        if (!controller_get_interface()->supports_simple_pairing()
            || (p_dev_rec->sm4 == BTM_SM4_KNOWN))
        {
            if ( btm_sec_check_prefetch_pin (p_dev_rec) )
                return (BTM_CMD_STARTED);
        }
        if ((btm_cb.security_mode == BTM_SEC_MODE_SP ||
             btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG ||
             btm_cb.security_mode == BTM_SEC_MODE_SC) &&
             BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4))
        {
            /* local is 2.1 and peer is unknown */
            if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0)
            {
                /* we are not accepting connection request from peer
                 * -> RNR (to learn if peer is 2.1)
                 * RNR when no ACL causes HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT */
                btm_sec_change_pairing_state (BTM_PAIR_STATE_GET_REM_NAME);
                BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
            }
            else
            {
                /* We are accepting connection request from peer */
                btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
            }
            BTM_TRACE_DEBUG ("State:%s sm4: 0x%x sec_state:%d",
                btm_pair_state_descr (btm_cb.pairing_state), p_dev_rec->sm4, p_dev_rec->sec_state);
            return BTM_CMD_STARTED;
        }
    
        /* both local and peer are 2.1  */
        status = btm_sec_dd_create_conn(p_dev_rec);
    
        if (status != BTM_CMD_STARTED)
        {
            btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
        }
    
        return status;
    }
    
    • 从btm_sec_dd_create_conn函数继续后续分析;
    static tBTM_STATUS btm_sec_dd_create_conn (tBTM_SEC_DEV_REC *p_dev_rec)
    {
        tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
        if (p_lcb && (p_lcb->link_state == LST_CONNECTED || p_lcb->link_state == LST_CONNECTING))
        {
           BTM_TRACE_WARNING("%s Connection already exists", __func__);
           return BTM_CMD_STARTED;
        }
    
        /* Make sure an L2cap link control block is available */
        if (!p_lcb && (p_lcb = l2cu_allocate_lcb (p_dev_rec->bd_addr, TRUE, BT_TRANSPORT_BR_EDR)) == NULL)
        {
            BTM_TRACE_WARNING ("Security Manager: failed allocate LCB [%02x%02x%02x%02x%02x%02x]",
                                p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
                                p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
    
            return(BTM_NO_RESOURCES);
        }
    
        /* set up the control block to indicated dedicated bonding */
        btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
    
        if (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE)
        {
            BTM_TRACE_WARNING ("Security Manager: failed create  [%02x%02x%02x%02x%02x%02x]",
                                p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
                                p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
    
            l2cu_release_lcb(p_lcb);
            return(BTM_NO_RESOURCES);
        }
    
        btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
    
        BTM_TRACE_DEBUG ("Security Manager: btm_sec_dd_create_conn [%02x%02x%02x%02x%02x%02x]",
                          p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2],
                          p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]);
    
        btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_PIN_REQ);
    
        return(BTM_CMD_STARTED);
    }
    
    
    • 调用l2cu_create_conn函数发送HCI指令给Controller;
    BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
    {
        int             xx;
        tL2C_LCB        *p_lcb_cur = &l2cb.lcb_pool[0];
    #if BTM_SCO_INCLUDED == TRUE
        BOOLEAN         is_sco_active;
    #endif
    
    #if (BLE_INCLUDED == TRUE)
        tBT_DEVICE_TYPE     dev_type;
        tBLE_ADDR_TYPE      addr_type;
    
    
        BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
    
        if (transport == BT_TRANSPORT_LE)
        {
            if (!controller_get_interface()->supports_ble())
                return FALSE;
    
            p_lcb->ble_addr_type = addr_type;
            p_lcb->transport = BT_TRANSPORT_LE;
    
            return (l2cble_create_conn(p_lcb));
        }
    #endif
    
        /* If there is a connection where we perform as a slave, try to switch roles
           for this connection */
        for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++)
        {
            if (p_lcb_cur == p_lcb)
                continue;
    
            if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE))
            {
    
    #if BTM_SCO_INCLUDED == TRUE
                /* The LMP_switch_req shall be sent only if the ACL logical transport
                is in active mode, when encryption is disabled, and all synchronous
                logical transports on the same physical link are disabled." */
    
                /* Check if there is any SCO Active on this BD Address */
                is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
    
                L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
                    (is_sco_active == TRUE) ? "TRUE":"FALSE");
    
                if (is_sco_active == TRUE)
                    continue; /* No Master Slave switch not allowed when SCO Active */
    #endif
                /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
                if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures()))
                {
                    /* mark this lcb waiting for switch to be completed and
                       start switch on the other one */
                    p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
                    p_lcb->link_role  = HCI_ROLE_MASTER;
    
                    if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED)
                    {
                        alarm_set_on_queue(p_lcb->l2c_lcb_timer,
                                           L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS,
                                           l2c_lcb_timer_timeout, p_lcb,
                                           btu_general_alarm_queue);
                        return (TRUE);
                    }
                }
            }
        }
    
        p_lcb->link_state = LST_CONNECTING;
    
        return (l2cu_create_conn_after_switch (p_lcb));
    }
    
    
    • 至此Host端的操作流程告一段落,Controller根据HCI指令进行后续的操作,这部分是由蓝牙芯片提供商来设计的,我们在此不做介绍。

    • 总结
      该篇文章挑选了蓝牙API操作中的createBond进行了详细分析,旨在给读者提供一个分析Android Bluetooth 调用流程的一个思路,也算是抛砖引玉。
      其中涉及到AIDL、binder、JNI等相关知识,读者如果有欠缺,可自行学习。
      当上层下发的操作被stack正常执行后,stack后返回一个相应的回调给上层,至于这个callback,上层是如何正常接收到的,读者可以沿着上文提到的思路倒推回去,也顺便检测一下自己的代码分析能力。

    相关文章

      网友评论

        本文标题:A: How to do the createBond oper

        本文链接:https://www.haomeiwen.com/subject/ceazsxtx.html