BT_蓝牙电话本数据包分析

1,388 阅读29分钟

基于Android P版本分析

协议简述

蓝牙电话应用不但需要HFP协议来支持打电话的功能,同时在很多车载蓝牙应用中,都支持查看通讯录和通话记录等信息,而这一部分的所涉及到的协议为PBAP;

PBAP协议架构.png

PBAP

PBAP:(Phone Book Access Profile)电话本访问协议,是一种基于OBEX的上层协议,该协议可以同步手机这些具有电话本功能设备上的通讯录和通话记录等信息;

OBEX

Object Exchange,对象交换协议,来源与红外通讯协议,但又不局限与具体的传输方式,后来被蓝牙组织SIG吸纳其中部分并进行优化处理作为蓝牙协议中的OBEX层用于蓝牙设备间的文件数据传输,如蓝牙传输文件(OPP)、同步电话簿(PBAP)和同步短信(MAP)等场景下都是以OBEX协议组织相关数据进行传输的;

OBEX协议有两种角色:Server和Client,通过request-response(请求-响应)形式进行交互,即客户端Client进行请求,服务端Server响应客户端请求的方式传输数据对象;

应用于PBAP协议中,Client只能进行数据的读取操作,不能对源数据进行修改,保证了源数据的安全性;

PBAP协议栈

PBAP协议.png

PBAP应用层协议处于最上层,之后就是数据格式处理方式,由于通讯录在手机中都是以vCard的格式存储的,所以这边为vCard的数据处理格式。在往下就是通过OBEX协议层联通蓝牙协议栈中的RFCOMM,最后通过统一的数据传输通道L2CAP链路发送数据;

vCard格式
BEGIN:VCARD\r\n
VERSION:3.0\r\n
N:;胡x;;;\r\n
FN:胡x\r\n
TEL;TYPE=CELL:610xxx\r\n
END:VCARD\r\n
  • BEGIN:VCARD:一组联系人信息开始标志
  • END:VCARD:结束标志
  • VERSION:版本
  • FN:姓名
  • TEL;TYPE=CELL:联系人联系方式

上述的参数为必要的,有些参数是可选项,例如:住址、邮件等信息;

当前vCard的版本有vCard 2.1 和 vCard 3.0 两个版本,所以PSE需要两种数据格式都支持,同步数据时根据PCE请求的哪种格式就以哪种格式封装数据进行传输。但是无论是哪种格式,vCard属性内容字符集使用唯一的字符编码utf-8格式进行编码转换;

协议栈中定义了两种角色:

  • PSE:Phone Book Server Equipment,拥有电话本源数据的设备,作为Server,比如手机;
  • PCE:Phone Book Client Equipment,向PSE端请求电话本源数据的设备,作为Client,例如车机;

因为PBAP协议是基于OBEX协议实现的,那PBAP协议获取数据的方式也是通过request-response形式传输的;

PSE & PCE 功能
FeatureSupport by the PCESupport by the PSE
DownloadC1M
BrowsingC1M
Database IdentifierC3M
Folder Version CountersOM
vCard SelectingOM
Enhanced Missed CallsOO
X-BT-UCI vCard PropertyOO
X-BT-UID vCard PropertyOO
Referencing ContactsC2C2
Contact Image Default FormatXM
  • C1:至少支持其中一种
  • C2:如果支持' X-BT-UID vCard Property ',则可选,否则不支持不可选
  • C3:如果支持“Folder Version Counters” 或 “X-BT-UID vCard Property”,则必选,否则可选
  • O:可选
  • M:必选,必须支持

我们常使用到的功能为:Download和Browsing;我们分析一下;

Download

Download功能可以将电话簿对象的全部内容同步到PCE,从而PCE端获取到数据后完全可以通过蓝牙电话等应用程序将数据显示到界面,一样可以达到滚动浏览电话簿信息的目的;

Download这个功能特别是用于PSE端存储的电话簿容量相对较大,PCE设备通常从PSE端下载这些大容量数据并在其本地存储整个电话簿的场景。

FeatureFunctionSupport by the PCESupport by the PSE
Phone Book Download featurePullPhonebookMM

协议层提供了PullPhonebook函数,这个函数就是用来下载自己感兴趣的电话簿对象;

PullPhonebook Data Format

由于PBAP协议是基于OBEX的,所以PullPhonebook函数顾名思义也是采用request-response这种一问一答的形式传输数据;

