文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android 9.0 蓝牙配对流程

2022-06-06 14:08

关注

1 、UI

DeviceListPreferenceFragment是蓝牙扫描到的设备列表,点击其中一个蓝牙设备,调用onPreferenceTreeClick方法开始蓝牙的配对过程。

/packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java

public boolean onPreferenceTreeClick(Preference preference) {
    if (KEY_BT_SCAN.equals(preference.getKey())) {
        mLocalAdapter.startScanning(true);
        return true;
    }
    if (preference instanceof BluetoothDevicePreference) {
        BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
        CachedBluetoothDevice device = btPreference.getCachedDevice();
        mSelectedDevice = device.getDevice();
        onDevicePreferenceClick(btPreference);
        return true;
    }
    return super.onPreferenceTreeClick(preference);
}
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
    btPreference.onClicked();
}

/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java

void onClicked() {
    Context context = getContext();
    int bondState = mCachedDevice.getBondState();
    final MetricsFeatureProvider metricsFeatureProvider =
            FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    if (mCachedDevice.isConnected()) {
        metricsFeatureProvider.action(context,
                MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
        askDisconnect();
    } else if (bondState == BluetoothDevice.BOND_BONDED) {
        metricsFeatureProvider.action(context,
                MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT);
        mCachedDevice.connect(true);
    } else if (bondState == BluetoothDevice.BOND_NONE) {
        metricsFeatureProvider.action(context,
                MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
        if (!mCachedDevice.hasHumanReadableName()) {
            metricsFeatureProvider.action(context,
                    MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
        }
        pair();
    }
}

这里先获取mCachedDevice的绑定状态,如果已经连接,则询问是否断开;如果已经绑定未连接,则开始连接;如果未连接也未绑定,则开始配对。这里我们先看配对。配对调用的是本地的pair方法:

private void pair() {
    if (!mCachedDevice.startPairing()) {
        Utils.showError(getContext(), mCachedDevice.getName(),
                R.string.bluetooth_pairing_error_message);
    }
}
2 、framework

/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java

public boolean startPairing() {
    // Pairing is unreliable while scanning, so cancel discovery
    if (mLocalAdapter.isDiscovering()) {
        mLocalAdapter.cancelDiscovery();
    }
    if (!mDevice.createBond()) {
        return false;
    }
    return true;
}

/frameworks/base/core/java/android/bluetooth/BluetoothDevice.java

public boolean createBond() {
    final IBluetooth service = sService;
    if (service == 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 service.createBond(this, TRANSPORT_AUTO);
    } catch (RemoteException e) {
        Log.e(TAG, "", e);
    }
    return false;
}
3 、Bluetooth app

和蓝牙扫描一样,实现IBluetooth接口的类是AdapterServiceBinder,AdapterServiceBinder实现IBluetooth.Stub接口,是AdapterService的私有内部类,AdapterServiceBinder收到的操作,都会转交AdapterService处理,所以会调用AdapterService的createBond方法。

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

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;
    }
    mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
    // 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;
}

createBond 方法会检查一下远程设备属性信息,取消蓝牙扫描任务,将配对任务转交mBondStateMachine,由状态机处理该信息。

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java

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);
        }
        if (!result) {
            sendIntent(dev, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED);
            return false;
        } else if (transition) {
            transitionTo(mPendingCommandState);
        }
        return true;
    }
    return false;
}

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

native boolean createBondNative(byte[] address, int transport);

/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address,
                                 jint transport) {
  ALOGV("%s", __func__);
  if (!sBluetoothInterface) return JNI_FALSE;
  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (addr == NULL) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }
  int ret = sBluetoothInterface->create_bond((RawAddress*)addr, transport);
  env->ReleaseByteArrayElements(address, addr, 0);
  return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
4 、蓝牙协议栈

/system/bt/btif/src/bluetooth.cc

