活动介绍
file-type

Android BLE源码流程图解析:广播、扫描、连接、数据读写

版权申诉
5星 · 超过95%的资源 | 708KB | 更新于2024-11-06 | 164 浏览量 | 18 下载量 举报 6 收藏
download 限时特惠:#11.90
本资源提供了Android平台中蓝牙低功耗广播、扫描、连接以及数据读写操作的源码流程图,并详细解释了从btif(Bluetooth Interface)到bta(Bluetooth Adapter)、btm(Bluetooth Manager)、再到HCI(Host Controller Interface)的数据流程。这些流程图以视觉化的方式展示了从蓝牙控制器接收到数据到btm层的整个过程,帮助开发者深入理解Android蓝牙源码的数据流向,并能够更快速地熟悉相关源码,从而有效解决开发过程中遇到的问题和BUG。" 知识点: 1. 蓝牙低功耗技术(BLE)简介 - BLE是一种专为低功耗通信而设计的蓝牙技术,广泛应用于小型设备和传感器。 - BLE具有快速连接、小数据包传输、低延迟等特点。 2. Android蓝牙架构 - Android的蓝牙框架基于三个主要组件:btif、bta、btm。 - btif为应用程序提供蓝牙接口。 - bta负责管理蓝牙硬件的适配器。 - btmm负责管理蓝牙的配对和连接。 3. 数据流程图的必要性 - 数据流程图能帮助开发者直观理解数据是如何在不同层级间传输的。 - 在蓝牙开发中,流程图揭示了广播、扫描、连接及数据读写等操作的实现细节。 4. 广播、扫描、连接、数据读写的实现原理 - 广播:设备通过广告包广播自己的存在,其他设备通过扫描识别。 - 扫描:设备主动搜索周围广播设备的信息。 - 连接:通过扫描找到的设备进行配对、建立连接。 - 数据读写:连接后,设备间可以进行数据的发送和接收。 5. HCI的作用与重要性 - HCI是蓝牙协议栈与蓝牙硬件之间的接口。 - HCI负责处理底层的数据传输和硬件通信,是连接高层协议与蓝牙控制器的关键。 6. Android源码结构与流程 - Android蓝牙源码分布在多个模块中,流程图有助于开发者快速定位和理解这些模块。 - 通过流程图,开发者可以了解如何在不同模块间进行数据交互和处理。 7. Android源码中的关键文件与类 - 在蓝牙开发中,开发者需要熟悉核心文件和类,如BluetoothAdapter、BluetoothProfile、BluetoothDevice等。 - 对于高级开发者,深入理解这些组件的内部机制是必要的。 8. 问题处理与BUG解决 - 理解源码流程图有助于识别和分析开发中出现的问题。 - 能够帮助开发者更快地定位BUG,并提供解决方案。 9. 开发者在使用流程图时的建议 - 开发者应将流程图与实际源码结合学习,以增强理解。 - 在项目开发中,应适时参考流程图以确保开发方向的正确性。 - 面对复杂的问题时,应尝试通过流程图梳理数据流向,逐步缩小问题范围。 以上知识点,结合了Android蓝牙低功耗技术的核心概念,源码结构分析,以及数据流的详细解释,对Android蓝牙开发者而言,这些内容提供了深入学习和问题解决的宝贵信息。通过流程图,开发者不仅能够把握整体的蓝牙通信架构,还能够详细理解每一层的工作原理,为高效开发和问题调试提供了有力的支撑。

相关推荐

filetype