请求格式如下:

Field / HeaderNameValueStatus
FieldOpcodeGET(0x03 or 0x83)M
FieldPacket LengthVariesM
HeaderConnection IDVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderNameObject name (*.vcf)M
HeaderType"x-bt/phonebook"M
HeaderApplication Parameters
- PropertySelectorVariesO
- FormatVariesO
- MaxListCountVariesO
- ListStartOffsetVariesO
- ResetNewMissedCallsVariesC3
- vCardSelectorVariesC4
- vCardSelectorOperatorVariesC5
  • Opcode:操作码,可以理解为标识码,和Type参数组合形成了唯一标识;
  • Connection ID:PBAP连接指令中PSE回复的连接ID 号;
  • Name:表明了需要同步哪种数据;
  • Type:对应了Function,基本上每一个Function对应一个Type,除了SetPhonebook Function;
  • Application Parameters:应用设置的参数,PSE的回复数据会根据这些参数来组装回复data数据,其中就包括了PropertySelector、Format、MaxListCount等参数信息;
  • MaxListCount:本次 GET 获取的最大List Count;
  • ListStartOffset:本次 GET 开始的List Offset;

响应格式如下:

Field / HeaderNameValueStatus
FieldResponse0x09 or 0xA0 or Error CodeM
FieldPacket LengthVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderApplication Parameters
- PhonebookSizeVariesC3
- NewMissedCallsVariesC4
- PrimaryFolderVersionVariesC5
- SecondaryFolderVersionVariesC5
- DatabaseIdentifierVariesC6
HeaderBody/End of BodyvCard object(s)C7
  • PhonebookSize:Name个数,当MaxListCount = 0时,返回Name的总个数;
  • NewMissedCalls:新增的未接电话
  • Body/End or Body:请求中MaxListCount != 0时,返回Name对应的数据,回复数据中的vCard对象只应包含使用属性选择器Attribute Selector参数指示的属性,并且应使用格式Format参数指示的格式组装数据;
Application Parameters Header

该数据是由一组不同的TAG组成的整体的Application Parameters;

ValueTag IDLengthPossible Values
Order0x011 byte0x00 = indexed 0x01 = alphanumeric 0x02 = phonetic
Search Value0x02variableText
SearchProperty0x031 byte0x00 = Name 0x01 = Number 0x02 = Sound
MaxListCount0x042 bytes0x0000 to 0xFFFF
ListStartOffset0x052 bytes0x0000 to 0xFFFF
PropertySelector0x068 bytes64 bits mask
Format0x071 byte0x00 = 2.1 0x01 = 3.0
PhonebookSize0x082 bytes0x0000 to 0xFFFF
NewMissedCalls0x091 byte0x00 to 0xFF
PrimaryVersionCounter0x0A16 bytes0 to (2 128 – 1)
SecondaryVersionCounter0x0B16 bytes0 to (2 128 – 1)
vCardSelector0x0C8 bytes64 bits mask
DatabaseIdentifier0x0D16 bytes0 to (2 128 – 1)
vCardSelectorOperator0x0E1 byte0x00 = OR 0x01 = AND
ResetNewMissedCalls0x0F1 byte0x01 = Reset
PbapSupportedFeatures0x104 bytesBit 0 = Download Bit 1 = Browsing Bit 2 = Database Identifier Bit 3 = Folder Version Counters Bit 4 = vCard Selecting Bit 5 = Enhanced Missed Calls Bit 6 = X-BT-UCI vCard Property Bit 7 = X-BT-UID vCard Property Bit 8 = Contact Referencing Bit 9 = Default Contact Image Format Bit 10 ~ 31 Reserved 1
  • PropertySelector:用于指示请求的vCard object中应该包含的属性,PSE根据这些属性来组织恢复的Body/End of Body Header中包含的数据,PCE只能使用此Header接收所请求的vCard所需要内容,PSE不得回复任何其他性能数据,除非PCE有其他要求;

PropertySelector的值是由一个64位的数据组成,所以每一位都代表了一种属性,如果PCE请求的电话簿需要包含对应的数据,就将该数据对应在PropertySelector的二进制位设置为true(1)。具体每一位的含义见下图:

PBAP_Property Mask.png

流程图

电话簿下载流程图.png

这里有一个需要注意的,PCE和PSE的服务连接不是一直保持的,只有在同步Phone Book的时候,服务保持连接,同步完成之后,就会断开;

Browsing

