当前位置: 首页 > article >正文

【Bluedroid】 BLE连接源码分析(一)

BLE链接过程分析见【Bluedroid】BLE连接过程详解-CSDN博客,本篇主要围绕HCI_LE_Create_Connection展开。基于Android14源码进行分析。在蓝牙低功耗技术中,设备之间建立连接是进行数据传输等操作的前提。HCI LE Extended Create Connection Command 提供了一种更灵活、功能更丰富的方式来创建连接,相比传统的连接创建命令,它能支持更多的参数配置和功能特性,以满足不同应用场景下的连接需求。

一、创建连接指令下发(HCI_LE_Create_Connection)过程

  • 主设备发起:主设备发送 HCI LE Extended Create Connection Command 命令,其中包含了指定的连接参数等信息,如连接间隔和连接延迟等。
  • 从设备响应:从设备接收到命令后,会根据自身的能力和配置来决定是否接受连接。如果从设备支持主设备所请求的连接参数,并且当前资源允许,它会发送一个响应消息,表示接受连接请求。
  • 连接建立:双方根据协商好的连接参数开始建立连接,按照设定的连接间隔进行数据交互等操作,从设备会根据连接延迟参数来控制自身的休眠和唤醒时间,以实现节能和数据传输的平衡。

二、源码分析

BTM_AcceptlistAdd

从BTM_AcceptlistAdd开始分析:

/packages/modules/Bluetooth/system/stack/btm/btm_ble_bgconn.cc
bool BTM_AcceptlistAdd(const RawAddress& address) {
  return BTM_AcceptlistAdd(address, false);
}

bool BTM_AcceptlistAdd(const RawAddress& address, bool is_direct) {
  if (!controller_get_interface()->SupportsBle()) {
    log::warn("Controller does not support Le");
    return false;
  }

  return bluetooth::shim::ACL_AcceptLeConnectionFrom(
      BTM_Sec_GetAddressWithType(address), is_direct);
}

BTM_AcceptlistAdd将对端地址添加到BLE连接列表中。由于BLE连接的建立是异步的,因此即使这个函数返回了 true,也并不意味着连接已经成功建立,而只是表示连接请求已经被接受并开始处理。

另外,is_direct 参数可能用于指示连接请求是否是通过某种直接方式(如通过已知的设备地址发起连接)发出的。

bluetooth::shim::ACL_AcceptLeConnectionFrom

/packages/modules/Bluetooth/system/main/shim/acl_api.cc
bool bluetooth::shim::ACL_AcceptLeConnectionFrom(
    const tBLE_BD_ADDR& legacy_address_with_type, bool is_direct) {
  std::promise<bool> promise;  // 用于异步操作的对象
  
  // 调用promise.get_future()获取与promise关联的future对象。future用于在异步操作完成后获取结果值
  auto future = promise.get_future();
  
  // 调用 AcceptLeConnectionFrom 方法
  Stack::GetInstance()->GetAcl()->AcceptLeConnectionFrom(
      ToAddressWithTypeFromLegacy(legacy_address_with_type), is_direct,
      std::move(promise));
  
  //调用future.get()等待异步操作完成并获取结果。future.get()会阻塞当前线程,直到异步操作完成并设置了结果值
  return future.get();
  }

接受来自特定蓝牙低功耗(BLE)设备的连接请求。它使用 std::promise 和 std::future 实现了异步操作的同步等待,确保在接受连接请求的操作完成后,返回操作结果(是否成功接受连接)。

  • 注意:由于BLE连接的建立是一个异步过程,即使这个函数返回true,也不意味着连接已经成功建立。只是表示连接请求已经被接受,并且连接建立过程已经开始。

shim::legacy::Acl::AcceptLeConnectionFrom

/packages/modules/Bluetooth/system/main/shim/acl.cc
void shim::legacy::Acl::AcceptLeConnectionFrom(
    const hci::AddressWithType& address_with_type, bool is_direct,
    std::promise<bool> promise) {
  LOG_DEBUG("AcceptLeConnectionFrom %s",
            ADDRESS_TO_LOGGABLE_CSTR(address_with_type.GetAddress()));
  handler_->CallOn(pimpl_.get(), &Acl::impl::accept_le_connection_from,
                   address_with_type, is_direct, std::move(promise));
}

将实际的处理逻辑委托给 Acl::impl 类的 accept_le_connection_from 方法,并使用 handler_ 来确保操作在合适的线程或上下文环境中执行。

  • pimpl_.get():使用了指向 Acl::impl 实现的智能指针,并通过 get() 方法获取原始指针。这是一种实现隐藏(Pimpl Idiom)的常见方式,用于在接口和实现之间提供清晰的分离。

  • &Acl::impl::accept_le_connection_from:指向 Acl::impl 类中 accept_le_connection_from 成员函数的指针。

  • address_with_type, is_direct, std::move(promise):这些是传递给 accept_le_connection_from 函数的参数。注意,promise 参数被 std::move 了,意味着它的所有权被转移给了 CallOn 方法。

关于 std::promise<bool> 的使用:

std::promise<bool> 被用作异步操作的结果传递机制。当 accept_le_connection_from 函数完成其工作时,它应该调用 promise.set_value(some_bool_value) 来设置结果,其中 some_bool_value 表示操作的成功或失败。然后,任何持有与 promise 相关联的 std::future<bool> 的代码都可以调用 future.get() 来等待结果并获取它。


http://www.kler.cn/a/548792.html

相关文章:

  • LeetCode每日精进:203.移除链表元素
  • 开发中需要使用到volatile的情况
  • 【大模型系列】入门常识备忘
  • IT行业方向细分,如何做到专家水平——7.边缘计算与物联网(IoT)
  • 算法刷题--哈希表--字母异位词和两个数组的交集
  • 从短片到长片:王琦携《Mountain》续作迈向新高度
  • Python进制转换
  • 智能设备监控:AI 与 Python 助力设备管理的未来
  • Substance Painter快捷键
  • 【AJAX】项目——数据管理平台
  • LabVIEW的吞雨测控系统
  • 【鸿蒙】ArkUI-X跨平台问题集锦
  • 虚拟机安装k8s集群
  • RFID技术在制造环节的应用与价值
  • 中缀表达式转后缀表达式(逆波兰表达式)并进行计算
  • Transformer 模型介绍(四)——编码器 Encoder 和解码器 Decoder
  • redis cluster测试
  • 基于Istio Ambient Mesh的无边车架构:实现零侵入式服务网格的云原生革命
  • Android remount failed: Permission denied 失败解决方法
  • 【前端框架】Vue 3组件生命周期钩子的使用场景