static int create_bond(const RawAddress* bd_addr, int transport) {
  
  if (!interface_ready()) return BT_STATUS_NOT_READY;
  return btif_dm_create_bond(bd_addr, transport);
}

/system/bt/btif/src/btif_dm.cc

bt_status_t btif_dm_create_bond(const RawAddress* bd_addr, int transport) {
  btif_dm_create_bond_cb_t create_bond_cb;
  create_bond_cb.transport = transport;
  create_bond_cb.bdaddr = *bd_addr;
  BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
                   bd_addr->ToString().c_str(), 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;
}
static void btif_dm_generic_evt(uint16_t event, char* p_param) {
  BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
  switch (event) {
    case BTIF_DM_CB_DISCOVERY_STARTED: {
      HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                BT_DISCOVERY_STARTED);
    } break;
    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;
    case BTIF_DM_CB_REMOVE_BOND: {
      btif_dm_cb_remove_bond((RawAddress*)p_param);
    } break;
    case BTIF_DM_CB_HID_REMOTE_NAME: {
      btif_dm_cb_hid_remote_name((tBTM_REMOTE_DEV_NAME*)p_param);
    } break;
    case BTIF_DM_CB_BOND_STATE_BONDING: {
      bond_state_changed(BT_STATUS_SUCCESS, *((RawAddress*)p_param),
                         BT_BOND_STATE_BONDING);
    } break;
    case BTIF_DM_CB_LE_TX_TEST:
    case BTIF_DM_CB_LE_RX_TEST: {
      uint8_t status;
      STREAM_TO_UINT8(status, p_param);
      HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
                (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
    } break;
    case BTIF_DM_CB_LE_TEST_END: {
      uint8_t status;
      uint16_t count = 0;
      STREAM_TO_UINT8(status, p_param);
      if (status == 0) STREAM_TO_UINT16(count, p_param);
      HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
                (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
    } break;
    default: {
      BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
    } break;
  }
}
static void btif_dm_cb_create_bond(const RawAddress& bd_addr,
                                   tBTA_TRANSPORT transport) {
  bool is_hid = check_cod(&bd_addr, COD_HID_POINTING);
  bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
  int device_type;
  int addr_type;
  std::string addrstr = bd_addr.ToString();
  const char* bdstr = addrstr.c_str();
  if (transport == BT_TRANSPORT_LE) {
    if (!btif_config_get_int(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) {
      // Try to read address type. OOB pairing might have set it earlier, but
      // didn't store it, it defaults to BLE_ADDR_PUBLIC
      uint8_t tmp_dev_type;
      uint8_t tmp_addr_type;
      BTM_ReadDevInfo(bd_addr, &tmp_dev_type, &tmp_addr_type);
      addr_type = tmp_addr_type;
      btif_storage_set_remote_addr_type(&bd_addr, addr_type);
    }
  }
  if ((btif_config_get_int(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, addr_type, device_type);
  }
  if (is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0) {
    bt_status_t status;
    status = (bt_status_t)btif_hh_connect(&bd_addr);
    if (status != BT_STATUS_SUCCESS)
      bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
  } else {
    BTA_DmBondByTransport(bd_addr, transport);
  }
  
  pairing_cb.is_local_initiated = true;
}

/system/bt/bta/dm/bta_dm_api.cc

void BTA_DmBondByTransport(const RawAddress& bd_addr,
                           tBTA_TRANSPORT transport) {
  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_bond, bd_addr, transport));
}

/system/bt/bta/dm/bta_dm_act.cc

void bta_dm_bond(const RawAddress& bd_addr, tBTA_TRANSPORT transport) {
  tBTM_STATUS status;
  tBTA_DM_SEC sec_event;
  char* p_name;
  if (transport == BTA_TRANSPORT_UNKNOWN)
    status = BTM_SecBond(bd_addr, 0, NULL, 0);
  else
    status = BTM_SecBondByTransport(bd_addr, transport, 0, NULL, 0);
  if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED)) {
    memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
    sec_event.auth_cmpl.bd_addr = bd_addr;
    p_name = BTM_SecReadDevName(bd_addr);
    if (p_name != NULL) {
      memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN - 1));
      sec_event.auth_cmpl.bd_name[BD_NAME_LEN - 1] = 0;
    }
    
    sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
    if (status == BTM_SUCCESS) {
      sec_event.auth_cmpl.success = true;
    } else {
      
      bta_dm_remove_sec_dev_entry(bd_addr);
    }
    bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
  }
}