FeatureFunctionSupport by the PCESupport by the PSE
Phone Book Browsing FeatureSetPhonebookMM
PullvCardListingMM
PullvCardEntryMM

  • SetPhonebook:选择感兴趣的Phone Object
  • PullvCardListing:client使用该Function获取感兴趣的Phone Object 列表
  • PullvCardEntry:client使用该Function获取感兴趣的Phone Object(单个)
SetPhonebook Data Format

请求格式:

Field / HeaderNameValueStatus
FieldOpcodeSETPATH (0x05)M
FieldPacket LengthVariesM
FieldFlagsUp / Down / RootM
FieldConstantReserved (0)M
HeaderConnection IDVariesM
HeaderNameName of the folderO

响应格式:

Field / HeaderNameValueStatus
FieldResponse Code0xA0 or Error CodeM
FieldPacket Length3M
PullvCardListing Data Format

请求格式:

Field / HeaderNameValueStatus
FieldOpcodeGET(0x03 or 0x83)M
FieldPacket LengthVariesM
HeaderConnection IDVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderNameName of the folderM
HeaderType"x-bt/vcard-listing"M
HeaderApplication Parameters
- OrderVariesO
- SearchValueVariesO
- SearchPropertyVariesC3
- MaxListCountVariesO
- ListStartOffsetVariesO
- ResetNewMissedCallsVariesC4
- vCardSelectorVariesC5
- vCardSelectorOperatorVariesC6

响应格式:

Field / HeaderNameValueStatus
FieldResponse Code0x09 or 0xA0 or Error CodeM
FieldPacket LengthVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderApplication Parameters
- PhonebookSizeVariesC3
- NewMissedCallsVariesC4
- PrimaryFolderVersionVariesC5
- SecondaryFolderVersionVariesC5
- DatabaseIdentifierVariesC6
HeaderBody/End of BodyvCard object(s)C7
PullvCardEntry Data Format

请求格式:

Field / HeaderNameValueStatus
FieldOpcodeGET(0x03 or 0x83)M
FieldPacket LengthVariesM
HeaderConnection IDVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderNameObject name (*.vcf) or X-BT-UID (X-BT-UID)M
HeaderType"x-bt/vcard"M
HeaderApplication Parameters
- PropertySelectorVariesO
- FormatVariesO

响应格式:

Field / HeaderNameValueStatus
FieldResponse Code0x09 or 0xA0 or Error CodeM
FieldPacket LengthVariesM
HeaderSingle Response Mode0x01C1
HeaderSingle Response Mode Param0x01C2
HeaderApplication Parameters
- DatabaseIdentifierVariesC3
HeaderBody/End of BodyvCard objectC4
流程图

Phone_Book Browsing流程图.png

vcf文件

Download和Browsing功能描述完成之后,我们需要知道,所有的Phone Object信息都是来自于PSE端,而在PSE端保存Phone Object的方式或者是路径可能有很多;

数据存储形式.png

  • 存储设备

    • 手机:telecom/xxx.vcf
    • SIM卡:SIM1/telecom/xxx.vcf

无论是哪种存储方式,其对应都有相同的数据存储类型,例如通讯录、通讯记录,而在通讯记录中,又可以分为:来电、去电、未接来电、所有通讯记录。同时电话簿还提供了两个功能:快速拨号和收藏联系人;

上述描述的分类方式,对应了PSE端存储文件格式;

Phone ObjectASFormatDesc
Phone Book Objectpbpb.vcf通讯录
Incoming Calls History Objectichich.vcf来电通话记录
Outgoing Calls History Objectochoch.vcf去电通话记录
Missed Calls History Objectmchmch.vcf未接来电通话记录
Commbined Calls History Objectcchcch.vcf所有的通话记录
Speed-Dial Objectspdspd.vcf快速拨号
Favorite Contacts Objectfavfav.vcf收藏通讯录

协议数据包分析

在PBAP协议同步通讯录和通讯记录中,都是基于OBEX协议实现的,PBAP协议作为了应用层协议;

同步通讯录

获取联系人数量 - telecom

Request:

