【android bluetooth 案例分析 03】【PTS 测试 】【PBAP/PCE/SSM/BV-10-C】

1. PBAP/PCE/SSM/BV-10-C

[PCE Does not share PbapSupportedFeatures bits]

这个 PTS 测试用例 PBAP/PCE/SSM/BV-10-C 的核心目的是验证 PBAP 客户端(PCE)在与旧版服务器通信时不会发送 PbapSupportedFeatures 特性位,以确保兼容性和标准符合性。

1. 测试目标

Verify that the PCE does not share its PbapSupportedFeatures bits with a legacy server.

目的:验证 PCE(Phonebook Client Equipment)在与一个不支持 PbapSupportedFeatures SDP 属性的 legacy(传统)PBAP Server 建立连接时,不应在 OBEX CONNECT 请求中包含 PbapSupportedFeatures Header

这是为了保证新版本设备与老版本设备之间的向后兼容性。

2. 参考

[PBAP 1.2] 6.3节: 明确指出当 Server 的 SDP 中没有 PbapSupportedFeatures 属性时,Client 不应在 OBEX CONNECT 请求中发送该 Header 字段。

3. 测试条件

  • The IUT and the Lower Tester have been paired.

  • Lower Tester: The Lower Tester is in discoverable and connectable mode. The Lower Tester
    does not have a PbapSupportedFeatures attribute in its SDP record.

  • IUT(被测设备)和 Lower Tester 已配对。

  • Lower Tester 是 PBAP Server,并处于:

    • Discoverable + Connectable 状态
    • 其 SDP 记录中不含 PbapSupportedFeatures 属性

4. 测试流程

  • Lower Tester 启动并广播自己的 SDP 信息(无 PbapSupportedFeatures 属性)。
  • IUT(PCE) 尝试发起 PBAP 连接。
  • 观察 IUT 的 OBEX CONNECT 请求内容

5.预期流程

OBEX CONNECT 请求中

  • 不得包含 PbapSupportedFeatures Header(0xFB)
  • 若包含此字段,则视为 FAIL

6.如何判断测试是否通过

抓包(如使用 Wireshark + Bluetooth HCI log)时,查看:

  • OBEX CONNECT 请求帧中是否包含 header ID 为 0xFB
  • 如果没有,则测试通过

2. 真实测试案例

Test case : PBAP/PCE/SSM/BV-10-C started
- version=0x0102  rfcommPsm=0x02  l2capPsm=0x1005  supportRepositories=0x0f  supportedFeatures=0x00000000 
- Final supported Feature 0
- OBEX Connect request contains SupportedFeatures ApplicationParameter
- Received HCI disconnection event. Handle = 0x0063-Final Verdict: FAIL
PBAP/PCE/SSM/BV-10-C finished

1. pts 侧

在这里插入图片描述

  1. 车机向 PTS 发起了 SDP
  2. 但是 PTS SDP中回复了两个 AttributeList

第一个 Attribute List如下
在这里插入图片描述

  • 支持协议 V1.2
  • 可以通过 l2cap psm: 0x1005 对应十进制:4101
  • 支持 supported features.
  • 可以通过 RFCOMM 通道 2 连接

第二个 Attribute List 如下
在这里插入图片描述

  • 支持协议 v.1.0
  • 可以通过 RFCOMM 通道 2 连接

这个 PTS 测试用例 PBAP/PCE/SSM/BV-10-C 的核心目的是验证 PBAP 客户端(PCE)在与旧版服务器通信时不会发送 PbapSupportedFeatures 特性位,以确保兼容性和标准符合性。

  • 也就是说 车机应该去连接 V1.0 这个。

2. 车机侧

在这里插入图片描述

# 车机收到第一个 UUID  也就是 v1.2
04-25 12:04:14.238917  6075  6075 I PbapClientStateMachine: Received UUID: 0000112f-0000-1000-8000-00805f9b34fb
04-25 12:04:14.239812  6075  6498 I PbapClientConnHandler: Handling Message = 1
# 使用 l2cap psm 0x1005 已经去连接了
04-25 12:04:14.239949  6075  6498 V PbapClientConnHandler: connectSocket: PSM: 410104-25 12:04:14.321776  6075  6498 D PbapClientConnHandler: Socket connected
04-25 12:04:14.321849  6075  6498 V PbapClientConnHandler: Start Obex Client Session
04-25 12:04:14.327761  6075  6498 D PbapClientConnHandler: Remote PbapSupportedFeatures 0
04-25 12:04:14.373370  6075  6498 D PbapClientConnHandler: Success = true# 车机收到 第二个 UUID  v1.0
04-25 12:04:14.239991  6075  6075 I PbapClientStateMachine: Received UUID: 0000112f-0000-1000-8000-00805f9b34fb04-25 12:04:14.373594  6075  6498 I PbapClientConnHandler: Handling Message = 1# 使用 rfcomm channle 2 去连, 连失败了。
04-25 12:04:14.373891  6075  6498 V PbapClientConnHandler: connectSocket: channel: 2
04-25 12:04:14.471800  6075  6498 E PbapClientConnHandler: Error while connecting socket
04-25 12:04:14.471800  6075  6498 E PbapClientConnHandler: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
  • 其实第一次 使用 v1.2 去连的时候,已经下发了 PbapSupportedFeatures , 所以 测试失败了。