/system/bt/stack/btm/btm_sec.cc

tBTM_STATUS BTM_SecBondByTransport(const RawAddress& bd_addr,
                                   tBT_TRANSPORT transport, uint8_t pin_len,
                                   uint8_t* p_pin, uint32_t trusted_mask[]) {
  tBT_DEVICE_TYPE dev_type;
  tBLE_ADDR_TYPE addr_type;
  BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
  
  if ((transport == BT_TRANSPORT_LE && (dev_type & BT_DEVICE_TYPE_BLE) == 0) ||
      (transport == BT_TRANSPORT_BR_EDR &&
       (dev_type & BT_DEVICE_TYPE_BREDR) == 0)) {
    return BTM_ILLEGAL_ACTION;
  }
  return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin,
                                   trusted_mask);
}

/system/bt/stack/btm/btm_sec.cc

tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
                                      tBT_TRANSPORT transport, uint8_t pin_len,
                                      uint8_t* p_pin, uint32_t trusted_mask[]) {
  tBTM_SEC_DEV_REC* p_dev_rec;
  tBTM_STATUS status;
  uint8_t* p_features;
  uint8_t ii;
  tACL_CONN* p = btm_bda_to_acl(bd_addr, transport);
  VLOG(1) << __func__ << " BDA: " <get_is_ready()) {
    BTM_TRACE_ERROR("%s controller module is not ready", __func__);
    return (BTM_NO_RESOURCES);
  }
  BTM_TRACE_DEBUG("before update sec_flags=0x%x", p_dev_rec->sec_flags);
  
  if (((p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE) &&
       transport == BT_TRANSPORT_BR_EDR &&
       (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) ||
      ((p_dev_rec->ble_hci_handle != BTM_SEC_INVALID_HANDLE) &&
       transport == BT_TRANSPORT_LE &&
       (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED))) {
    BTM_TRACE_WARNING("BTM_SecBond -> Already Paired");
    return (BTM_SUCCESS);
  }
  
  if ((BTM_DeleteStoredLinkKey(&bd_addr, NULL)) != BTM_SUCCESS)
    return (BTM_NO_RESOURCES);
  
  if (p_pin && (pin_len pin_code_length = pin_len;
    memcpy(btm_cb.pin_code, p_pin, PIN_CODE_LEN);
  }
  btm_cb.pairing_bda = bd_addr;
  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 (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);
  }
  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()) {
    
    
    
    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 feature_pages[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 (p && p->hci_handle != BTM_SEC_INVALID_HANDLE) {
    btm_sec_start_authentication(p_dev_rec);
    btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
    
    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)) {
    
    if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0) {
      
      btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
      status = BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
    } else {
      
      btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
      status = BTM_CMD_STARTED;
    }
    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);
  } else {
    
    status = btm_sec_dd_create_conn(p_dev_rec);
  }
  if (status != BTM_CMD_STARTED) {
    BTM_TRACE_ERROR(
        "%s BTM_ReadRemoteDeviceName or btm_sec_dd_create_conn error: 0x%x",
        __func__, (int)status);
    btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
  }
  return status;
}

/system/bt/stack/hcic/hcicmds.cc

void btsnd_hcic_write_pin_type(uint8_t type) {
  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
  uint8_t* pp = (uint8_t*)(p + 1);
  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1;
  p->offset = 0;
  UINT16_TO_STREAM(pp, HCI_WRITE_PIN_TYPE);
  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1);
  UINT8_TO_STREAM(pp, type);
  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
