【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: 4101

04-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-00805f9b34fb

04-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

    @Override
    public 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 去连接 obex
                if (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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值