Android13 BluetoothDevice createBond流程分析

BluetoothDevice的createBond方法用于与指定蓝牙设备进行配对,如下为BluetoothDevice的createBond代码:

//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothDevice.java
public final class BluetoothDevice implements Parcelable, Attributable {
    public boolean createBond() {
        return createBond(TRANSPORT_AUTO);
    }
}

调用重载方法:

//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothDevice.java
public final class BluetoothDevice implements Parcelable, Attributable {
    public boolean createBond(int transport) {
        return createBondInternal(transport, null, null);
    }
}

BluetoothDevice createBondInternal

调用createBondInternal方法:

//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothDevice.java
public final class BluetoothDevice implements Parcelable, Attributable {
    private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
            @Nullable OobData remoteP256Data) {
        if (DBG) log("createBondOutOfBand()");
        final IBluetooth service = sService;
        final boolean defaultValue = false;
        if (service == null || !isBluetoothEnabled()) {
            Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
        } else if (NULL_MAC_ADDRESS.equals(mAddress)) {
            Log.e(TAG, "Unable to create bond, invalid address " + mAddress);
        } else {
            try {
                final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
                service.createBond(this, transport, remoteP192Data, remoteP256Data,
                        mAttributionSource, recv);
                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
            } catch (RemoteException | TimeoutException e) {
                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            }
        }
        return defaultValue;
    }
}

调用IBluetooth的createBond方法,IBluetooth是一个接口,由AdapterService的内部类AdapterServiceBinder实现:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java
public class AdapterService extends Service {
    public static class AdapterServiceBinder extends IBluetooth.Stub {
        public void createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
                OobData remoteP256Data, AttributionSource source,
                SynchronousResultReceiver receiver) {
            try {
                receiver.send(createBond(device, transport, remoteP192Data, remoteP256Data,
                            source));
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }
    }
}

调用重载方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java
public class AdapterService extends Service {
    public static class AdapterServiceBinder extends IBluetooth.Stub {
        private boolean createBond(BluetoothDevice device, int transport, OobData remoteP192Data,
                OobData remoteP256Data, AttributionSource 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);


            return service.createBond(device, transport, remoteP192Data, remoteP256Data,
                    attributionSource.getPackageName());
        }
    }
}

AdapterService createBond

调用AdapterService的createBond方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java
public class AdapterService extends Service {
    private RemoteDevices mRemoteDevices;
    private BondStateMachine mBondStateMachine;
    private HashMap<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>();
    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 = Binder.getCallingUserHandle();
        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);
        }
        mBondStateMachine.sendMessage(msg);
        return true;
    }
}

调用BondStateMachine的sendMessage方法,发送CREATE_BOND消息,发送的消息会在BondStateMachine类的内部类StableState的processMessage中处理,这时由于在BondStateMachine的构造方法中调用setInitialState(mStableState);方法设置了默认状态:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
    private class StableState extends State {
        public synchronized boolean processMessage(Message msg) {
            switch (msg.what) {
                case CREATE_BOND:
                    OobData p192Data = (msg.getData() != null)
                            ? msg.getData().getParcelable(OOBDATAP192) : null;
                    OobData p256Data = (msg.getData() != null)
                            ? msg.getData().getParcelable(OOBDATAP256) : null;
                    createBond(dev, msg.arg1, p192Data, p256Data, true);
                    break;
            }
        }
    }
}

BondStateMachine createBond

调用createBond方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
    private AdapterService mAdapterService;
    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); //调用AdapterService的createBondOutOfBandNative方法
            } else {
                result = mAdapterService.createBondNative(addr, transport);  //调用AdapterService的createBondNative方法
            }
            BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED,
                    mAdapterService.getMetricId(dev), dev.getName());
            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,
                        false);
                return false;
            } else if (transition) {
                transitionTo(mPendingCommandState); //迁移到PendingCommandState状态
            }
            return true;
        }
        return false;
    }
}

调用AdapterService的createBondNative方法,createBondNative为Native方法,通过查表调用的是com_android_bluetooth_btservice_AdapterService.cpp的createBondNative方法:

static const bt_interface_t* sBluetoothInterface = NULL;
//packages/modules/Bluetooth/android/app/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); //调用bt_interface_t的create_bond方法
  env->ReleaseByteArrayElements(address, addr, 0);
  return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

调用bt_interface_t的create_bond方法,bt_interface_t是Bluetooth.h (packages/modules/Bluetooth/system/include/hardware)中定义的结构体,调用的是Bluetooth.cc:

//packages/modules/Bluetooth/system/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;


  do_in_main_thread(FROM_HERE,
                    base::BindOnce(btif_dm_create_bond, *bd_addr, transport));
  return BT_STATUS_SUCCESS;
}

在之后就是蓝牙协议栈相关内容,在这里就不再分析了。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中,因为 BluetoothDevice 类并没有实现 Serializable 接口,所以不能直接将 BluetoothDevice 对象保存到 SharedPreferences 中。不过,我们可以将 BluetoothDevice 对象中的 MAC 地址和名称保存到 SharedPreferences 中。 以下是一个示例代码,用来将 BluetoothDevice 对象的 MAC 地址和名称保存到 SharedPreferences 中: ```java // 将 BluetoothDevice 对象保存到 SharedPreferences 中 private void saveBluetoothDevice(BluetoothDevice device) { // 获取 SharedPreferences 对象 SharedPreferences sharedPreferences = getSharedPreferences("BluetoothDeviceInfo", Context.MODE_PRIVATE); // 获取 MAC 地址和名称 String address = device.getAddress(); String name = device.getName(); // 获取 SharedPreferences 编辑器对象 SharedPreferences.Editor editor = sharedPreferences.edit(); // 保存 MAC 地址和名称 editor.putString("address", address); editor.putString("name", name); // 提交更改 editor.apply(); } ``` 在代码中,我们首先通过 getSharedPreferences() 方法获取到一个 SharedPreferences 对象,并通过 edit() 方法获取到它的编辑器对象。然后,我们通过 BluetoothDevice 对象的 getAddress() 和 getName() 方法获取到 MAC 地址和名称,并将它们保存到 SharedPreferences 中。最后,我们通过 apply() 方法提交更改。 在需要读取保存的 BluetoothDevice 信息时,可以通过以下代码读取: ```java // 从 SharedPreferences 中读取 BluetoothDevice 信息 private BluetoothDevice readBluetoothDevice() { // 获取 SharedPreferences 对象 SharedPreferences sharedPreferences = getSharedPreferences("BluetoothDeviceInfo", Context.MODE_PRIVATE); // 读取保存的 MAC 地址和名称 String address = sharedPreferences.getString("address", null); String name = sharedPreferences.getString("name", null); // 如果 MAC 地址或名称为空,则返回 null if (address == null || name == null) { return null; } // 使用 MAC 地址创建 BluetoothDevice 对象 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); return bluetoothAdapter.getRemoteDevice(address); } ``` 在代码中,我们首先通过 getSharedPreferences() 方法获取到之前保存的 SharedPreferences 对象,并通过 getString() 方法读取保存的 MAC 地址和名称。然后,我们使用 BluetoothAdapter 的 getRemoteDevice() 方法根据 MAC 地址创建 BluetoothDevice 对象。需要注意的是,如果之前没有保存过数据,则 getString() 方法会返回 null。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值