3. 解决办法

通过上面的分析,我们可以清晰的看到, 车机在这个测试中,不应该处理 v1.2 的连接。 应该去连接 v1.0

  • 那我们就按照这个思路来做调整。

3. 代码分析

// android/app/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandler.java@Overridepublic void handleMessage(Message msg) {if (DBG) {Log.i(TAG, "Handling Message = " + msg.what);}switch (msg.what) {case MSG_CONNECT:mRetryTime = 0;case MSG_RECONNECT:mPseRec = (SdpPseRecord) msg.obj; // 将 SDP 赋值给 mPseRec/* To establish a connection, first open a socket and then create an OBEX session */if (connectSocket()) {} else {return;}if (connectObexSession()) {} else {}break;}return;}

整个 连接逻辑其实很简单,当SDP 结束后,会触发 PbapClientConnectionHandler 处理 MSG_CONNECT 消息。

  1. 调用 connectSocket()
  2. 如果第一步调用成功,调用 connectObexSession()
    synchronized boolean connectSocket() { try {/* Use BluetoothSocket to connect */if (mPseRec == null) {// BackWardCompatability: Fall back to create RFCOMM through UUID.if (VDBG) Log.v(TAG, "connectSocket: UUID: " + BluetoothUuid.PBAP_PSE.getUuid());mSocket =mDevice.createRfcommSocketToServiceRecord(BluetoothUuid.PBAP_PSE.getUuid());} else if (mPseRec.getL2capPsm() != L2CAP_INVALID_PSM) { // 由于 V1.2 中 L2cap 的 PCM 是  0x1005   对应十进制:4101  , 这里有限去连接  v1.2 if (SystemProperties.getBoolean("xxx.bluetooth.pts.pbap.pce.ssm.bv-10-c", false)) {Log.d(TAG, "pts test, pbap.pce.ssm.bv-10-c");} else {if (VDBG)Log.v(TAG, "connectSocket: PSM: " + mPseRec.getL2capPsm());mSocket = mDevice.createL2capSocket(mPseRec.getL2capPsm()); // 也就是 v1.2 是使用 l2cap 通道去 连接 obex 的。}} else {// 这里是 v1.0 的逻辑, 使用 rfcomm  channel:2 去连接 obexif (VDBG) Log.v(TAG, "connectSocket: channel: " + mPseRec.getRfcommChannelNumber());mSocket = mDevice.createRfcommSocket(mPseRec.getRfcommChannelNumber());}if (mSocket != null) {mSocket.connect();return true;} else {Log.w(TAG, "Could not create socket");}} catch (IOException e) {Log.e(TAG, "Error while connecting socket", e);}return false;}
  • 上面已经给出了处理办法,就是在当前测试环境中,不去连 v1.2 协议。

  • 第一步,只是 决定了 当前 上层obex 走那种通道, 是直接走 l2cap, 还是 走 rfcomm->l2cap 方式

那还有一个疑问, 测试提到的 PbapSupportedFeatures 是在哪里设置的呢?

继续看 第二步 connectObexSession

boolean connectObexSession() {boolean connectionSuccessful = false;try {if (VDBG) {Log.v(TAG, "Start Obex Client Session");}BluetoothObexTransport transport = new BluetoothObexTransport(mSocket);mObexSession = new ClientSession(transport);mObexSession.setAuthenticator(mAuth);HeaderSet connectionRequest = new HeaderSet();connectionRequest.setHeader(HeaderSet.TARGET, PBAP_TARGET);if (mPseRec != null) {if (DBG) {Log.d(TAG, "Remote PbapSupportedFeatures " + mPseRec.getSupportedFeatures());}ObexAppParameters oap = new ObexAppParameters();if (mPseRec.getProfileVersion() >= PBAP_V1_2) { // 如何是 v1.2 就会去添加 PbapSupportedFeatures, 如何是 1.0 跳过oap.add(BluetoothPbapRequest.OAP_TAGID_PBAP_SUPPORTED_FEATURES,PBAP_SUPPORTED_FEATURE);}oap.addToHeaderSet(connectionRequest);}HeaderSet connectionResponse = mObexSession.connect(connectionRequest); // 这里会去发起 obex 的连接请求connectionSuccessful =(connectionResponse.getResponseCode() == ResponseCodes.OBEX_HTTP_OK);if (DBG) {Log.d(TAG, "Success = " + Boolean.toString(connectionSuccessful));}} return connectionSuccessful;}

4.整改后的

在这里插入图片描述

# 收到 sdp
04-25 13:22:04.301633  5766  5766 I PbapClientStateMachine: Received UUID: 0000112f-0000-1000-8000-00805f9b34fb
04-25 13:22:04.302432  5766  5766 I PbapClientStateMachine: Received UUID: 0000112f-0000-1000-8000-00805f9b34fb# v1.2 连接失败
04-25 13:22:04.303335  5766  6197 I PbapClientConnHandler: Handling Message = 1
04-25 13:22:04.303911  5766  6197 D PbapClientConnHandler: pts test, pbap.pce.ssm.bv-10-c
04-25 13:22:04.304104  5766  6197 W PbapClientConnHandler: Could not create socket 
04-25 13:22:04.304145  5766  6197 W PbapClientConnHandler: Socket CONNECT Failure # v1.0 连接成功
04-25 13:22:04.304193  5766  6197 I PbapClientConnHandler: Handling Message = 1
04-25 13:22:04.304238  5766  6197 V PbapClientConnHandler: connectSocket: channel: 2
04-25 13:22:04.419481  5766  6197 D PbapClientConnHandler: Socket connected
04-25 13:22:04.419564  5766  6197 V PbapClientConnHandler: Start Obex Client Session
04-25 13:22:04.425265  5766  6197 D PbapClientConnHandler: Remote PbapSupportedFeatures 0
04-25 13:22:04.483244  5766  6197 D PbapClientConnHandler: Success = true
04-25 13:22:04.483363  5766  6197 I PbapClientConnHandler: Handling Message = 257
04-25 13:22:04.483404  5766  6197 D PbapClientConnHandler: pts test, pbap.pce.ssm.bv-10-c

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量删除OpenStack实例

在Linux终端实现批量删除OpenStack实例,支持并发删除、安全确认、重试机制、优先清理运行中实例 #!/bin/bash # # 增强版 OpenStack 删除实例脚本 # 功能:支持并发删除、安全确认、重试机制、优先清理运行中实例 # 更新:2025年4月30日 # ##…

# 基于 Python 和 jieba 的中文文本自动摘要工具

基于 Python 和 jieba 的中文文本自动摘要工具 在信息爆炸的时代,快速准确地提取文本核心内容变得至关重要。今天,我将介绍一个基于 Python 和 jieba 的中文文本自动摘要工具,帮助你高效地从长文本中提取关键信息。 一、背景与需求 在处理…

Seaborn数据可视化库

一、Seaborn介绍:基于Matplotlib的Python数据可视化库,专注绘制统计图形,简化可视化过程,提供高级接口和美观默认主题。 二、安装与导入 1.安装:可使用pip install seaborn或conda install seaborn,也可使…

机器视觉2D码垛和机器视觉3D码垛的区别

机器视觉3D码垛是一种结合3D视觉技术和工业机器人的自动化系统,主要用于在复杂环境中精准识别、定位并堆叠(码垛)各种形状、尺寸的物体。它通过3D传感器(如激光雷达、结构光相机、双目视觉等)获取物体的三维空间信息,并结合算法规划机器人的抓取路径和码放策略,实现高效…

Python魔法函数深度解析

一、魔法函数是什么? 魔法函数(Magic Methods)是Python中以双下划线(__xx__)包裹的特殊方法,它们为类提供了一种与Python内置语法深度集成的能力。这些方法由解释器自动调用,无需显式调用&…

C++负载均衡远程调用学习之自定义内存池管理

目录 1.内存管理_io_buf的结构分析 2.Lars_内存管理_io_buf内存块的实现 3.buf总结 4.buf_pool连接池的单例模式设计和基本属性 5.buf_pool的初始化构造内存池 6.buf_pool的申请内存和重置内存实现 7.课前回顾 1.内存管理_io_buf的结构分析 ## 3) Lars系统总体架构 ​ …

流水线问题(算法设计)C++

目录 一、需求分析 1.1 问题描述 1.2 数据需求 1.3 功能需求 1.4 开发环境 二、概要设计 2.1 抽象数据类型 ADT 的定义 2.2 系统的主要功能模块 2.3 功能模块联系图 三、详细设计 3.1 数据结构设计 3.2 主要算法 四、系统运行及结果分析 1. 用户界面 2. 程序运行…

从实列中学习linux shell4: shell 脚本中 $0 $1 $2 $3 >> 以及 awk 都是干啥的?

在 Linux Shell 脚本中,这些符号和工具的功能如下: 一、位置参数 $0 $1 $2 $3 符号功能说明示例$0脚本自身的文件名若执行 ./test.sh,则 $0 值为 ./test.sh$1第一个参数执行 ./test.sh apple 时,$1 值为 "apple"$2第二…

TM1668芯片学习心得三

一、键扫数据储存地址如下所示,先发读键命令后,开始读取按键数据BYTE1-BYTE5字节,读数据从低位开始输出,其中B6和B7位为无效位,此时芯片输出为0。芯片K和KS引脚对应的按键按下时,相对应的字节内的 BIT位为1…

MySQL 基本查询(一)

文章目录 Create(insert)指定列的单行插入和全列插入多行全列插入和指定列的多行插入如果主键存在,要插入替换存在的值replace 基本select全列查询指定列查询where子句where子句案例语文成绩在 [80, 90] 分的同学及语文成绩数学成绩是 58 或者 59 或者 98 或者 99 分…

LeetCode路径总和系列问题解析:I、II、III的解决方案与优化

文章目录 引言一、路径总和 I(LeetCode 112)问题描述方法思路Java代码实现复杂度分析 二、路径总和 II(LeetCode 113)问题描述方法思路Java代码实现复杂度分析 三、路径总和 III(LeetCode 437)问题描述方法…

NFC 碰一碰发视频贴牌技术,音频功能的开发实践与技术解析

在数字化营销与信息交互场景中,NFC 碰一碰技术凭借其便捷性和高效性,成为快速传递多媒体内容的新选择。通过 NFC 实现视频音频的快速传输,不仅能提升用户体验,还能为各类场景带来创新应用。本文将深入探讨该功能开发过程中的关键技…

跨境电商生死劫:IP筛查三法则破解封号魔咒

一、血泪数据:90%封号案源于IP污染 跨境电商平台风控系统持续升级,2023年亚马逊全球封号案例中,67%涉及账号关联(Marketplace Pulse数据),其中IP问题占比高达91%。更触目惊心的是: 新号存活率&…

MIPS架构详解:定义、应用与其他架构对比

一、MIPS架构的定义 MIPS(Microprocessor without Interlocked Pipeline Stages) 是一种经典的精简指令集(RISC)处理器架构,由斯坦福大学John Hennessy团队于1981年提出,强调高效流水线设计和硬件简化。 核…

第十六届蓝桥杯 2025 C/C++组 脉冲强度之和

目录 题目: 题目描述: 题目链接: 思路: 思路详解: 代码: 代码详解: 题目: 题目描述: 题目链接: P12338 [蓝桥杯 2025 省 B/Python B 第二场] 脉冲强度…

从Ping到iperf3:深度实战无线网络压测与优化指南

以下是测试无线网络稳定性的详细步骤与工具指南,涵盖信号质量、吞吐量、干扰排查等关键维度: 一、基础信号质量测试 1. 信号强度与覆盖测试 工具:手机APP(WiFi Analyzer、NetSpot)或笔记本(Acrylic WiFi&a…

MySQL 连接池 (Pool) 常用方法详解

MySQL 连接池 (Pool) 常用方法详解 1. 创建连接池 首先需要创建连接池实例: const mysql require(mysql2/promise); // 使用Promise版本const pool mysql.createPool({host: localhost,user: root,password: password,database: test,waitForConnections: true…

大型连锁酒店集团数据湖应用示例

目录 一、应用前面临的严峻背景 二、数据湖的精细化构建过程 (一)全域数据整合规划 (二)高效的数据摄取与存储架构搭建 (三)完善的元数据管理体系建设 (四)强大的数据分析平台…

GNU gettext 快速上手

文章目录 1.简介2.核心概念国际化 (i18n)本地化 (l10n)POT 文件PO 文件MO 文件文本域翻译函数 3.主要组件4.使用示例参考文献 1.简介 GNU gettext 是一套用于软件国际化(internationalization,i18n)和本地化(localization&#x…

分享:VTK版本的选择 - WPF空域问题

在早期版本中,ActiViz 对 Windows Presentation Foundation (WPF) 框架的支持是通过 WindowsFormHost 组件实现的,这种方式依赖于 WindowsForm 和 WPF 的互操作性。然而,这种方法存在一个众所周知的“空域问题”(airspace issue&a…