本文主要是列出一些蓝牙配对重要的类和方法/函数,遇到相关问题时方便查找添加log排查。
蓝牙扫描列表页面:packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java点击其中一个设备会调用:onPreferenceTreeClick()
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- if (KEY_BT_SCAN.equals(preference.getKey())) {
- startScanning();
- return true;
- }
-
- if (preference instanceof BluetoothDevicePreference) {
- BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
- CachedBluetoothDevice device = btPreference.getCachedDevice();
- mSelectedDevice = device.getDevice();
- mSelectedList.add(mSelectedDevice);
- //配对
- onDevicePreferenceClick(btPreference);
- return true;
- }
-
- return super.onPreferenceTreeClick(preference);
- }
接着调用 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,
- SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
- askDisconnect();
- } else if (bondState == BluetoothDevice.BOND_BONDED) {
- metricsFeatureProvider.action(context,
- SettingsEnums.ACTION_SETTINGS_BLUETOOTH_CONNECT);
- mCachedDevice.connect();
- } else if (bondState == BluetoothDevice.BOND_NONE) {
- metricsFeatureProvider.action(context,
- SettingsEnums.ACTION_SETTINGS_BLUETOOTH_PAIR);
- if (!mCachedDevice.hasHumanReadableName()) {
- metricsFeatureProvider.action(context,
- SettingsEnums.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
- }
- pair();//配对
- }
- }
继续调用
- public boolean startPairing() {
- // Pairing is unreliable while scanning, so cancel discovery
- if (mLocalAdapter.isDiscovering()) {
- mLocalAdapter.cancelDiscovery();
- }
- //创建配对
- if (!mDevice.createBond()) {
- return false;
- }
-
- return true;
- }
一直往下会到BluetoothDevice.java,在里面调用了IBuletooth.aidl
frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
- @Nullable OobData remoteP256Data) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
- return false;
- }
- try {
- return service.createBond(
- this, transport, remoteP192Data, remoteP256Data, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
在AdapterService.java里实现了IBluetooth.Stub
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
- @VisibleForTesting
- public static class AdapterServiceBinder extends IBluetooth.Stub {
- private AdapterService mService;
-
- AdapterServiceBinder(AdapterService svc) {
- mService = svc;
- mService.invalidateBluetoothGetStateCache();
- BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache();
- }
- .....省略
-
-
- @Override
- public boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
- OobData remoteP256Data, AttributionSource attributionSource) {
- Attributable.setAttributionSource(device, attributionSource);
- AdapterService service = getService();
- if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, attributionSource, "AdapterService createBond")) {
- return false;
- }
-
- // This conditional is required to satisfy permission dependencies
- // since createBond calls createBondOutOfBand with null value passed as data.
- // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only.
- service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data);
- //进入createBond
- return service.createBond(device, transport, remoteP192Data, remoteP256Data,
- attributionSource.getPackageName());
- }
- }
- boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
- OobData remoteP256Data, String callingPackage) {
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
- return false;
- }
-
- if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) {
- return false;
- }
-
- CallerInfo createBondCaller = new CallerInfo();
- createBondCaller.callerPackageName = callingPackage;
- createBondCaller.user = UserHandle.of(UserHandle.getCallingUserId());
- mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller);
-
- 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;
-
- Bundle remoteOobDatasBundle = new Bundle();
- boolean setData = false;
- if (remoteP192Data != null) {
- remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data);
- setData = true;
- }
- if (remoteP256Data != null) {
- remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data);
- setData = true;
- }
- if (setData) {
- msg.setData(remoteOobDatasBundle);
- }
- //发送配对message
- mBondStateMachine.sendMessage(msg);
- return true;
- }
接着进入packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java
- private boolean createBond(BluetoothDevice dev, int transport, OobData remoteP192Data,
- OobData remoteP256Data, boolean transition) {
- if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
- infoLog("Bond address is:" + dev);
- byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
- boolean result;
- // If we have some data
- if (remoteP192Data != null || remoteP256Data != null) {
- result = mAdapterService.createBondOutOfBandNative(addr, transport,
- remoteP192Data, remoteP256Data);
- } else {
- //调用了native的代码
- result = mAdapterService.createBondNative(addr, transport);
- }
- BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
- mAdapterService.obfuscateAddress(dev), transport, dev.getType(),
- BluetoothDevice.BOND_BONDING,
- remoteP192Data == null && remoteP256Data == null
- ? BluetoothProtoEnums.BOND_SUB_STATE_UNKNOWN
- : BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_OOB_DATA_PROVIDED,
- BluetoothProtoEnums.UNBOND_REASON_UNKNOWN);
-
- if (!result) {
- BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
- mAdapterService.obfuscateAddress(dev), transport, dev.getType(),
- BluetoothDevice.BOND_NONE, BluetoothProtoEnums.BOND_SUB_STATE_UNKNOWN,
- BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS);
- // Using UNBOND_REASON_REMOVED for legacy reason
- sendIntent(dev, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED);
- return false;
- } else if (transition) {
- transitionTo(mPendingCommandState);
- }
- return true;
- }
- return false;
- }
这里调到了JNI层的代码,进入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;
- }
- //调用hal层的配对函数
- int ret = sBluetoothInterface->create_bond((RawAddress*)addr, transport);
- env->ReleaseByteArrayElements(address, addr, 0);
- return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
- }
调用到了hal层的代码,在蓝牙协议栈里 system/bt/btif/src/bluetooth.cc
- static int create_bond(const RawAddress* bd_addr, int transport) {
- if (!interface_ready()) return BT_STATUS_NOT_READY;
- if (btif_dm_pairing_is_busy()) return BT_STATUS_BUSY;
-
- //调用了btif_dm_create_bond
- do_in_main_thread(FROM_HERE,
- base::BindOnce(btif_dm_create_bond, *bd_addr, transport));
- return BT_STATUS_SUCCESS;
- }
调用到了system/bt/btif/src/btif_dm.cc
- /*******************************************************************************
- *
- * Function btif_dm_create_bond
- *
- * Description Initiate bonding with the specified device
- *
- ******************************************************************************/
- void btif_dm_create_bond(const RawAddress bd_addr, int transport) {
- BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
- bd_addr.ToString().c_str(), transport);
- btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_CREATE_BOND,
- pairing_cb.state);
-
- pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
- btif_dm_cb_create_bond(bd_addr, transport);
- }
- static void btif_dm_cb_create_bond(const RawAddress bd_addr,
- tBT_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 = 0;
- tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
- 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;
- tBLE_ADDR_TYPE tmp_addr_type = BLE_ADDR_PUBLIC;
- 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_DmBond(bd_addr, addr_type, transport, device_type);
- }
- /* Track originator of bond creation */
- pairing_cb.is_local_initiated = true;
- }
这个函数BTA_DmBond里调用到了system/bt/bta/dm/bta_dm_act.cc
- /** Bonds with peer device */
- void bta_dm_bond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
- tBT_TRANSPORT transport, int device_type) {
- tBTA_DM_SEC sec_event;
- char* p_name;
-
- //在BTM_SecBond函数发送配对信息,蓝牙地址、数据、命令等信息
- tBTM_STATUS status =
- (bluetooth::shim::is_gd_security_enabled())
- ? bluetooth::shim::BTM_SecBond(bd_addr, addr_type, transport,
- device_type)
- : BTM_SecBond(bd_addr, addr_type, transport, device_type, 0, NULL);
-
- 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 = (bluetooth::shim::is_gd_security_enabled())
- ? bluetooth::shim::BTM_SecReadDevName(bd_addr)
- : BTM_SecReadDevName(bd_addr);
- if (p_name != NULL) {
- memcpy(sec_event.auth_cmpl.bd_name, p_name, BD_NAME_LEN);
- sec_event.auth_cmpl.bd_name[BD_NAME_LEN] = 0;
- }
-
- /* taken care of by memset [above]
- sec_event.auth_cmpl.key_present = false;
- sec_event.auth_cmpl.success = false;
- */
- sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
- if (status == BTM_SUCCESS) {
- sec_event.auth_cmpl.success = true;
- } else {
- /* delete this device entry from Sec Dev DB */
- 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,最终在这里发送命令给HCI与硬件打交道
- /*******************************************************************************
- *
- * Function BTM_SecBond
- *
- * Description This function is called to perform bonding with peer device.
- * If the connection is already up, but not secure, pairing
- * is attempted. If already paired BTM_SUCCESS is returned.
- *
- * Parameters: bd_addr - Address of the device to bond
- * transport - doing SSP over BR/EDR or SMP over LE
- * pin_len - length in bytes of the PIN Code
- * p_pin - pointer to array with the PIN Code
- *
- * Note: After 2.1 parameters are not used and preserved here not to change API
- ******************************************************************************/
- tBTM_STATUS BTM_SecBond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
- tBT_TRANSPORT transport, int device_type,
- uint8_t pin_len, uint8_t* p_pin) {
- if (bluetooth::shim::is_gd_shim_enabled()) {
- return bluetooth::shim::BTM_SecBond(bd_addr, addr_type, transport,
- device_type);
- }
-
- if (transport == BT_TRANSPORT_INVALID)
- transport = BTM_UseLeLink(bd_addr) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
-
- tBT_DEVICE_TYPE dev_type;
-
- BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
- /* LE device, do SMP pairing */
- 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;
- }
- //执行btm_sec_bond_by_transport函数
- return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin);
- }
-
-
- /*******************************************************************************
- *
- * Function btm_sec_bond_by_transport
- *
- * Description this is the bond function that will start either SSP or SMP.
- *
- * Parameters: bd_addr - Address of the device to bond
- * pin_len - length in bytes of the PIN Code
- * p_pin - pointer to array with the PIN Code
- *
- * Note: After 2.1 parameters are not used and preserved here not to change API
- ******************************************************************************/
- tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
- tBT_TRANSPORT transport, uint8_t pin_len,
- uint8_t* p_pin) {
-
- //....代码太多,最底层就是发送控制命令
-
- 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;
-
- //通过HCI向底层发送命令
- btsnd_hcic_write_pin_type(HCI_PIN_TYPE_FIXED);
- }
- }
- return status;
- }
到这里就结束了,后面就是控制硬件发起配对操作。