5、 配对状态改变的回传

我们在bta里面调用/system/bt/bta/dm/bta_dm_act.cc里面的bta_dm_bond方法,进行配对,这个方法最后会执行这个函数:
/system/bt/bta/dm/bta_dm_act.cc

bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);

这个就是bta的回调函数,回调事件是BTA_DM_AUTH_CMPL_EVT,根据这个事件标志,我们找到了 /system/bt/btif/src/btif_dm.cc里面的btif_dm_upstreams_evt方法,这个方法就是用于向上层回调消息的,相关代码是:
/system/bt/btif/src/btif_dm.cc

case BTA_DM_AUTH_CMPL_EVT:
  btif_dm_auth_cmpl_evt(&p_data->auth_cmpl);
  break;

/system/bt/btif/src/btif_dm.cc

static void btif_dm_auth_cmpl_evt(tBTA_DM_AUTH_CMPL* p_auth_cmpl) {
  
  bt_status_t status = BT_STATUS_FAIL;
  bt_bond_state_t state = BT_BOND_STATE_NONE;
  bool skip_sdp = false;
  BTIF_TRACE_DEBUG("%s: bond state=%d, success=%d, key_present=%d", __func__,
                   pairing_cb.state, p_auth_cmpl->success,
                   p_auth_cmpl->key_present);
  RawAddress bd_addr = p_auth_cmpl->bd_addr;
  if ((p_auth_cmpl->success) && (p_auth_cmpl->key_present)) {
    if ((p_auth_cmpl->key_type key_type == HCI_LKEY_TYPE_AUTH_COMB) ||
        (p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) ||
        (p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB_P_256) ||
        pairing_cb.bond_type == BOND_TYPE_PERSISTENT) {
      bt_status_t ret;
      BTIF_TRACE_DEBUG("%s: Storing link key. key_type=0x%x, bond_type=%d",
                       __func__, p_auth_cmpl->key_type, pairing_cb.bond_type);
      ret = btif_storage_add_bonded_device(&bd_addr, p_auth_cmpl->key,
                                           p_auth_cmpl->key_type,
                                           pairing_cb.pin_code_len);
      ASSERTC(ret == BT_STATUS_SUCCESS, "storing link key failed", ret);
    } else {
      BTIF_TRACE_DEBUG(
          "%s: Temporary key. Not storing. key_type=0x%x, bond_type=%d",
          __func__, p_auth_cmpl->key_type, pairing_cb.bond_type);
      if (pairing_cb.bond_type == BOND_TYPE_TEMPORARY) {
        BTIF_TRACE_DEBUG("%s: sending BT_BOND_STATE_NONE for Temp pairing",
                         __func__);
        btif_storage_remove_bonded_device(&bd_addr);
        bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_NONE);
        return;
      }
    }
  }
    btif_storage_set_remote_addr_type(&bd_addr, p_auth_cmpl->addr_type);
    btif_update_remote_properties(p_auth_cmpl->bd_addr, p_auth_cmpl->bd_name,
                                  NULL, p_auth_cmpl->dev_type);
    pairing_cb.timeout_retries = 0;
    status = BT_STATUS_SUCCESS;
    state = BT_BOND_STATE_BONDED;
    bd_addr = p_auth_cmpl->bd_addr;
    if (check_sdp_bl(&bd_addr) && check_cod_hid(&bd_addr)) {
      LOG_WARN(LOG_TAG, "%s:skip SDP", __func__);
      skip_sdp = true;
    }
    if (!pairing_cb.is_local_initiated && skip_sdp) {
      bond_state_changed(status, bd_addr, state);
      LOG_WARN(LOG_TAG, "%s: Incoming HID Connection", __func__);
      bt_property_t prop;
      RawAddress bd_addr;
      Uuid uuid = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
      prop.type = BT_PROPERTY_UUIDS;
      prop.val = &uuid;
      prop.len = Uuid::kNumBytes128;
      
      HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS,
                &bd_addr, 1, &prop);
    } else {
      bool is_crosskey = false;
      
      if (pairing_cb.state == BT_BOND_STATE_BONDING &&
          p_auth_cmpl->bd_addr != pairing_cb.bd_addr) {
        BTIF_TRACE_DEBUG(
            "%s: bonding initiated due to cross key, adding static address",
            __func__);
        pairing_cb.static_bdaddr = bd_addr;
        is_crosskey = true;
      }
      if (!is_crosskey ||
          !(stack_config_get_interface()->get_pts_crosskey_sdp_disable())) {
        // Ensure inquiry is stopped before attempting service discovery
        btif_dm_cancel_discovery();
        
        pairing_cb.sdp_attempts = 1;
        btif_dm_get_remote_services(bd_addr);
      }
    }
    // Do not call bond_state_changed_cb yet. Wait until remote service
    // discovery is complete
  } else {
        break;
      default:
        status = BT_STATUS_FAIL;
    }
    
    if (check_cod(&bd_addr, COD_HID_POINTING)) {
      
      BTIF_TRACE_DEBUG("%s(): removing hid pointing device from nvram",
                       __func__);
      btif_storage_remove_bonded_device(&bd_addr);
    }
    bond_state_changed(status, bd_addr, state);
  }
}

