资讯动态

framework 蓝牙笔记(三)-- 经典蓝牙

发布时间:2026/8/15 11:07:10 来源:尧图企业网站定制
在 framework 蓝牙笔记二-经典蓝牙连接配对 中有提及调用 BluetoothSocket.connect() 在未配对的情况下会自动连接回调触发系统的配对弹窗 UI。在调用socket.connect()方法后BluetoothSocket.connect() - IBluetoothSocketManager.connectSocket()/BluetoothSocketManagerBinder.connectSocket- AdapterService.connectSocketNative();AdapterService.java类在AdapterService类中首次“主动使用”时触发classInitNative,并且在onCreate()中调用initNativestatic { classInitNative(); } public void onCreate() { super.onCreate(); initMetricsLogger(); ... //初始化 initNative(mUserManager.isGuestUser(), isCommonCriteriaMode(), configCompareResult, getInitFlags(), isAtvDevice, getApplicationInfo().dataDir); ... }在classInitNative中会去声明多个回调为后面的连接配对蓝牙返回弹窗等其他功能做准备。//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp static void classInitNative(JNIEnv* env, jclass clazz) { jclass jniUidTrafficClass env-FindClass(android/bluetooth/UidTraffic); android_bluetooth_UidTraffic.constructor env-GetMethodID(jniUidTrafficClass, init, (IJJ)V); ... method_deviceFoundCallback env-GetMethodID(jniCallbackClass, deviceFoundCallback, ([B)V); method_pinRequestCallback env-GetMethodID(jniCallbackClass, pinRequestCallback, ([B[BIZ)V); method_sspRequestCallback env-GetMethodID(jniCallbackClass, sspRequestCallback, ([B[BIII)V); method_bondStateChangeCallback env-GetMethodID(jniCallbackClass, bondStateChangeCallback, (I[BII)V); ... } //*********************************************************************** static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest, jboolean isCommonCriteriaMode, int configCompareResult, jobjectArray initFlags, jboolean isAtvDevice, jstring userDataDirectory) { std::unique_lockstd::shared_timed_mutex lock(jniObjMutex); ALOGV(%s, __func__); //这边省略其他代码主要看怎么回调的流程 ... int ret sBluetoothInterface-init( sBluetoothCallbacks, isGuest JNI_TRUE ? 1 : 0, isCommonCriteriaMode JNI_TRUE ? 1 : 0, configCompareResult, flags, isAtvDevice JNI_TRUE ? 1 : 0, user_data_directory); env-ReleaseStringUTFChars(userDataDirectory, user_data_directory); ... return JNI_TRUE; }使用socket.connect()连接蓝牙中在BTIF中会去查本地密钥库如果已配对的设备直接配对通信如果是未配对的设备需要再经过认证校验后通过btif_dm_ssp_cfm_req_evt方法HAL_CBACK回调通知到上层显示弹窗。btif_dm.ccpackages/modules/Bluetooth/system/btif/src/btif_dm.cc在btif中执行SSP请求事件确认发送回调。static void btif_dm_ssp_cfm_req_evt(tBTA_DM_SP_CFM_REQ* p_ssp_cfm_req) { bt_bdname_t bd_name; bool is_incoming !(pairing_cb.state BT_BOND_STATE_BONDING); uint32_t cod; int dev_type; BTIF_TRACE_DEBUG(%s, __func__); ... pairing_cb.sdp_attempts 0; BTM_LogHistory(kBtmLogTagCallback, bd_addr, Ssp request, base::StringPrintf(name:\%s\ just_works:%c pin:%u, PRIVATE_NAME(bd_name.name), (p_ssp_cfm_req-just_works) ? T : F, p_ssp_cfm_req-num_val)); //通过ssp_request_cb回调 GetInterfaceToProfiles()-events-invoke_ssp_request_cb( bd_addr, bd_name, cod, (p_ssp_cfm_req-just_works ? BT_SSP_VARIANT_CONSENT : BT_SSP_VARIANT_PASSKEY_CONFIRMATION), p_ssp_cfm_req-num_val); }packages/modules/Bluetooth/system/btif/src/bluetooth.ccvoid invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key) { do_in_jni_thread(FROM_HERE, base::BindOnce( [](RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key) { HAL_CBACK(bt_hal_cbacks, ssp_request_cb, bd_addr, bd_name, cod, pairing_variant, pass_key); }, bd_addr, bd_name, cod, pairing_variant, pass_key));ssp_request_cb在com_android_bluetooth_btservice_AdapterService.cpp中包括其他的回调都统一注册进来了所以这边HAL_CBACK会回调到sspRequestCallback。BondStateMachine.javapackages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java通过sspRequestCallback接受BTIF回调上来的信息RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant, int passkey) { BluetoothDevice bdDevice mRemoteDevices.getDevice(address); if (bdDevice null) { mRemoteDevices.addDeviceProperties(address); } ... //发送SSP请求 Message msg obtainMessage(SSP_REQUEST); msg.obj device; if (displayPasskey) { msg.arg1 passkey; Bundle bundle new Bundle(); bundle.putByte(BondStateMachine.DISPLAY_PASSKEY, (byte) 1 /* true */); msg.setData(bundle); } msg.arg2 variant; sendMessage(msg); } //processMessage 接受SSP_REQUEST显示弹窗 public synchronized boolean processMessage(Message msg) { ... case SSP_REQUEST: int passkey msg.arg1; int variant msg.arg2; boolean displayPasskey (msg.getData() ! null) ? msg.getData().getByte(DISPLAY_PASSKEY) 1 /* 1 true */ : false; sendDisplayPinIntent( devProp.getAddress(), displayPasskey ? Optional.of(passkey) : Optional.empty(), variant); break; ... }总结BluetoothSocket.connect()本质上是一个“协议栈自动拦截未授权连接 → 硬件发起安全协商 → 系统广播驱动UI”的全自动异步过程。调用connect()接口只是声明了“需要一条加密的 RFCOMM 通道”协议栈在尝试建立这条通道时发现缺少密钥便自动触发硬件级安全协商并通过系统广播将协商结果转化为可见的配对弹窗。注意socket.connect()和createBond()在 BTM 安全引擎层完全汇合后续流程一致

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价