识别并详细讲解图片上关于“android蓝牙连接过程分析(三)--btm_cb.api回调函数的赋值”的代码,讲解具体的函数和方法的调用过程和执行流程以及每个函数或方法的内容都进行详细的讲解。代码内容如下: static void bta_dm_sys_hw_cback(tBTA_SYS_HW_EVT status) { DEV_CLASS dev_class; tBTA_DM_SEC_CBACK *temp_cback; UINT8 key_mask = 0; UINT8 mode = 0; if(status == BTA_SYS_HW_ON_EVT) { if(bta_dm_cb.p_sec_cback && bta_dm_cb.is_bta_dm_active == FALSE) { /* restore the application callback */ temp_cback = bta_dm_cb.p_sec_cback; memset(&bta_dm_cb, 0, sizeof(bta_dm_cb)); bta_dm_cb.p_sec_cback = temp_cback; bta_dm_cb.is_bta_active = TRUE; /* make sure the control block is properly initialized */ if(bta_dm_cb.p_sec_cback && bta_dm_cb.is_bta_dm_active) { /* set the Security callback to the firmware */ bta_dm_cb.p_sec_cback(BTA_DM_SEC_CHG_EVT, &bta_dm_cb); } } } else if(status == BTA_SYS_HW_OFF_EVT) { /* save security callback */ temp_cback = bta_dm_cb.p_sec_cback; memset(&bta_dm_cb, 0, sizeof(bta_dm_cb)); bta_dm_cb.p_sec_cback = temp_cback; bta_dm_cb.is_bta_active = FALSE; } BTM_SecRegister((tBTM_APPL_INFO *)&bta_security); BTM_SetDiscoverability((tBTM_DISC_MODE)bta_dm_cb.disc_mode, bta_dm_cb.disc_duration, bta_dm_cb.disc_interval); bta_dm_cb.cur_policy = bta_dm_cb.policy; BTM_SetLinkPolicy(bta_dm_cb.policy); } 在重要后语中分析bta_dm_sys_hw_cback函数中,在这里里面使用BTM_SecRegister函数来注册一个Security service服务,在这里里面,入参为 bta_security结构体。 tBTM_SecRegister(tBTM_APPL_INFO *p_cb_info) { BT_HDR_INCLUDED == TRUE IF_OCTET16 temp_value = {0}; tBTM_TRACE_EVENT ("BTM_Sec: application registered"); #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE if (p_cb_info->p_le_callback) { BTM_TRACE_ERROR ("BTM_SecRegister: p_cb_info->p_le_callback = 0x%x", p_cb_info->p_le_callback); } #endif if (p_cb_info->p_le_callback) { BTM_TRACE_ERROR ("BTM_SecRegister: DEV_CB.api.p_le_callback = 0x%x", p_cb_info->p_le_callback); } #if SMP_INCLUDED == TRUE if (p_cb_info->p_le_callback) { BTM_TRACE_EVENT ("BTM_Sec: application registered"); } #endif btm_cb.api = *p_cb_info; BTM_TRACE_ERROR ("BTM_SecRegister: p_cb_info->p_le_callback = 0x%x", p_cb_info->p_le_callback); #if SMP_INCLUDED == TRUE if (p_cb_info->p_le_callback) { btm_cb.api.p_le_callback = p_cb_info->p_le_callback; BTM_TRACE_EVENT ("BTM_Sec: application registered"); } #endif } 这是公开的函数列表,函数体内的功能说明,在这里bta_security结构体信息被赋值给btm_cb.api可以看到这是个重要的回调函数。 bta_security callback结构体分析 /* bta_security_callback */ const tBTM_APPL_INFO bta_security = { &bta_dm_authorize_cback, &bta_dm_pin_cback, &bta_dm_new_link_key_cback, &bta_dm_link_key_request_cback, &bta_dm_authentication_complete_cback, NULL, &bta_dm_bond_cancel_complete_cback, #if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE) &bta_dm_sp_cback, #else NULL, #endif #if SMP_INCLUDED == TRUE &bta_dm_ble_smp_cback #else NULL #endif &bta_dm_ble_id_key_cback #endif }; 在这里看到bta_security结构体的定义,里面包含了各种回调函数的定义,这是一个重要的结构体,也是整个蓝牙认证过程中非常重要的一环。 const tBTM_APPL_INFO bta_security = { &bta_dm_authorize_cback, &bta_dm_pin_cback, &bta_dm_new_link_key_cback, &bta_dm_link_key_request_cback, &bta_dm_authentication_complete_cback, NULL, &bta_dm_bond_cancel_complete_cback, #if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE) &bta_dm_sp_cback, bta_security结构体的sp_callback定义 #else NULL, #endif #if SMP_INCLUDED == TRUE &bta_dm_ble_smp_cback #else NULL #endif &bta_dm_ble_id_key_cback #endif }; bta_security结构体的sp_callback定义数btm_cb.api.p_sp_callback = bta_dm_sp_cback主要,充当了蓝牙连接过程中的认证。

filetype

详细讲解下面的代码: { // 准备存放设备名称和 UUID(16-bit 和 128-bit)的缓存区。 /* inquiry result */ bt_bdname_t bdname; uint8_t remote_name_len; uint8_t num_uuids = 0, num_uuids128 = 0, max_num_uuid = 32; uint8_t uuid_list[32 * Uuid::kNumBytes16]; uint8_t uuid_list128[32 * Uuid::kNumBytes128]; // 根据 EIR 数据判断是否需要发起 Remote Name Request(即设备是否已广播出名称)。 p_search_data->inq_res.remt_name_not_required = check_eir_remote_name(p_search_data, NULL, NULL); // 获取发现设备的地址。 RawAddress& bdaddr = p_search_data->inq_res.bd_addr; BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __func__, bdaddr.ToString().c_str(), p_search_data->inq_res.device_type); bdname.name[0] = 0; // 尝试从 EIR 中读取名称,失败则从缓存中获取。 if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len)) check_cached_remote_name(p_search_data, bdname.name, &remote_name_len); /* Check EIR for services */ // 获取 UUID(服务)信息: if (p_search_data->inq_res.p_eir) { BTM_GetEirUuidList(p_search_data->inq_res.p_eir, p_search_data->inq_res.eir_len, Uuid::kNumBytes16, &num_uuids, uuid_list, max_num_uuid); BTM_GetEirUuidList(p_search_data->inq_res.p_eir, p_search_data->inq_res.eir_len, Uuid::kNumBytes128, &num_uuids128, uuid_list128, max_num_uuid); } { /* 构建属性列表: 将设备属性打包成数组,逐项填充: - 蓝牙地址 - 名称 - 类别(COD) - 类型(BR/EDR、BLE 或 DUAL) - RSSI - 是否支持 CSIP 协调组 - UUID(服务) UUID 部分还会缓存入 eir_uuids_cache,并使用 btif_update_uuid 做去重更新。 */ bt_property_t properties[7]; bt_device_type_t dev_type; uint32_t num_properties = 0; bt_status_t status; tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC; memset(properties, 0, sizeof(properties)); /* RawAddress */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr); num_properties++; /* BD_NAME */ /* Don't send BDNAME if it is empty */ if (bdname.name[0]) { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_BDNAME, strlen((char*)bdname.name), &bdname); num_properties++; } /* DEV_CLASS */ uint32_t cod = devclass2uint(p_search_data->inq_res.dev_class); BTIF_TRACE_DEBUG("%s cod is 0x%06x", __func__, cod); if (cod != 0) { BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); num_properties++; } /* DEV_TYPE */ /* FixMe: Assumption is that bluetooth.h and BTE enums match */ /* Verify if the device is dual mode in NVRAM */ int stored_device_type = 0; if (btif_get_device_type(bdaddr, &stored_device_type) && ((stored_device_type != BT_DEVICE_TYPE_BREDR && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BREDR) || (stored_device_type != BT_DEVICE_TYPE_BLE && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE))) { dev_type = (bt_device_type_t)BT_DEVICE_TYPE_DUMO; } else { dev_type = (bt_device_type_t)p_search_data->inq_res.device_type; } if (p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE) addr_type = p_search_data->inq_res.ble_addr_type; BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type); num_properties++; /* RSSI */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t), &(p_search_data->inq_res.rssi)); num_properties++; /* CSIP supported device */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_REMOTE_IS_COORDINATED_SET_MEMBER, sizeof(bool), &(p_search_data->inq_res.include_rsi)); num_properties++; /* Cache EIR queried services */ if ((num_uuids + num_uuids128) > 0) { uint16_t* p_uuid16 = (uint16_t*)uuid_list; auto uuid_iter = eir_uuids_cache.find(bdaddr); Uuid new_remote_uuid[BT_MAX_NUM_UUIDS]; size_t dst_max_num = sizeof(new_remote_uuid)/sizeof(Uuid); size_t new_num_uuid = 0; Uuid remote_uuid[BT_MAX_NUM_UUIDS]; if (uuid_iter == eir_uuids_cache.end()) { auto triple = eir_uuids_cache.try_emplace(bdaddr, std::set<Uuid>{}); uuid_iter = std::get<0>(triple); } //LOG_INFO("EIR UUIDs for %s:", bdaddr.ToString().c_str()); for (int i = 0; i < num_uuids; ++i) { Uuid uuid = Uuid::From16Bit(p_uuid16[i]); //LOG_INFO(" %s", uuid.ToString().c_str()); uuid_iter->second.insert(uuid); if (i < BT_MAX_NUM_UUIDS) { remote_uuid[i] = uuid; } else { LOG_INFO("%d >= %d", i, BT_MAX_NUM_UUIDS); } } for (int i = 0; i < num_uuids128; ++i) { Uuid uuid = Uuid::From128BitBE((uint8_t *)&uuid_list128[i * Uuid::kNumBytes128]); //LOG_INFO(" %s", uuid.ToString().c_str()); uuid_iter->second.insert(uuid); if (i < BT_MAX_NUM_UUIDS) { remote_uuid[num_uuids + i] = uuid; } else { LOG_INFO("%d >= %d", i, BT_MAX_NUM_UUIDS); } } //LOG_INFO("%s %d : update EIR UUIDs.", __func__, __LINE__); new_num_uuid = btif_update_uuid(bdaddr, remote_uuid, (num_uuids + num_uuids128), new_remote_uuid, sizeof(new_remote_uuid), dst_max_num); BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties], BT_PROPERTY_UUIDS, new_num_uuid * Uuid::kNumBytes128, new_remote_uuid); //LOG_INFO("%s %d : fill BT_PROPERTY_UUIDS property.", __func__, __LINE__); num_properties ++; } // 持久化 & 回调: status = btif_storage_add_remote_device(&bdaddr, num_properties, properties); // 添加进本地数据库 ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote device (inquiry)", status); status = btif_storage_set_remote_addr_type(&bdaddr, addr_type); // 保存 BLE 地址类型 ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote addr type (inquiry)", status); bool restrict_report = osi_property_get_bool( "bluetooth.restrict_discovered_device.enabled", false); // 限制上报策略, 可选地根据系统属性是否限制上报某些设备。 if (restrict_report && p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE && !(p_search_data->inq_res.ble_evt_type & BTM_BLE_CONNECTABLE_MASK)) { LOG_INFO("%s: Ble device is not connectable", bdaddr.ToString().c_str()); break; } // 上报到上层(Java 层): 触发 BluetoothAdapter.onBluetoothDeviceFound() 等 Java 层通知。 /* Callback to notify upper layer of device */ invoke_device_found_cb(num_properties, properties); } }

短距WCN协议开发分享
  • 粉丝: 2432
上传资源 快速赚钱