【android bluetooth 案例分析 04】【Carplay 详解 2】【Carplay 连接之手机主动连车机】

article/2025/6/23 10:00:23

1. 背景

在【android bluetooth 案例分析 04】【Carplay 详解 1】【CarPlay 在车机侧的蓝牙通信原理与角色划分详解】中我们从整理上介绍了车机中 carplay 相关基础概念。 本节 将详细分析 iphone手机主动 连接 车机carplay 这一过程。

先回顾一下 上一节, carplay 整个流程:

  1. EIR 广播识别

    • iPhone 开启 EIR 广播,包含 UUID_DEVICE_CARPLAY_EIR 2d8d2466-e14d-451c-88bc-7301abea291a
    • 车机通过蓝牙扫描识别支持 CarPlay 的 iPhone
  2. 蓝牙连接

    • 没有配对,需要先配对
    • iPhone 主动连接车机的 SPP Server UUID (UUID_IAP_ACCESSORY 00000000-deca-fade-deca-deafdecacaff
      • 车机需要先 listenUsingRfcommWithServiceRecord
    • 车机作为 Client 主动连接 iPhone 暴露的 Server UUID
      • (需 iPhone 开启EIR 广播)
  3. IAP2 协议交互

    • 交换设备信息、认证令牌、能力参数(支持哪种 Wi-Fi 架构)
  4. Wi-Fi 建链

    • 手机连接车机热点,或车机连接手机热点,完成 IP 建立
  5. TCP & mDNS 发现 CarPlay 服务

    • 建立 TCP 通信,寻找 _carplay._tcp.local 服务,启动 CarPlay Session
  6. 启动投屏/音频/导航服务

上面总过分为 6 步: 但是涉及到蓝牙的只有 1 、 2、 3 步。 那我们就来分别来介绍一下 在当前 手机主动连车机的清晰。这三步是如何具体实操的。

2. 手机主动连车机

1. EIR 广播

EIR 广播识别:

  1. 车机开启 EIR 广播, 包含 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3
    • 手机就可以扫描到 车机支持 carplay
  2. iPhone 开启 EIR 广播,包含 00000000-deca-fade-deca-deafdecacafe2d8d2466-e14d-451c-88bc-7301abea291a
    • 车机通过蓝牙扫描识别支持 CarPlay 的 iPhone

1. 手机 开启 EIR 广播

当 iphone 手机进入 设置 -> 通用 -> Carplay 车载 界面时, 此时,车机如果开启 扫描。此时就能从 扫描到的 EIR 中看到如下的广播信息。


300	2025-01-01 19:40:57.096358	controller	host	HCI_EVT	258	Rcvd Extended Inquiry ResultBluetooth HCI Event - Extended Inquiry ResultEvent Code: Extended Inquiry Result (0x2f)Parameter Total Length: 255Number of responses: 1BD_ADDR: Apple_7c:81:36 (84:ad:8d:7c:81:36)Page Scan Repetition Mode: R1 (0x01)Reserved: 0x00Class of Device: 0x7a020c (Phone:Smartphone - services: Networking Capturing ObjectTransfer Audio Telephony).110 1101 0010 1011 = Clock Offset: 0x6d2bRSSI: -38 dBmExtended Inquiry Response DataDevice Name: JxlLength: 4Type: Device Name (0x09)Device Name: Jxl16-bit Service Class UUIDsLength: 15Type: 16-bit Service Class UUIDs (0x03)UUID 16: PnP Information (0x1200)UUID 16: Handsfree Audio Gateway (0x111f)UUID 16: Phonebook Access Server (0x112f)UUID 16: Audio Source (0x110a)UUID 16: A/V Remote Control Target (0x110c)UUID 16: Message Access Server (0x1132)UUID 16: Generic Attribute Profile (0x1801)32-bit Service Class UUIDsLength: 1Type: 32-bit Service Class UUIDs (0x05)128-bit Service Class UUIDsLength: 49Type: 128-bit Service Class UUIDs (0x07)Custom UUID: 00000000-deca-fade-deca-deafdecacafe (Unknown)Custom UUID: 02030302-1d19-415f-86f2-22a2106a0a77 (Unknown)Custom UUID: 2d8d2466-e14d-451c-88bc-7301abea291a (Unknown)  // 此时手机 回复的 uuid 中就包含, 识别手机支持 carplay 的 uuidManufacturer SpecificLength: 39Type: Manufacturer Specific (0xff)Company ID: Unknown (0x4c00)Data: 022402000000000000000000000000000000000000000000000000000000000000000000[Expert Info (Note/Undecoded): Undecoded][Undecoded][Severity level: Note][Group: Undecoded]Unused

2d8d2466-e14d-451c-88bc-7301abea291a 这个 uuid 就是帮助车机筛选 那些手机支持 carplay 功能的。

在协议栈中 我们会将 该 uuid 上报 到 应用侧。如果不明白 如果上报,可以看一下这篇文章
【android bluetooth 协议分析 03】【蓝牙扫描详解 1】【扫描关键函数 btif_dm_search_devices_evt 分析】

此时在车机 carplay 连接 界面就可以看到 当前 iphone 手机。

2. 车机开启EIR 广播

分析到这里, 有人疑惑,车机是 可以看到 手机支持 carplay. 但是此时 手机 应该看不到 车机支持carplay 功能吧。确实是这样子?

我们可以参照手机的操作。 将 carplay 的 uuid 写入 车机的 EIR 中。 这样手机在扫描时 , 就可以扫描 到车机的 EIR. 这块手机就可以发现 车机支持 carplay.

如下是 app 侧的操作 流程:

    /*我们代码添加IAP的uuid,车机的BT模块里自动添加CP的uuid*///IAP2 uuid 使用此uuid,手机才能发起IAP连接private static final UUID SERVER_SPP_UUID = UUID.fromString("00000000-deca-fade-deca-deafdecacaff");//CP uuid 使用此uuid,手机CarPlay车载画面能够扫描出来,但是在手机CarPlay车载画面点击车机时,无法连接上private static final UUID SERVER_SPP_UUID_CP = UUID.fromString("EC884348-CD41-40A2-9727-575D50BF1FD3");BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();BluetoothServerSocket mServerSocket = adapter.listenUsingRfcommWithServiceRecord("com.running.android.carplay", SERVER_SPP_UUID);BluetoothSocket mClientSocket = mServerSocket.accept();
  1. 先调用 listenUsingRfcommWithServiceRecord 方法,在 该 listenUsingRfcommWithServiceRecord 中,就会将 00000000-deca-fade-deca-deafdecacaff 和 EC884348-CD41-40A2-9727-575D50BF1FD3 两个 uuid. 写入到我们的 eir 中。 并创建 一个 spp server.
  2. mServerSocket.accept(); 等待 手机来连接。 手机连接后,将会返回一个新的 socket.
  3. 拿到这个 socket. 手机和车机就可以 交互 carplay 连接需要的信息。例如 wifi 热点名字,密码等。

105	2025-01-01 19:40:31.420798	host	controller	HCI_CMD	245	Sent Write Extended Inquiry ResponseFrame 105: 245 bytes on wire (1960 bits), 245 bytes captured (1960 bits)
Bluetooth
Bluetooth HCI H4
Bluetooth HCI Command - Write Extended Inquiry ResponseCommand Opcode: Write Extended Inquiry Response (0x0c52)Parameter Total Length: 241FEC Required: true (1)Extended Inquiry Response DataDevice Name: xxxxxx16-bit Service Class UUIDsLength: 13Type: 16-bit Service Class UUIDs (0x03)UUID 16: Audio Sink (0x110b)UUID 16: A/V Remote Control Target (0x110c)UUID 16: A/V Remote Control (0x110e)UUID 16: Handsfree (0x111e)UUID 16: Phonebook Access Client (0x112e)UUID 16: PnP Information (0x1200)32-bit Service Class UUIDsLength: 1Type: 32-bit Service Class UUIDs (0x05)128-bit Service Class UUIDsLength: 129Type: 128-bit Service Class UUIDs (0x07)Custom UUID: 00000000-deca-fade-deca-deafdecacaff (Unknown) // 这个是 app 侧下发的 uuidCustom UUID: ec884348-cd41-40a2-9727-575d50bf1fd3 (Unknown) // 这个我们根据 app 下发的uuid 在协议栈中我们任务加的Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Custom UUID: 00000000-0000-0000-0000-000000000000 (Unknown)Tx Power LevelLength: 2Type: Tx Power Level (0x0a)Power Level (dBm): 8Unused[Response in frame: 106][Command-Response Delta: 28.115ms]
  • 此时 我们的手机就可以正确的扫描到 我们的车机也支持 carplay。

2. 蓝牙连接 iap 并通信

没有配对,需要先配对 : 这个是常规操作, 这里不分享了。

这里主要分析一下。 手机 主动连接 车机 iap 的过程:

在这里插入图片描述

在这里插入图片描述

  • 手机向 车机发起了 sdp , 这里手机向我们查询的 uuid. 正是我们前面注册的 00000000-deca-fade-deca-deafdecacaff
  • 车机回复了 对应的 rfcomm 通道为 3

手机继续 主动查询 车机之前注册的 UUID ec884348-cd41-40a2-9727-575d50bf1fd3

在这里插入图片描述

在这里插入图片描述

这里车机回复了该uuid 对应的 rfcomm 通道为 4

在这里插入图片描述

手机 主动 请求连接车机的 rfcomm channel 3

在这里插入图片描述

接下来 车机和手机 通过 channel 3 开始将 后面 carplay 连接需要的 wifi 相关的 热点名字,密码发送给手机。

3. 总结

手机 如果要主动连接车机carplay

车机需要 完成如下步骤:

  1. 车机 app 侧需要 通过如下代码:
    • 开启 车机 EIR 广播:广播 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3 这样 在手机carplay 界面才可以看到车机。
    • 向 sdp 数据库中注册 上述 两个uuid. 这样 手机主动发起 上述两个服务的uuid 时, 车机才知道如何回复。
	BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();// 开启 EIR 和 注册 SDP 数据库,都是通过该调用实现的BluetoothServerSocket mServerSocket = adapter.listenUsingRfcommWithServiceRecord("com.running.android.carplay", SERVER_SPP_UUID);
  1. 车机carplay app. 等待 手机连接
BluetoothSocket mClientSocket = mServerSocket.accept(); // 当手机主动连接时, 这里将返回,一个新的 socket. 用于 iap 内容交互
  1. 此时 手机 carplay 界面就可以扫描到 车机, 点击界面发起 对车机的主动连接:

    • 此时会看到 手机主动向 车机发起 00000000-deca-fade-deca-deafdecacaffec884348-cd41-40a2-9727-575d50bf1fd3 两个服务的 SDP 查询。
    • 车机返回对应的 rfcomm 通道号。 例如 00000000-deca-fade-deca-deafdecacaff iap协议, rfcomm channel= 3
  2. 手机主动发起 rfcomm channel 3 , iap 协议的连接。

  3. 车机和手机,此时就可以通过 iap 协议交互,后续 carplay 连接所需要的 wifi 热点信息。

  4. 交互完成后,断开rfcomm channel3

  5. 发起 真正的 carplay 连接, 此时就可以看到 手机将画面 投屏到车机上。

这里的重点是 调用 listenUsingRfcommWithServiceRecord 函数。
该函数的讲解,将在另外的 文章中单独讲解。


http://www.hkcw.cn/article/fJglnsbuwE.shtml

相关文章

【Kotlin】数字字符串数组集合

【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 文章目录 Kotlin_数字&字符串&数组&集合数字字面常量显式转换数值类型转换背后发生了什么 运算字符串字符串模板字符串判等修饰符数组集合通过序列提高效率惰性求值序列的操…

FreeCAD源码分析: 串行化工具

本文分析FreeCAD中的串行化工具。 注1:限于研究水平,分析难免不当,欢迎批评指正。 注2:文章内容会不定期更新。 零、预修 0.1 QDataStream 0.2 Boost.Iostreams 0.3 Zipios 0.4 Xerces-C 一、核心组件 1.1 Base::Writer 1.2 Ba…

【R语言编程绘图-plotly】

安装与加载 在R中使用plotly库前需要安装并加载。安装可以通过CRAN进行,使用install.packages()函数。加载库使用library()函数。 install.packages("plotly") library(plotly)测试库文件安装情况 # 安装并加载必要的包 if (!requireNamespace("p…

设计模式——系统数据建模设计

摘要 本文主要介绍了UML在软件系统分析和设计中的应用,详细阐述了六大类关系(泛化、实现、依赖、关联、聚合、组合)及其在UML类图中的表示方法,并通过具体例子说明了这些关系在实际编程中的应用。同时,文章还概述了UM…

37. Sudoku Solver

题目描述 37. Sudoku Solver 回溯 class Solution {vector<vector<bool>> row_used;vector<vector<bool>> col_used;vector<vector<bool>> box_used;public:void solveSudoku(vector<vector<char>>& board) {row_used.r…

【Java开发日记】基于 Spring Cloud 的微服务架构分析

目录 1、Spring Cloud 2、Spring Cloud 的核心组件 1. Eureka&#xff08;注册中心&#xff09; 2. Zuul&#xff08;服务网关&#xff09; 3. Ribbon&#xff08;负载均衡&#xff09; 4. Hystrix&#xff08;熔断保护器&#xff09; 5. Feign&#xff08;REST转换器&a…

进程间通信IV System V 系列(linux)

目录 消息队列 原理 操作 补充概念 信号量 (原子性计数器) 原理 操作 (和共享内存相似) 总结 小知识 消息队列 原理 在内核中建立一个队列&#xff0c;进程可以相互进行通信&#xff0c;通过队列进行IPC&#xff0c;就是进程之间发送带类型的数据块。 操作 接口和共享…

【MySQL】索引(B+树详解)

MySQL(五)索引 一、索引的减I/O设计 1.读取量 2.搜索树 2.1方向 2.2有序 3.分多叉 3.1B树 弊端: 3.2B树 3.2.1非叶子-搜索字段 3.2.1.1海量分叉 3.2.1.1.1最大式 3.2.1.1.2最快式 3.2.1.2缓存内存 3.2.1.2.1字段总量小 3.2.1.2.2时间复杂度 3.2.1.3区间搜索向…

2025年全国青少年信息素养大赛复赛C++算法创意实践挑战赛真题模拟强化训练(试卷4:共计6题带解析)

2025年全国青少年信息素养大赛复赛C++算法创意实践挑战赛真题模拟强化训练(试卷4:共计6题带解析) 第1题:最佳情侣身高差(题目及解析) 题目描述 专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高) 1.09 =(男方的身高)。如果符合,你俩的身…

5.31 day33

知识点回顾&#xff1a; PyTorch和cuda的安装 查看显卡信息的命令行命令&#xff08;cmd中使用&#xff09; cuda的检查 简单神经网络的流程 数据预处理&#xff08;归一化、转换成张量&#xff09; 模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 定义损失函数和优…

【C++】模板

目录 1、函数模板 基本用法 函数模板的实现原理 函数模板的实例化 模板参数的匹配原则 2、类模板 类模板的定义格式 类模板的实例化 1、函数模板 基本用法 template < typename T >返回值类型 函数名(参数列表){} template 是模板的意思&#xff0c;typename是…

第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型

在计算机视觉领域,OpenCV的DNN(深度神经网络)模块正逐渐成为轻量级模型部署的利器。本文将深入探讨如何利用OpenCV加载和运行三大主流框架(TensorFlow、PyTorch、Caffe)训练的模型,并提供完整的代码实现和优化技巧。 一、OpenCV DNN模块的核心优势 OpenCV的DNN模块自3.3…

Linux系统下安装配置 Nginx

Windows Nginx https://nginx.org/en/download.htmlLinux Nginx https://nginx.org/download/nginx-1.24.0.tar.gz解压 tar -zxvf tar -zxvf nginx-1.18.0.tar.gz #解压安装依赖&#xff08;如未安装&#xff09; yum groupinstall "Development Tools" -y yum…

qwen3解读

1. 模型架构 重点&#xff1a; 思维模式和非思维模式这两种不同的操作模式集成到一个模型中。这样可以让用户在这些模式间切换&#xff0c;而不是在不同模型间切换。多阶段的后培训方法&#xff1a;增强推理和非推理模式。将基础模型和人的偏好结合。 预训练阶段&#xff1a…

用127.0.0.1访问VMware虚拟机中间件

文章目录 前言一、虚拟机安装、插件安装二、改虚拟机配置1.更改虚拟机使用的是 NAT 模式2.编辑 VMware 的 NAT 设置并添加端口转发 总结至此大功告成了&#xff01;&#xff01;&#xff01; 前言 docker 安装中间件很方便,平时使用windows作开发,如果想快速安装中间件,那么首…

【大模型部署】mac m1本地部署 ChatGLM3-6B 超详细教程

本人环境&#xff1a;macOS 15.5 (Sonoma) - Apple M1 / 16 G 目标&#xff1a;在 mac m1 16G 上 完全离线 的本地模型目录上&#xff0c;跑通官方 ChatGLM3-6B 目录 背景 & 踩坑记录 准备工作 新建 Conda 环境并安装依赖 关键环境变量 运行 composite_demo 常见报错与…

评标专家随机抽选系统-建设方案——仙盟创梦IDE

政策要求 抽选记录保存 专辑库管理 系统统计 抽选打印 系统分级管理 项目管理 系统分级管理 集团公司管理 专家补抽 评标专家随机抽选 1、系统分级管理合规 符合《数据安全法》第二十一条&#xff08;分类分级制度&#xff09;&#xff0c;安全按照不同职级&#xff0c;配置权…

2.5/Q2,Charls最新文章解读

文章题目&#xff1a;Trajectories of depressive symptoms and risk of chronic liver disease: evidence from CHARLS DOI&#xff1a;10.1186/s12876-025-03943-7 中文标题&#xff1a;抑郁症状的轨迹和慢性肝病风险&#xff1a;来自 CHARLS 的证据 发表杂志&#xff1a;BM…

win1011安装WinGet和Windows Terminal

前言 winget是微软推出的类似Ubuntu apt 的包管理器。安装winget建议一同安装微软推出的代替conhost.exe的新版命令提示符工具Windows Terminal。 安装 Windows Terminal 微软商店 github 安装后以管理员打开老版命令提示符&#xff0c;上方任务栏右键-默认值-终端-默认终端…

深 入 剖 析 单 链 表:从 原 理 到 实 战 应 用

深 入 剖 析 单 链 表&#xff1a;从 原 理 到 实 战 应 用 顺 序 表 的 问 题单 链 表单 链 表 与 顺 序 表 区 别相 关 概 念链 表 定 义单 链 表 定 义存 储 结 构 单 链 表 的 操 作 实 现代 码 全 貌 与 功 能 介 绍单 链 表 的 功 能 说 明代 码 效 果 展 示代 码 详 解S…