前言
维护Miracast投屏中遇到的一些问题,简单记录一下
[2024-01-23 10:03:32] 01-23 10:03:32.240 11685 11685 I wpa_supplicant: wlan0: SME: Trying to authenticate with 74:50:4e:25:c4:e0 (SSID='XXX' freq=5220 MHz)
[2024-01-23 10:03:32] 01-23 10:03:32.242 11685 11685 I wpa_supplicant: P2P-GROUP-REMOVED p2p0 GO reason=FREQ_CONFLICT
[2024-01-23 10:03:33] 01-23 10:03:32.243 11685 11685 I wpa_supplicant: p2p0: interface state ENABLED->DISABLED
[2024-01-23 10:03:33] 01-23 10:03:32.243 11685 11685 I wpa_supplicant: p2p0: AP-DISABLED
信道冲突
WiFi信道,也就是频段,是以无线信号作为传输载体的数据信号传送通道。
目前WiFi已经推出了WiFi的2.4G、5G、6G频段, Android源码中也增加了相关的功能,这里总结一下。
2.4G一共分为14个信道(1-14),从2412到2484,每个信道的有效宽度是 20MHz,另外还有2MHz的强制隔离频带(类似于公路上的隔离带)。即,对于中心频率为 2412 MHz 的1信道,其频率范围为2401~2423MHz。
5G一共有60个信道(32-173),从5160到5865,在中国支持的5G信道为36 38 40 44 46 48 52 54 56 60 62 64,后六个是DFS。
6G为1-233,从5946到7105。大概为1.2GHz的总带宽,可以分成15个80MHz的频谱。
出现信道冲突的原因是什么?
举一个简单的例子:如果WLAN工作在一个信道上,P2P工作在另一个信道上,如果你的wifi驱动或者系统只支持单通工作,那么必然出现冲突,只能有一个可以工作。
Google默认就是WLAN的优先级高,出现conflict时,会直接断开p2p那边的连接。
工作冲出现的信道冲突
Miracast投屏需要依赖Wifi P2P连接,当P2P与对端建立连接后,如果又去连接Ap,P2P工作频段是5G, WLAN工作频段是2.4G,导致信道冲突,P2P连接被wpa_supplicant断开了。
一般情况Miracast连接P2P时会优先选用5G信道,因为Miracast投屏需要传输RTP音视频数据,对带宽要求比较大,所以优先选容5G信道。而AP的信道一般是路由器固定的,要么是5G, 要么是2.4G。问题发生时WLAN连接了2.4G的AP,导致投屏断开了
上述问题一般发生的概率很低,因为一般投屏之前WLAN早已连接完成了,此后再连接P2P,wpa_supplicant会检查可用的信道。但是如果WLAN连接发生在P2P连接之后,就很容易发生了。
同样的原因出现再我做Miracast多路投屏上了
为了实现多路投屏,TV设备(SINK)需要作为GO,这样可以实现多个手机同时连接到TV设备上。
我在投屏连接之前先让TV设备创建了P2P Group,这样可以避免P2P协商(修改go_intent=15也可以,但是有部分手机在做P2P协商时也想做GO,此时双方go_intent都是15,就会导致协商失败)。
在开启Miracast之前,我的项目又会重启了Wifi(为了提高miracast投屏的连接成功率)。这就导致了一个问题,Miracast重启WIFI后,创建P2P Group,然后系统会在WIfi重启后重新连接WLAN,WLNA很可能会与P2P Group产生信道冲突。
最终检查代码发现问题出现之前优化多路投屏成功率上
为了优化多路投屏的连接成功率,我们修改了wpa_supplicant,对P2P使用固定网卡,这部分修改出现了问题,固定网卡的同时也固定了单通道工作模式。
static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
struct nlattr *nl_combi)
{
......
#if 1
return 0;
#else
if (combination_has_p2p && combination_has_mgd) {
unsigned int num_channels =
nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
info->p2p_concurrent = 1;
if (info->num_multichan_concurrent < num_channels)
info->num_multichan_concurrent = num_channels;
}
return 0;
#endif
}
没有更新num_multichan_concurrent可同时工作的信道数量,导致连接WLAN时wpa_supplicant会检测是否支持多通道,如果不支持就会检查信道冲突。
/*
* If multi-channel concurrency is not supported, check for any
* frequency conflict. In case of any frequency conflict, remove the
* least prioritized connection.
*/
if (wpa_s->num_multichan_concurrent < 2) {
int freq, num;
num = get_shared_radio_freqs(wpa_s, &freq, 1);
if (num > 0 && freq > 0 && freq != params.freq) {
wpa_printf(MSG_DEBUG,
"Conflicting frequency found (%d != %d)",
freq, params.freq);
if (wpas_p2p_handle_frequency_conflicts(wpa_s,
params.freq,
ssid) < 0) {
wpas_connection_failed(wpa_s, bss->bssid);
wpa_supplicant_mark_disassoc(wpa_s);
wpabuf_free(resp);
wpas_connect_work_done(wpa_s);
return;
}
}
}