梳理Android_WIFI_MBB(Make Befor Break)
触发MBB流程 和 解除MBB流程
目录
一、触发MBB(Make Befor Break)
二、解除MBB(Make Befor Break)
一、触发MBB(Make Befor Break)
硬件要求:
①设备是否支持至少两个并发的客户端模式管理器(STA + STA 并发)
②是否使能了mbb 的wifi切换
1、在连接一个接口为wlan0的wifi使用的过程中,wifi会不时的自我检查,在某个时间段遇到以下条件之一时,则会考虑触发MBB行为:
①当前连接的网络是OEM付费/专用网络(只对系统应用可用)
②当前连接的wifi没有互联网接入或预计没有互联网
③当前连接的网络链路质量不足,且流量低。(RSSI强度不足 && Tx或Rx流量低)
伴随Log:wlan0: Current connected network is not sufficient.
代码定位:WifiNetworkSelector.java -> isNetworkSufficient(WifiInfo wifiInfo)
2、程序过滤找出除了当前连接的AP,其他已保存最佳候选candidate网络AP。往下会走以下三个method的其中一个。
在触发连接candidate网络之前,先检查一下当前是否有已连接网路。
如果有,则会执行triggerConnectWhenConnected()方法去触发MBB。
如果没有的话,则会执行triggerConnectWhenDisconnected()方法进行单个AP连接。
Method:
①triggerConnectWhenDisconnected() //正常情况下当前没有网络连接时走该方法。
②triggerConnectWhenConnected() //触发MBB执行该方法===============
③triggerRoamWhenConnected()
3、发送CMD_REQUEST_ADDITIONAL_CLIENT_MODE_MANAGER消息,创建新的ClientModeManager,设置新的candidate网络的Role为ROLE_CLIENT_SECONDARY_TRANSIENT。随后去连接该新的网络。
伴随log:
Starting a new ClientModeManager
Starting additional ClientModeManager in role: ROLE_CLIENT_SECONDARY_TRANSIENT
4、其实在MBB行为中会有三个方式的回调,本次回调onActiveModeManagerAdded()方法。
三个方式回调:
onActiveModeManagerAdded(@NonNull ActiveModeManager activeModeManager) //当准备连接一个新的热点之前,对新的热点set这个role的时候,发生这个方法回调。
onActiveModeManagerRemoved(@NonNull ActiveModeManager activeModeManager) //在MBB行为下,热点断开连接后发送的调用
onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager) //role发生变化时回调这个方法
5、往下就是对新的wlan1网络进行四次握手连接并发送广播。随后发送CMD_NETWORK_STATUS消息,回调onInternetValidated(@NonNull ConcreteClientModeManager clientModeManager),主要做了以下事情:
①log:
Starting MBB switch primary from ConcreteClientModeManager{id=8499 iface=wlan0 role=ROLE_CLIENT_PRIMARY … …} to ConcreteClientModeManager{id=58235 iface=wlan1 role=ROLE_CLIENT_SECONDARY_TRANSIENT … …} by setting current primary's role to ROLE_CLIENT_SECONDARY_TRANSIENT
②设置wlan0主CMM的role为ROLE_CLIENT_SECONDARY_TRANSIENT
③保存主网络InterfaceName,(方便后面找到对应的Interface恢复发送connected广播)
④当主CMM的role变更为ROLE_CLIENT_SECONDARY_TRANSIENT时,立即发送虚假的断开连接广播。
6、主CMM的role有更变,所以回调上面第4步骤中的onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager),主要做了以下事情:
①Log: Continue MBB switch primary from ConcreteClientModeManager{id=8499 iface=wlan0 role=ROLE_CLIENT_SECONDARY_TRANSIENT … …} to ConcreteClientModeManager{id=58235 iface=wlan1 role=ROLE_CLIENT_SECONDARY_TRANSIENT … …} by setting new Primary's role to ROLE_CLIENT_PRIMARY and reducing network score
②设置wlan1副CMM的role为ROLE_CLIENT_PRIMARY
7、前面的wlan0和wlan1网络role都发生了变化,那么Primary ClientModeManager也会发生变化,切换wlan1为主要上网网络,以下对应log:
Log:
①WifiActiveModeWarden: Primary ClientModeManager changed from ConcreteClientModeManager{id=9581 iface=wlan0 role=ROLE_CLIENT_SECONDARY_TRANSIENT} to null
②WifiActiveModeWarden: Primary ClientModeManager changed from null to ConcreteClientModeManager{id=1110261964 iface=wlan1 role=ROLE_CLIENT_PRIMARY}
总结:
到了这里之后程序触发MBB行为就算完成了,以上综合总结简单的描述就是:最开始设备使用wlan0主网络接口上网,后面因为网络原因,在不断开wlan0主网络的情况下,暂时创建了wlan1副网络接口,提供给设备上网。
因为程序逻辑的原因,需要变更wlan0主网络和wlan1副网络的role名称,让程序知道该使用谁的网络作为当前设备上网网络。
wlan0主网络和wlan1副网络role演变过程:
iface=wlan0 role=ROLE_CLIENT_PRIMARY //该网络Interface提供给设备上网
iface=wlan1 role=ROLE_CLIENT_SECONDARY_TRANSIENT
========= >
iface=wlan0 role=ROLE_CLIENT_SECONDARY_TRANSIENT
iface=wlan1 role=ROLE_CLIENT_PRIMARY //该网络Interface提供给设备上网
二、解除MBB(Make Befor Break)
8、根据第1步骤的条件,当系统检测到wlan0的网络恢复正常,则会解除MBB行为,断开wlan1副网络,恢复使用wlan0主网络上网。
wlan1的role变更为ROLE_CLIENT_SCAN_ONLY,回调onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager)方法,做了以下事情:
①设置wlan1的role变更为ROLE_CLIENT_SCAN_ONLY
②Log:WifiMbbManager: recoveryPrimary kicking in, making ConcreteClientModeManager{id=9581 iface=wlan0 role=ROLE_CLIENT_SECONDARY_TRANSIENT} primary and stopping all other SECONDARY_TRANSIENT ClientModeManagers
9、随后Primary ClientModeManager也发生变化,以及wlan1断开连接,wlan0的role发生变更。
①Log: WifiActiveModeWarden: Primary ClientModeManager changed from ConcreteClientModeManager{id=1110261964 iface=wlan1 role=ROLE_CLIENT_SCAN_ONLY} to null
②发送了wlan1的Disconnected广播
③WifiClientModeManager[wlan0]: ClientModeManager role changed: Role: ROLE_CLIENT_PRIMARY, RequestorWs: WorkSource{1000 com.android.settings}, ModeListener: null
④WifiActiveModeWarden: ModeManager role changed ConcreteClientModeManager{id=9581 iface=wlan0 role=ROLE_CLIENT_PRIMARY}
10、wlan0的role role从ROLE_CLIENT_SECONDARY_TRANSIENT
变更为ROLE_CLIENT_PRIMARY,回调onActiveModeManagerRoleChanged(@NonNull ActiveModeManager activeModeManager)方法,做了以下事情:
①恢复发送wlan0主CMM的Connected广播
②WifiMbbManager:All secondary transient CMMs stopped, triggering queued callbacks
11、Primary ClientModeManager发生变化
①WifiActiveModeWarden: Primary ClientModeManager changed from null to ConcreteClientModeManager{id=9581 iface=wlan0 role=ROLE_CLIENT_PRIMARY}
总结:
到了这里之后就正式结束MBB行为了,wlan1副网络断开连接,重新恢复wlan0主网络提供设备上网。
这里需要注意的一点就是,在恢复wlan0主网络时,需要恢复发送wlan0的Connected广播。因为在前面触发MBB行为时,发送了wlan0虚假的断开连接广播。所以在最后结束MBB行为后,需要重新发送wlan0的Connected广播。
结束MBB行为wlan0主网络和wlan1副网络role演变过程:
iface=wlan0 role=ROLE_CLIENT_SECONDARY_TRANSIENT
iface=wlan1 role=ROLE_CLIENT_PRIMARY //该网络Interface提供给设备上网
========= >
iface=wlan0 role=ROLE_CLIENT_PRIMARY //该网络Interface提供给设备上网
iface=wlan1 role=ROLE_CLIENT_SCAN_ONLY //该Interface网络断开连接