Frame 485: 84 bytes on wire (672 bits), 84 bytes captured (672 bits)
…………………………
OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .000 0011 = Opcode: Get (0x03)
    1... .... = Final Flag: True
    Packet Length: 70
    [Response in Frame: 489]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Name: "telecom/pb.vcf"
            Header Id: Name (0x01)
                00.. .... = Encoding: Null terminated Unicode text, length prefixed with 2 byte Unsigned Integer (0x0)
                ..00 0001 = Meaning: Name (0x01)
            Length: 33
            Name: telecom/pb.vcf
        Type: "x-bt/vcard-listing"
            Header Id: Type (0x42)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 0010 = Meaning: Type (0x02)
            Length: 22
            Type: x-bt/vcard-listing
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 7
            Parameter: Max List Count
                Parameter Id: Max List Count (0x04)
                Parameter Length: 2
                Max List Count: 0 (0x0000)
  • Profile:PBAP (4),上层应用层协议为PBAP,OBEX协议的上层应用层协议除了PBAP,还有OPP、MAP协议;

  • Opcode:操作码,Get (0x03),即Request对应的code为Get;

  • Packet Length:70

  • Response in Frame:该request frame-485对应的Response frame为489;

  • Header - Connection Id = 1:PBAP连接指令中PSE回复的连接ID 号;

  • Header - Name = "telecom/pb.vcf":代表了访问的通讯录路径;

  • Header - Type = "x-bt/vcard-listing":代表了该Request对应的Function为PullvCardListing;

  • Header - Application Parameters

    • Parameter Id = 0x04:该ID 对应了Max List Count
    • Parameter - Max List Count = 0:在MaxListCount = 0 的情况下,Response返回的PhonebookSize为Name对应路径下所有通讯人的Count;

Response:

Frame 489: 29 bytes on wire (232 bits), 29 bytes captured (232 bits)
………………………………
OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .010 0000 = Response Code: Success (0x20)
    1... .... = Final Flag: True
    Packet Length: 15
    [Request in Frame: 485]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 7
            Parameter: Phonebook Size
                Parameter Id: Phonebook Size (0x08)
                Parameter Length: 2
                Phonebook Size: 102 (0x0066)
  • Response Code:Success

  • Header - Connection Id = 1:对应了上述Request 的Connection Id;

  • Header - Application Parameters

    • Parameter Id = 0x08:该Id代表了Phonebook Size
    • Parameter - Phonebook Size = 102:代表了Name对应telecom/pb.vcf的总数
获取联系人数量 - SIM1/telecom

Request:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .000 0011 = Opcode: Get (0x03)
    1... .... = Final Flag: True
    Packet Length: 80
    [Response in Frame: 492]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Name: "SIM1/telecom/pb.vcf"
            Header Id: Name (0x01)
                00.. .... = Encoding: Null terminated Unicode text, length prefixed with 2 byte Unsigned Integer (0x0)
                ..00 0001 = Meaning: Name (0x01)
            Length: 43
            Name: SIM1/telecom/pb.vcf
        Type: "x-bt/vcard-listing"
            Header Id: Type (0x42)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 0010 = Meaning: Type (0x02)
            Length: 22
            Type: x-bt/vcard-listing
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 7
            Parameter: Max List Count
                Parameter Id: Max List Count (0x04)
                Parameter Length: 2
                Max List Count: 0 (0x0000)
  • Header - Name = "SIM1/telecom/pb.vcf":访问路径为SIM卡中的联系人总数;
  • Parameter - Max List Count = 0:获取SIM中联系人总数;

Response:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .010 0000 = Response Code: Success (0x20)
    1... .... = Final Flag: True
    Packet Length: 11
    [Request in Frame: 490]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        End Of Body
            Header Id: End Of Body (0x49)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1001 = Meaning: End Of Body (0x09)
            Length: 3
            Value: <MISSING>
  • End or Body:

    • MaxListCount != 0:返回Name对应的数据,回复数据中的vCard对象只应包含使用属性选择器Attribute Selector参数指示的属性,并且应使用格式Format参数指示的格式组装数据;
    • MaxListCount == 0:直接返回,代表没有获取的数据;
同步 All 联系人

