• Android 12 Bluetooth源码分析蓝牙配对


    本文主要是列出一些蓝牙配对重要的类和方法/函数,遇到相关问题时方便查找添加log排查。

    蓝牙扫描列表页面:packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java点击其中一个设备会调用:onPreferenceTreeClick()

    1. @Override
    2. public boolean onPreferenceTreeClick(Preference preference) {
    3. if (KEY_BT_SCAN.equals(preference.getKey())) {
    4. startScanning();
    5. return true;
    6. }
    7. if (preference instanceof BluetoothDevicePreference) {
    8. BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
    9. CachedBluetoothDevice device = btPreference.getCachedDevice();
    10. mSelectedDevice = device.getDevice();
    11. mSelectedList.add(mSelectedDevice);
    12. //配对
    13. onDevicePreferenceClick(btPreference);
    14. return true;
    15. }
    16. return super.onPreferenceTreeClick(preference);
    17. }

    接着调用 packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java

    1. void onClicked() {
    2. Context context = getContext();
    3. int bondState = mCachedDevice.getBondState();
    4. final MetricsFeatureProvider metricsFeatureProvider =
    5. FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    6. if (mCachedDevice.isConnected()) {
    7. metricsFeatureProvider.action(context,
    8. SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
    9. askDisconnect();
    10. } else if (bondState == BluetoothDevice.BOND_BONDED) {
    11. metricsFeatureProvider.action(context,
    12. SettingsEnums.ACTION_SETTINGS_BLUETOOTH_CONNECT);
    13. mCachedDevice.connect();
    14. } else if (bondState == BluetoothDevice.BOND_NONE) {
    15. metricsFeatureProvider.action(context,
    16. SettingsEnums.ACTION_SETTINGS_BLUETOOTH_PAIR);
    17. if (!mCachedDevice.hasHumanReadableName()) {
    18. metricsFeatureProvider.action(context,
    19. SettingsEnums.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
    20. }
    21. pair();//配对
    22. }
    23. }

    继续调用

    1. public boolean startPairing() {
    2. // Pairing is unreliable while scanning, so cancel discovery
    3. if (mLocalAdapter.isDiscovering()) {
    4. mLocalAdapter.cancelDiscovery();
    5. }
    6. //创建配对
    7. if (!mDevice.createBond()) {
    8. return false;
    9. }
    10. return true;
    11. }

    一直往下会到BluetoothDevice.java,在里面调用了IBuletooth.aidl

    frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
    1. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    2. private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
    3. @Nullable OobData remoteP256Data) {
    4. final IBluetooth service = sService;
    5. if (service == null) {
    6. Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
    7. return false;
    8. }
    9. try {
    10. return service.createBond(
    11. this, transport, remoteP192Data, remoteP256Data, mAttributionSource);
    12. } catch (RemoteException e) {
    13. Log.e(TAG, "", e);
    14. }
    15. return false;
    16. }

    在AdapterService.java里实现了IBluetooth.Stub

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

    1. @VisibleForTesting
    2. public static class AdapterServiceBinder extends IBluetooth.Stub {
    3. private AdapterService mService;
    4. AdapterServiceBinder(AdapterService svc) {
    5. mService = svc;
    6. mService.invalidateBluetoothGetStateCache();
    7. BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache();
    8. }
    9. .....省略
    10. @Override
    11. public boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
    12. OobData remoteP256Data, AttributionSource attributionSource) {
    13. Attributable.setAttributionSource(device, attributionSource);
    14. AdapterService service = getService();
    15. if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
    16. || !Utils.checkConnectPermissionForDataDelivery(
    17. service, attributionSource, "AdapterService createBond")) {
    18. return false;
    19. }
    20. // This conditional is required to satisfy permission dependencies
    21. // since createBond calls createBondOutOfBand with null value passed as data.
    22. // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only.
    23. service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data);
    24. //进入createBond
    25. return service.createBond(device, transport, remoteP192Data, remoteP256Data,
    26. attributionSource.getPackageName());
    27. }
    28. }
    1. boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
    2. OobData remoteP256Data, String callingPackage) {
    3. DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
    4. if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
    5. return false;
    6. }
    7. if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) {
    8. return false;
    9. }
    10. CallerInfo createBondCaller = new CallerInfo();
    11. createBondCaller.callerPackageName = callingPackage;
    12. createBondCaller.user = UserHandle.of(UserHandle.getCallingUserId());
    13. mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller);
    14. mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
    15. // Pairing is unreliable while scanning, so cancel discovery
    16. // Note, remove this when native stack improves
    17. cancelDiscoveryNative();
    18. Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
    19. msg.obj = device;
    20. msg.arg1 = transport;
    21. Bundle remoteOobDatasBundle = new Bundle();
    22. boolean setData = false;
    23. if (remoteP192Data != null) {
    24. remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data);
    25. setData = true;
    26. }
    27. if (remoteP256Data != null) {
    28. remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data);
    29. setData = true;
    30. }
    31. if (setData) {
    32. msg.setData(remoteOobDatasBundle);
    33. }
    34. //发送配对message
    35. mBondStateMachine.sendMessage(msg);
    36. return true;
    37. }

    接着进入packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java

    1. private boolean createBond(BluetoothDevice dev, int transport, OobData remoteP192Data,
    2. OobData remoteP256Data, boolean transition) {
    3. if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
    4. infoLog("Bond address is:" + dev);
    5. byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
    6. boolean result;
    7. // If we have some data
    8. if (remoteP192Data != null || remoteP256Data != null) {
    9. result = mAdapterService.createBondOutOfBandNative(addr, transport,
    10. remoteP192Data, remoteP256Data);
    11. } else {
    12. //调用了native的代码
    13. result = mAdapterService.createBondNative(addr, transport);
    14. }
    15. BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
    16. mAdapterService.obfuscateAddress(dev), transport, dev.getType(),
    17. BluetoothDevice.BOND_BONDING,
    18. remoteP192Data == null && remoteP256Data == null
    19. ? BluetoothProtoEnums.BOND_SUB_STATE_UNKNOWN
    20. : BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_OOB_DATA_PROVIDED,
    21. BluetoothProtoEnums.UNBOND_REASON_UNKNOWN);
    22. if (!result) {
    23. BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
    24. mAdapterService.obfuscateAddress(dev), transport, dev.getType(),
    25. BluetoothDevice.BOND_NONE, BluetoothProtoEnums.BOND_SUB_STATE_UNKNOWN,
    26. BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS);
    27. // Using UNBOND_REASON_REMOVED for legacy reason
    28. sendIntent(dev, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED);
    29. return false;
    30. } else if (transition) {
    31. transitionTo(mPendingCommandState);
    32. }
    33. return true;
    34. }
    35. return false;
    36. }

    这里调到了JNI层的代码,进入packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

    1. static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address,
    2. jint transport) {
    3. ALOGV("%s", __func__);
    4. if (!sBluetoothInterface) return JNI_FALSE;
    5. jbyte* addr = env->GetByteArrayElements(address, NULL);
    6. if (addr == NULL) {
    7. jniThrowIOException(env, EINVAL);
    8. return JNI_FALSE;
    9. }
    10. //调用hal层的配对函数
    11. int ret = sBluetoothInterface->create_bond((RawAddress*)addr, transport);
    12. env->ReleaseByteArrayElements(address, addr, 0);
    13. return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    14. }

    调用到了hal层的代码,在蓝牙协议栈里 system/bt/btif/src/bluetooth.cc

    1. static int create_bond(const RawAddress* bd_addr, int transport) {
    2. if (!interface_ready()) return BT_STATUS_NOT_READY;
    3. if (btif_dm_pairing_is_busy()) return BT_STATUS_BUSY;
    4. //调用了btif_dm_create_bond
    5. do_in_main_thread(FROM_HERE,
    6. base::BindOnce(btif_dm_create_bond, *bd_addr, transport));
    7. return BT_STATUS_SUCCESS;
    8. }

    调用到了system/bt/btif/src/btif_dm.cc

    1. /*******************************************************************************
    2. *
    3. * Function btif_dm_create_bond
    4. *
    5. * Description Initiate bonding with the specified device
    6. *
    7. ******************************************************************************/
    8. void btif_dm_create_bond(const RawAddress bd_addr, int transport) {
    9. BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
    10. bd_addr.ToString().c_str(), transport);
    11. btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CREATE_BOND,
    12. pairing_cb.state);
    13. pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
    14. btif_dm_cb_create_bond(bd_addr, transport);
    15. }
    1. static void btif_dm_cb_create_bond(const RawAddress bd_addr,
    2. tBT_TRANSPORT transport) {
    3. bool is_hid = check_cod(&bd_addr, COD_HID_POINTING);
    4. bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
    5. int device_type = 0;
    6. tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
    7. std::string addrstr = bd_addr.ToString();
    8. const char* bdstr = addrstr.c_str();
    9. if (transport == BT_TRANSPORT_LE) {
    10. if (!btif_config_get_int(bdstr, "DevType", &device_type)) {
    11. btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
    12. }
    13. if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) !=
    14. BT_STATUS_SUCCESS) {
    15. // Try to read address type. OOB pairing might have set it earlier, but
    16. // didn't store it, it defaults to BLE_ADDR_PUBLIC
    17. uint8_t tmp_dev_type;
    18. tBLE_ADDR_TYPE tmp_addr_type = BLE_ADDR_PUBLIC;
    19. BTM_ReadDevInfo(bd_addr, &tmp_dev_type, &tmp_addr_type);
    20. addr_type = tmp_addr_type;
    21. btif_storage_set_remote_addr_type(&bd_addr, addr_type);
    22. }
    23. }
    24. if ((btif_config_get_int(bdstr, "DevType", &device_type) &&
    25. (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) ==
    26. BT_STATUS_SUCCESS) &&
    27. (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) ||
    28. (transport == BT_TRANSPORT_LE)) {
    29. BTA_DmAddBleDevice(bd_addr, addr_type, device_type);
    30. }
    31. if (is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0) {
    32. bt_status_t status;
    33. status = (bt_status_t)btif_hh_connect(&bd_addr);
    34. if (status != BT_STATUS_SUCCESS)
    35. bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
    36. } else {
    37. //执行到这个方法
    38. BTA_DmBond(bd_addr, addr_type, transport, device_type);
    39. }
    40. /* Track originator of bond creation */
    41. pairing_cb.is_local_initiated = true;
    42. }

    这个函数BTA_DmBond里调用到了system/bt/bta/dm/bta_dm_act.cc

    1. /** Bonds with peer device */
    2. void bta_dm_bond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
    3. tBT_TRANSPORT transport, int device_type) {
    4. tBTA_DM_SEC sec_event;
    5. char* p_name;
    6. //在BTM_SecBond函数发送配对信息,蓝牙地址、数据、命令等信息
    7. tBTM_STATUS status =
    8. (bluetooth::shim::is_gd_security_enabled())
    9. ? bluetooth::shim::BTM_SecBond(bd_addr, addr_type, transport,
    10. device_type)
    11. : BTM_SecBond(bd_addr, addr_type, transport, device_type, 0, NULL);
    12. if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED)) {
    13. memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
    14. sec_event.auth_cmpl.bd_addr = bd_addr;
    15. p_name = (bluetooth::shim::is_gd_security_enabled())
    16. ? bluetooth::shim::BTM_SecReadDevName(bd_addr)
    17. : BTM_SecReadDevName(bd_addr);
    18. if (p_name != NULL) {
    19. memcpy(sec_event.auth_cmpl.bd_name, p_name, BD_NAME_LEN);
    20. sec_event.auth_cmpl.bd_name[BD_NAME_LEN] = 0;
    21. }
    22. /* taken care of by memset [above]
    23. sec_event.auth_cmpl.key_present = false;
    24. sec_event.auth_cmpl.success = false;
    25. */
    26. sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
    27. if (status == BTM_SUCCESS) {
    28. sec_event.auth_cmpl.success = true;
    29. } else {
    30. /* delete this device entry from Sec Dev DB */
    31. bta_dm_remove_sec_dev_entry(bd_addr);
    32. }
    33. bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
    34. }
    35. }

    来到system/bt/stack/btm/btm_sec.cc,最终在这里发送命令给HCI与硬件打交道

    1. /*******************************************************************************
    2. *
    3. * Function BTM_SecBond
    4. *
    5. * Description This function is called to perform bonding with peer device.
    6. * If the connection is already up, but not secure, pairing
    7. * is attempted. If already paired BTM_SUCCESS is returned.
    8. *
    9. * Parameters: bd_addr - Address of the device to bond
    10. * transport - doing SSP over BR/EDR or SMP over LE
    11. * pin_len - length in bytes of the PIN Code
    12. * p_pin - pointer to array with the PIN Code
    13. *
    14. * Note: After 2.1 parameters are not used and preserved here not to change API
    15. ******************************************************************************/
    16. tBTM_STATUS BTM_SecBond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
    17. tBT_TRANSPORT transport, int device_type,
    18. uint8_t pin_len, uint8_t* p_pin) {
    19. if (bluetooth::shim::is_gd_shim_enabled()) {
    20. return bluetooth::shim::BTM_SecBond(bd_addr, addr_type, transport,
    21. device_type);
    22. }
    23. if (transport == BT_TRANSPORT_INVALID)
    24. transport = BTM_UseLeLink(bd_addr) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
    25. tBT_DEVICE_TYPE dev_type;
    26. BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
    27. /* LE device, do SMP pairing */
    28. if ((transport == BT_TRANSPORT_LE && (dev_type & BT_DEVICE_TYPE_BLE) == 0) ||
    29. (transport == BT_TRANSPORT_BR_EDR &&
    30. (dev_type & BT_DEVICE_TYPE_BREDR) == 0)) {
    31. return BTM_ILLEGAL_ACTION;
    32. }
    33. //执行btm_sec_bond_by_transport函数
    34. return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin);
    35. }
    36. /*******************************************************************************
    37. *
    38. * Function btm_sec_bond_by_transport
    39. *
    40. * Description this is the bond function that will start either SSP or SMP.
    41. *
    42. * Parameters: bd_addr - Address of the device to bond
    43. * pin_len - length in bytes of the PIN Code
    44. * p_pin - pointer to array with the PIN Code
    45. *
    46. * Note: After 2.1 parameters are not used and preserved here not to change API
    47. ******************************************************************************/
    48. tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
    49. tBT_TRANSPORT transport, uint8_t pin_len,
    50. uint8_t* p_pin) {
    51. //....代码太多,最底层就是发送控制命令
    52. if (!controller_get_interface()->supports_simple_pairing()) {
    53. /* The special case when we authenticate keyboard. Set pin type to fixed */
    54. /* It would be probably better to do it from the application, but it is */
    55. /* complicated */
    56. if (((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) ==
    57. BTM_COD_MAJOR_PERIPHERAL) &&
    58. (p_dev_rec->dev_class[2] & BTM_COD_MINOR_KEYBOARD) &&
    59. (btm_cb.cfg.pin_type != HCI_PIN_TYPE_FIXED)) {
    60. btm_cb.pin_type_changed = true;
    61. //通过HCI向底层发送命令
    62. btsnd_hcic_write_pin_type(HCI_PIN_TYPE_FIXED);
    63. }
    64. }
    65. return status;
    66. }

    到这里就结束了,后面就是控制硬件发起配对操作。

  • 相关阅读:
    Elasticsearch和sboot整合
    插入排序算法
    Avalonia踩坑
    Java判断字符串是否是有效的括号
    QDockWidget重新实现的事件处理
    流式结构化数据计算语言的进化与新选择
    一种优雅的Git分支实践
    NR CSI(三) CQI
    Spring Security 实战 01 Security核心功能解析
    CrystalNet ADO.Net VCL for Delphi
  • 原文地址:https://blog.csdn.net/gxhea/article/details/133171386