本文主要是介绍BLE 定向广播和privacy mode的纠缠,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
BLE 定向广播和privacy mode的解析
1. 问题
近两年来,安卓客户经常在bug系统上碰到客户提问,BLE蓝牙遥控器无法回连。对策下起来好说,如下:
diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h
index dd8c74e..18cbcba 100644
--- a/internal_include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -548,8 +548,9 @@/** Enables or disables support for local privacy (ex. address rotation)*/
+#undef BLE_LOCAL_PRIVACY_ENABLED#ifndef BLE_LOCAL_PRIVACY_ENABLED
-#define BLE_LOCAL_PRIVACY_ENABLED TRUE
+#define BLE_LOCAL_PRIVACY_ENABLED FALSE#endif/*
diff --git a/stack/btm/btm_ble_bgconn.cc b/stack/btm/btm_ble_bgconn.cc
index 3607cda..3f459b1 100644
--- a/stack/btm/btm_ble_bgconn.cc
+++ b/stack/btm/btm_ble_bgconn.cc
@@ -364,7 +364,9 @@ static bool btm_ble_start_auto_conn() {btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT);if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE &&controller_get_interface()->supports_ble_privacy()) {
+ #if ( BLE_LOCAL_PRIVACY_ENABLED == TRUE)own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+ #endifpeer_addr_type |= BLE_ADDR_TYPE_ID_BIT;}
好了,问题解决了。但这是什么原因呢?
前面一个对策意思是不使用privacy mode, 后面一个对策意思是本地Device不生成RPA地址(参考4.10节),具体见HCI规格7.8.12.
BLE_LOCAL_PRIVACY_ENABLED默认TRUE是google写的,应该问题不大。同时,观察市面上安卓手机行为,设置的是TRUE。这些遥控器也没办法回连其他手机。而对比其他蓝牙HID LE设备,例如鼠标,是可以回连的。由此可见,这个对策只是规避对策,不是解决对策, 问题还是出在遥控器身上。
2. 原因分析
通过空中抓包,发现这台HID设备回连的时候一直发定向广播,定向广播回连理论上更快,这原则上没问题。那为什么默认情况下回连失败呢?
经过调查,是因为TargetA地址(外围设备广播消息,221030说明)给的是公有地址,而蓝牙4.2以上规范,定向回连中,规定如果Host使用了可解析私有地址(RPA)时,Device(中央设备端,221030说明)不响应TargetA公有地址和静态私有地址(两个合起来叫做identity address)。所以回连失败。此种情况下,TargetA只能给RPA地址.
那熟悉协议的同学可能会说,定向回连本来就是要用静态私有地址或者公有地址,因为定向回连只接受白名单地址,白名单只可能是静态地址或者公有地址,并且是由控制器完成自动回连的。那不是和上面冲突了?
好吧,直接说答案吧:
-
确实,在蓝牙4.1以下(含,下同)时,定向回连就是这样的,只接受白名单地址(外围设备地址AdvA)。大家知道,白名单只能是静态地址或者公有地址(才有意义)。在使用白名单情况+蓝牙4.1之前,控制器是不支持reslove list的。也就是说,控制器并不知道对方IRK,4.1之前这些信息是保存在蓝牙Host协议栈的。所以,广播设备的控制器想填充TargetA 地址,只可能是白名单中的地址,不可能填写PRA地址,因为他根本没记录过这个,也不会自己生成(只能Host才有IRK来生成)。
图2 -
蓝牙4.2(含,下同)以后,就有了Device Privacy Mode。而大家知道,Privacy Mode是基于RPA地址的。安卓作为一个通用OS系统,肯定默认要打开Device Privacy Mode, 用来达成最强的隐私特性。此种情况下,定向回连也是可以支持的,是因为Device Privacy Mode增加的同时,新增了reslove list功能。reslove list中每一组数据中会含有本地IRK,对端IRK和Identity Address。这样,在Device Privacy Mode情况下,即使广播设备使用RPA地址,也可以使用IRK先核对定向广播中的AdvA地址,找到对应的Identity Address在reslove list的记录,并和白名单地址比对,如果一致,Device就接受AdvA地址,同时查看TargetA地址是否符合图1要求,并决定链连接是否继续。
图1 INITIATING STATE代表中心设备的初始状态. 对于外围设备, 对应状态叫做广播状态(221030新增说明).
3. 定向广播和privacy mode历史的纠缠
这里,我们可以分析下为什么遥控器厂为什么一直使用公有地址,然后让安卓厂一直忙于应付,不断发开头所示的补丁?
(1) 相信大家也猜到了,基本上是因为遥控器厂在蓝牙4.0/4.1时代的遗产,那时候使用公有地址+定向广播真香;
(2) 但是到了蓝牙4.2以后,遥控器厂可能疏忽了Device Privacy Mode的变更,并延续了此前设置。然后客户觉得遥控器啥也没动,只有安卓厂升级SDK了。于是把问题扔给安卓厂,安卓厂关闭安卓端本身的Device Privacy Mode特性,这样privacy mode同蓝牙4.1一致, 问题解决。
(3) 相反,鼠标厂没有这个问题,可能基本上是他们意识到,规格变了,手机适配起来了。
所以,现在对策是联系遥控器厂,说明此情况,请他们改正。
4. 定向广播和privacy mode其他想说的
- 蓝牙4.0/4.1也是有Privacy Mode的,但是这个只定义在Host,而Device里是没有的。蓝牙4.1的Privacy Mode叫做1.1版本。蓝牙4.2新增的Device Privacy Mode叫做1.2版本。
- 蓝牙4.2以上的Device Privacy Mode中,定向广播数据中,AdvA是可以用Identity Address的。但能使用RPA,还是建议用RPA。
- 再强调下,蓝牙4.2以上的Device Privacy Mode中,定向广播数据中,TargetA必须使用RPA。原因如图1所示。
- 关闭安卓本地Device Privacy Mode(即文章开头的对策),定向广播仍然是可以工作的。
- 假如不关闭安卓本地Device Privacy Mode,而遥控器使用非定向广播,那即使继续用公有地址,也是没有问题的(最终遥控器对策)。
- 中心设备中, 打开Device Privacy Mode情况下, device是可以解析Identity地址和RPA地址. 只是在Directed Advertising中, device无法解析Identity地址.
- 安卓中, 只有打开BLE_LOCAL_PRIVACY_ENABLED情况下, 才会设置私有地址. 可以以这个来区分代码是否打开了这个宏定义. 具体代码在:btm_gen_resolvable_private_addr(base::Bind(&btm_gen_resolve_paddr_low));
- 安卓代码的实际上不支持BLE 4.0/4.1 privacy mode. 原本代码打算基于静态的random address做的, 实际没实现, 见BTM_BleConfigPrivacy.
- BLE 4.2以上privacy mode实际分为两种, 一种是Device Privacy Mode, 另外一种是network privacy mode. 前一种支持Identy Addr和私有地址. 而后一种只支持RPA地址. 协议上说后一种其实是默认的. 但是google的实现只支持前一种.
10.RPA地址, 传统是Host周期生成的. Privacy Mode base on Host时, 也是Host周期产生. 但是Privacy Mode base on Controler时, 控制器可以自己产生(还待进一步考证… 搜索resolvable private adddress).
5. 鼠标厂怎么做的
-
鼠标厂看了几个,即使他们宣称支持4.2,5.0或者5.1,无论他们使用Nordical芯片,还是国产小博通芯片,Feature特性都是不支持Device Privacy Mode的,并且只支持特性中的LE Encryption。其他你能想到的,都没有的(实际上也确实不需要,徒增成本)。
-
所以,鼠标厂的做法,其实就是面对蓝牙4.2以上系统时,使用上面的(5)所说明; 面对蓝牙4.1芯片时,google只支持公有地址. 使用Identity蓝牙地址+定向或非定向广播都可以。
-
定向广播时,鼠标厂广播使用的TargetA地址,和CONNECT_IND指示的intiator地址应该是一样的。
6. 关于定向广播TargetA地址蓝牙芯片厂的说明
-
Nordical
http://www.wowotech.net/bluetooth/ble_address_type.html#comment-6910
这里是网友“虎妞”的说明,我没Nordical的SDK,所以不知道是不是真的,大家如果有,发我一份。
-
Dialog
https://www.dialog-semiconductor.com/forums/post/dialog-smartbond-bluetooth-low-energy-%E2%80%93-software/directed-advertise
如果以上真的代表两个大厂官方立场,他们想要说的应该只是蓝牙4.0/4.1的情况。N厂说只能用静态随机地址,D厂说只能用公有地址, 都不完整, 实际上应该是Identy address, 而Identy addr包括Public addrss和static random address。可能是他们的实现只支持他们说的那样。
不过, 使用静态随机地址时, 一定要follow N厂的说法. 即使开关机, 你的静态随机地址也不要改变. 不然, 肯定无法回连了.
总的来说, 4.0/4.1定向回连还是只支持白名单蓝牙地址, 只能是公有地址和不会变化的静态随机地址. 如上第二节第1个原因所述。但google的蓝牙协议栈, 也只支持公有地址.
4.2及以上, 定向回连只支持RPA地址, 不支持Identy address.
大家如有不同意见,欢迎拍砖。
这篇关于BLE 定向广播和privacy mode的纠缠的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!