Request:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .000 0011 = Opcode: Get (0x03)
    1... .... = Final Flag: True
    Packet Length: 83
    [Response in Frame: 553]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Name: "telecom/pb.vcf"
            Header Id: Name (0x01)
                00.. .... = Encoding: Null terminated Unicode text, length prefixed with 2 byte Unsigned Integer (0x0)
                ..00 0001 = Meaning: Name (0x01)
            Length: 33
            Name: telecom/pb.vcf
        Type: "x-bt/phonebook"
            Header Id: Type (0x42)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 0010 = Meaning: Type (0x02)
            Length: 18
            Type: x-bt/phonebook
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 24
            Parameter: Max List Count
                Parameter Id: Max List Count (0x04)
                Parameter Length: 2
                Max List Count: 101 (0x0065)
            Parameter: List Start Offset
                Parameter Id: List Start Offset (0x05)
                Parameter Length: 2
                List Start Offset: 1 (0x0001)
            Parameter: Filter
                Parameter Id: Filter (0x06)
                Parameter Length: 8
                Filter: 0x00000000
                    .... .... .... .... .... .... .000 0000 = Reserved: 0x00
                    .... .... .... .... .... .... 0... .... = Proprietary Filter: False
                    0000 0000 0000 0000 0000 0000 .... .... = Reserved for Proprietary Filter Usage: 0x000000
                Filter: 0x008001af, vCard Version, Formatted Name, Structured Presentation of Name, Associated Image or Photo, Delivery Address, Telephone Number, Electronic Mail Address, Nickname
                    .... .... .... .... .... .... .... ...1 = vCard Version: True
                    .... .... .... .... .... .... .... ..1. = Formatted Name: True
                    .... .... .... .... .... .... .... .1.. = Structured Presentation of Name: True
                    .... .... .... .... .... .... .... 1... = Associated Image or Photo: True
                    .... .... .... .... .... .... ...0 .... = Birthday: False
                    .... .... .... .... .... .... ..1. .... = Delivery Address: True
                    .... .... .... .... .... .... .0.. .... = Delivery: False
                    .... .... .... .... .... .... 1... .... = Telephone Number: True
                    .... .... .... .... .... ...1 .... .... = Electronic Mail Address: True
                    .... .... .... .... .... ..0. .... .... = Electronic Mail: False
                    .... .... .... .... .... .0.. .... .... = Time Zone: False
                    .... .... .... .... .... 0... .... .... = Geographic Position: False
                    .... .... .... .... ...0 .... .... .... = Job: False
                    .... .... .... .... ..0. .... .... .... = Role within the Organization: False
                    .... .... .... .... .0.. .... .... .... = Organization Logo: False
                    .... .... .... .... 0... .... .... .... = vCard of Person Representing: False
                    .... .... .... ...0 .... .... .... .... = Name of Organization: False
                    .... .... .... ..0. .... .... .... .... = Comments: False
                    .... .... .... .0.. .... .... .... .... = Revision: False
                    .... .... .... 0... .... .... .... .... = Pronunciation of Name: False
                    .... .... ...0 .... .... .... .... .... = Uniform Resource Locator: False
                    .... .... ..0. .... .... .... .... .... = Unique ID: False
                    .... .... .0.. .... .... .... .... .... = Public Encryption Key: False
                    .... .... 1... .... .... .... .... .... = Nickname: True
                    .... ...0 .... .... .... .... .... .... = Categories: False
                    .... ..0. .... .... .... .... .... .... = Product ID: False
                    .... .0.. .... .... .... .... .... .... = Class Information: False
                    .... 0... .... .... .... .... .... .... = String Used For Sorting Operations: False
                    ...0 .... .... .... .... .... .... .... = Timestamp: False
                    000. .... .... .... .... .... .... .... = Reserved: 0x0
            Parameter: Format
                Parameter Id: Format (0x07)
                Parameter Length: 1
                Format: 3.0 (0x01)
  • Name = "telecom/pb.vcf":加载手机中的联系人;

  • Type = "x-bt/phonebook":对应了Download Feature中的PullPhonebook Function;

  • Application Parameters

    • Parameter - Max List Count = 101:手机中联系人最大的count = 101;

    • Parameter - List Start Offset = 1:代表了从通讯录的第一个位置开始加载;

    • Parameter - Filter:过滤器,Parameter Id = 0x06,对应Application Parameters表格中其实为PropertySelector

      其中需要获取vCard Version, Formatted Name, Structured Presentation of Name, Associated Image or Photo, Delivery Address, Telephone Number, Electronic Mail Address, Nickname信息;

    • Parameter - Format = 3.0:这个其实是根据vCard Version来决定的,目前使用 version = 3.0 的Format;

其中我们涉及到了Filter,在这个模块中,规定了哪些属性是需要过滤,哪些属性是需要保留:

NameFilterNameFilter
VERSIONtrueNOTEfalse
FNtrueREVfalse
NtrueSOUNDfalse
PHOTOtrueURLfalse
BDAYfalseUIDfalse
ADRtrueKEYfalse
LABELfalseNICKNAMEfalse
TELtrueCATEGORIESfalse
EMAILtruePROIDfalse
MAILERfalseCLASSfalse
TZfalseSORT-STRINGfalse
GEOfalseX-IRMC-CALL-DATETIMEfalse
TITLEfalseX-BT-SPEEDDIALKEYfalse
ROLEfalseX-BT-UCIfalse
LOGOfalseX-BT-UIDfalse
AGENTfalsePROPRIETARY FILTERfalse
ORGfalse

Response:

响应过程分为两个部分:

  • 数据帧连续响应上报;
  • 汇总信息及数据文本信息上报;
数据帧连续响应上报
Frame 495: 1004 bytes on wire (8032 bits), 1004 bytes captured (8032 bits)
…………………………
OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    Reassembled OBEX in frame: 553
    Data (990 bytes)
        Data: a0ac17cb0000000149ac0f424547494e3a56434152440d0a…
        [Length: 990]

这一帧数据为同步指令下发后上报的第一帧数据,在Data参数中描述了联系人信息;

汇总信息及数据文本信息上报

