安卓源码避坑指南6——电话记录为空号触发蓝牙重启

电话记录为空号触发蓝牙重启

在这里插入图片描述

对于空的电话记录想必大家都会感到很奇怪,今天就给大家分享个空电话记录引起蓝牙crash的原生问题。

空电话记录的产生:在如今社会中,个人信息满天飞,相关从业者通过网络拨号软件拨打你的电话后,就会在你的手机上产生一条空的电话记录。

触发蓝牙重启指的是PBAP协议PCE端的蓝牙进程crash,从而引发蓝牙自动重启的问题。追踪分析后问题根因主要在 CallLogPullRequest.updateTimesContacted() 中,该方法用来统计通话记录中相同联系人的通话次数,并同步到通讯录数据库中。

updateTimesContacted()是从android-9才新增的方法,因此在android-8及以下版本上不存在此问题,只在android-9及以上版本上存在。

那空电话记录是如何一步步触发蓝牙重启了呢?话不多说,直接上同步的通话记录数据解析流程。

PCE端的蓝牙协议栈接收到通话记录数据:
在这里插入图片描述

接收到的通话记录VCARD中的电话号码信息在HCI层显示异常,其实该条通话记录就是我们这篇文章中所要讨论的空的通话记录。手机端(PSE)在组装通话记录数据时通过蓝牙发送到请求方,由于该号码不存在,因此会将字符串“未知号码”或“无号码”等通过UTF-8编码格式转换成相应数据发送给PCE。

上图中PCE端接收到的电话号码数据为:0xE69CAAE79FA5E58FB7E7A081
在这里插入图片描述

经UTF-8编码转换成对应字符串为:未知号码

数据再经过 VCardEntry.addPhone() 添加电话号码时,会依次提取char型字符判断该字符是否符合标准,由于是“未知号码”字符串转换的数据,显而易见builder最后是个空字符串,因此最后添加的电话号码数据是个空值。
在这里插入图片描述

通话记录数据全部解析完成后,蓝牙进程通过CallLogPullRequest.onPullComplete() 将通话记录写入数据库中,并统计每个电话号码的通话次数。写数据库完成后判断最后一条通话记录的类型如果是OUTGOING_TYPE(拨出类型),则更新通讯录中的联系次数。(这块的判断通话类型逻辑感觉没必要…)

以上条件满足,则在更新联系次数的方法updateTimesContacted()中使用一个空的电话号码查询数据库,触发IllegalArgumentException参数错误,引发蓝牙进程crash。
在这里插入图片描述

问题根因分析到这儿就很清楚了,那在android-9及以上版本的源码中规避此类问题的解决方案就小菜一碟,只需要在更新联系次数的for循环中首先对key值(对应于电话号码)新增判空处理即可。
在这里插入图片描述

感兴趣的小伙伴欢迎私信留言一起讨论,共同学习,一起进步!

更多互联互通技术,欢迎关注微信公众号:Connectivity
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值