可以发现也是通过HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);这样的方法进行回调的,bond_state_changed_cb这个函数在bluetooth.h被定义对应的是com_android_bluetooth_btservice_AdapterService.cpp里的bond_state_changed_callback,关键代码如下:
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

static void bond_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
                                        bt_bond_state_t state) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  if (!bd_addr) {
    ALOGE("Address is null in %s", __func__);
    return;
  }
  ScopedLocalRef addr(
      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
  if (!addr.get()) {
    ALOGE("Address allocation failed in %s", __func__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                   (jbyte*)bd_addr);
  sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback,
                               (jint)status, addr.get(), (jint)state);
}

这里将bondStateChangeCallback方法对应到jni的method_bondStateChangeCallback方法

static void classInitNative(JNIEnv* env, jclass clazz) {
  jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
  android_bluetooth_UidTraffic.constructor =
      env->GetMethodID(jniUidTrafficClass, "", "(IJJ)V");
  jclass jniCallbackClass =
      env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
  sJniCallbacksField = env->GetFieldID(
      clazz, "mJniCallbacks", "Lcom/android/bluetooth/btservice/JniCallbacks;");
  method_bondStateChangeCallback =
      env->GetMethodID(jniCallbackClass, "bondStateChangeCallback", "(I[BI)V");
  if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {
    ALOGE("No Bluetooth Library found");
  }
}

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/JniCallbacks.java

    void bondStateChangeCallback(int status, byte[] address, int newState) {
        mBondStateMachine.bondStateChangeCallback(status, address, newState);
    }

状态机里面通过sendMessage进行配对状态的变更。

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java

void bondStateChangeCallback(int status, byte[] address, int newState) {
    BluetoothDevice device = mRemoteDevices.getDevice(address);
    if (device == null) {
        infoLog("No record of the device:" + device);
        // This device will be added as part of the BONDING_STATE_CHANGE intent processing
        // in sendIntent above
        device = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
    }
    infoLog("bondStateChangeCallback: Status: " + status + " Address: " + device + " newState: "
            + newState);
    Message msg = obtainMessage(BONDING_STATE_CHANGE);
    msg.obj = device;
    if (newState == BOND_STATE_BONDED) {
        msg.arg1 = BluetoothDevice.BOND_BONDED;
    } else if (newState == BOND_STATE_BONDING) {
        msg.arg1 = BluetoothDevice.BOND_BONDING;
    } else {
        msg.arg1 = BluetoothDevice.BOND_NONE;
    }
    msg.arg2 = status;
    sendMessage(msg);
}

作者:二十岁了还没有去过星巴克


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