上述的过程中通过PropertySelector设置了属性可见性;

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    [45 OBEX Fragments (44055 bytes): #495(990), #496(990), #497(990), #498(990), #499(990), #500(990), #502(990), #503(990), #505(990), #506(990), #507(990), #508(990), #510(990), #512(990), #513(990), #514(990), #515(990), #516(990), #518(990]
        [Frame: 495, payload: 0-989 (990 bytes)]
        [Frame: 496, payload: 990-1979 (990 bytes)]
        …………………………
        [Frame: 553, payload: 43560-44054 (495 bytes)]
        [Fragment count: 45]
        [Reassembled OBEX length: 44055]
    .010 0000 = Response Code: Success (0x20)
    1... .... = Final Flag: True
    Packet Length: 44055
    [Request in Frame: 493]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        End Of Body
            Header Id: End Of Body (0x49)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1001 = Meaning: End Of Body (0x09)
            Length: 44047
            Value: 424547494e3a56434152440d0a56455253494f4e3a332e30…
    Line-based text data: x-bt/phonebook (1088 lines)
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        N:;胡#;;;\r\n
        FN:胡#\r\n
        TEL;TYPE=CELL:610xxx\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        N:;杜##;;;\r\n
        FN:杜##\r\n
        TEL;TYPE=CELL:184xxxxxxxx\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        N:;太####;;;\r\n
        FN:太####\r\n
        TEL;TYPE=CELL:156xxxxxxxx\r\n
        TEL;TYPE=CELL:135xxxxxxxx\r\n
        END:VCARD\r\n
        
        …………………………
        
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        N:;郭##;;;\r\n
        FN:郭##\r\n
        TEL;TYPE=CELL:135xxxxxxxx\r\n
        PHOTO;ENCODING=B;TYPE=JPEG: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\r\n
        \r\n
        END:VCARD\r\n
        
        …………………………

这一块就是响应PullPhonebook Function的结果;

  • OBEX Fragments:代表了数据帧,每一帧数据中有可能包含多组联系人方式,第一帧数据就是从Frame 495开始;
  • Fragment count:读取所有联系人所使用的Frame count;
  • Response Code:Success;
  • End Of Body:因为在Request中 MaxListCount != 0,所以其中的value不是标识,而是按照请求的指令组织的数据响应;
  • Line-based text data:数据响应的文本内容;

接下来就是vCard Object内容的描述了;

  • BEGIN:VCARD:一组联系人信息开始标志
  • END:VCARD:结束标志
  • VERSION:版本
  • FN:姓名
  • TEL;TYPE=CELL:联系人联系方式
  • PHOTO;ENCODING=B;TYPE=JPEG:联系人头像

我们在上述过程中,其实对很多属性都进行了保留,但是需要确保手机联系人信息中包含这些属性,例如联系人头像这一属性,很多联系人方式中并没有设置,所以同步下来的信息中没有该属性的描述,只有在极少数的联系人信息中设置过,所以会同步头像信息;

同步 SIM 联系人方式和同步手机联系人方式一样,只是在SIM卡中没有保存联系人,所有获取到的信息为空,Parameter - End Of Body的value标识为;

同步通话记录

获取 All CCH Count

同步所有的通话记录;

Request:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .000 0011 = Opcode: Get (0x03)
    1... .... = Final Flag: True
    Packet Length: 72
    [Response in Frame: 566]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Name: "telecom/cch.vcf"
            Header Id: Name (0x01)
                00.. .... = Encoding: Null terminated Unicode text, length prefixed with 2 byte Unsigned Integer (0x0)
                ..00 0001 = Meaning: Name (0x01)
            Length: 35
            Name: telecom/cch.vcf
        Type: "x-bt/vcard-listing"
            Header Id: Type (0x42)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 0010 = Meaning: Type (0x02)
            Length: 22
            Type: x-bt/vcard-listing
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 7
            Parameter: Max List Count
                Parameter Id: Max List Count (0x04)
                Parameter Length: 2
                Max List Count: 0 (0x0000)
  • Name = "telecom/cch.vcf":代表了需要加载或访问的数据为所有通话记录;

  • Type = "x-bt/vcard-listing":获取感兴趣的Phone Object 列表;

  • Application Parameters

    • Parameter - Max List Count = 0:= 0的情况下,表明本次Request获取的是符合条件的所有信息的Count;

Response:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .010 0000 = Response Code: Success (0x20)
    1... .... = Final Flag: True
    Packet Length: 15
    [Request in Frame: 562]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 7
            Parameter: Phonebook Size
                Parameter Id: Phonebook Size (0x08)
                Parameter Length: 2
                Phonebook Size: 1631 (0x065f)
  • Phonebook Size = 1631:代表所有的通话记录信息为1631条;
同步 All CCH

Request:

OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    .000 0011 = Opcode: Get (0x03)
    1... .... = Final Flag: True
    Packet Length: 71
    [Response in Frame: 578]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        Name: "telecom/cch.vcf"
            Header Id: Name (0x01)
                00.. .... = Encoding: Null terminated Unicode text, length prefixed with 2 byte Unsigned Integer (0x0)
                ..00 0001 = Meaning: Name (0x01)
            Length: 35
            Name: telecom/cch.vcf
        Type: "x-bt/phonebook"
            Header Id: Type (0x42)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 0010 = Meaning: Type (0x02)
            Length: 18
            Type: x-bt/phonebook
        Application Parameters
            Header Id: Application Parameters (0x4c)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1100 = Meaning: Application Parameters (0x0c)
            Length: 10
            Parameter: Max List Count
                Parameter Id: Max List Count (0x04)
                Parameter Length: 2
                Max List Count: 50 (0x0032)
            Parameter: Format
                Parameter Id: Format (0x07)
                Parameter Length: 1
                Format: 3.0 (0x01)
  • Name = "telecom/cch.vcf":被访问加载的数据文件路径;

  • Type = "x-bt/phonebook":同步通话记录;

  • Application Parameters

    • Parameter - Max List Count = 50:本次Request需要同步的最大的信息数
    • Parameter - Format:版本格式为3.0格式;

Response:

Frame 578: 61 bytes on wire (488 bits), 61 bytes captured (488 bits)
Bluetooth
    [Source: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
    [Destination: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
Bluetooth HCI H4
    [Direction: Rcvd (0x01)]
    HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
    .... 0000 0000 0010 = Connection Handle: 0x002
    ..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
    00.. .... .... .... = BC Flag: Point-To-Point (0)
    Data Total Length: 56
    Data
    [Connect in frame: 109]
    [Source BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
    [Source Device Name: dupz]
    [Source Role: Slave (2)]
    [Destination BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
    [Destination Device Name: HAVAL_6720]
    [Destination Role: Master (1)]
    [Last Role Change in Frame: 107]
    [Current Mode: Active Mode (0)]
    [Last Mode Change in Frame: 564]
Bluetooth L2CAP Protocol
    Length: 52
    CID: Dynamically Allocated Channel (0x0041)
    [Connect in frame: 178]
    [PSM: RFCOMM (0x0003)]
Bluetooth RFCOMM Protocol
    Address: E/A flag: 1, C/R flag: 0, Direction: 0, Channel: 19
        1001 10.. = DLCI: 0x26 (Direction: 0, Channel: 19)
            1001 1... = Channel: 19
            .... .0.. = Direction: 0x0
        .... ..0. = C/R Flag: Response (0x0)
        .... ...1 = EA Flag: Last field octet (0x1)
    Control: Frame type: Unnumbered Information with Header check (UIH) (0xef), P/F flag: 1
        ...1 .... = P/F flag: 0x1
        111. 1111 = Frame type: Unnumbered Information with Header check (UIH) (0xef)
    Payload length: 47
    Credits: 1
    Frame Check Sequence: 0xe1
OBEX Protocol
    [Profile: PBAP (4)]
    [Current Path: /]
    [8 OBEX Fragments (6977 bytes): #569(990), #570(990), #571(990), #572(990), #573(990), #574(990), #576(990), #578(47)]
        [Frame: 569, payload: 0-989 (990 bytes)]
        …………………………
        [Frame: 578, payload: 6930-6976 (47 bytes)]
        [Fragment count: 8]
        [Reassembled OBEX length: 6977]
    .010 0000 = Response Code: Success (0x20)
    1... .... = Final Flag: True
    Packet Length: 6977
    [Request in Frame: 567]
    Headers
        Connection Id: 1
            Header Id: Connection Id (0xcb)
                11.. .... = Encoding: 4 byte quantity (network order) (0x3)
                ..00 1011 = Meaning: Connection Id (0x0b)
            Connection ID: 1
        End Of Body
            Header Id: End Of Body (0x49)
                01.. .... = Encoding: Byte sequence, length prefixed with 2 byte Unsigned Integer (0x1)
                ..00 1001 = Meaning: End Of Body (0x09)
            Length: 6969
            Value: 424547494e3a56434152440d0a56455253494f4e3a332e30…
    Line-based text data: x-bt/phonebook (350 lines)
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN:\r\n
        N:\r\n
        TEL;TYPE=0:03511008611\r\n
        X-IRMC-CALL-DATETIME;TYPE=DIALED:20220609T145831\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN:\r\n
        N:\r\n
        TEL;TYPE=0:03511008611\r\n
        X-IRMC-CALL-DATETIME;TYPE=DIALED:20220609T143109\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN:\r\n
        N:\r\n
        TEL;TYPE=0:131xxxxxxxx\r\n
        X-IRMC-CALL-DATETIME;TYPE=RECEIVED:20220608T184054\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN:\r\n
        N:\r\n
        TEL;TYPE=0:03511008611\r\n
        X-IRMC-CALL-DATETIME;TYPE=DIALED:20220608T092034\r\n
        END:VCARD\r\n
        ……………………
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN;CHARSET=UTF-8:中通快递\r\n
        N;CHARSET=UTF-8:中通快递\r\n
        TEL;TYPE=0:95720\r\n
        X-IRMC-CALL-DATETIME;TYPE=DIALED:20220606T142440\r\n
        END:VCARD\r\n
        BEGIN:VCARD\r\n
        VERSION:3.0\r\n
        FN;CHARSET=UTF-8:中通快递\r\n
        N;CHARSET=UTF-8:中通快递\r\n
        TEL;TYPE=0:95720\r\n
        X-IRMC-CALL-DATETIME;TYPE=MISSED:20220606T141702\r\n
        END:VCARD\r\n
        ……………………

在本次的Response中,一共返回了50组通话记录信息,对应了Request中的MaxListCount = 50;

我们发现,在这50组信息中,有很多相同的来电或者是去电信息,他们以发生的时间节点作为唯一标识;

BEGIN:VCARD\r\n
VERSION:3.0\r\n
FN:\r\n
N:\r\n
TEL;TYPE=0:03511008611\r\n
X-IRMC-CALL-DATETIME;TYPE=DIALED:20220609T145831\r\n
END:VCARD\r\n
  • BEGIN:VCARD:一组通话记录信息开始标志

  • END:VCARD:结束标志

  • VERSION:版本

  • N:姓名,现在的这组信息中为空,因为在一般情况下,我们手机中保存的联系人来电时,会提示Name Info,如果是陌生号码,一般直接显示电话号码,无法显示Name Info,但是存在一种情况:公共类型的电话号码是默认支持的,例如外卖、快递、中国移动、中国联通类似性质的号码是无需备注,来电时可以直接显示Name;

    • CHARSET=UTF-8:针对中文Name,采用UTF-8的编码方式
  • TEL;TYPE=0:联系人联系方式

  • X-IRMC-CALL-DATETIME:发生的时间点

  • X-IRMC-CALL-DATETIME;TYPE:通话记录类型

    • TYPE=DIALED:拨号,去电
    • TYPE=RECEIVED:来电
    • TYPE=MISSED:未接