Android 12 中引入的 Wi-Fi/移动网络共存信道规避功能可以识别并避免使用不安全的 Wi-Fi 信道,以防可能受到来自移动网络信道的干扰或对移动网络信道造成干扰的情况。这包括 STA、SoftAp、Wi-Fi Direct (P2P)、Wi-Fi Aware (NAN) 等接口。
本页面讨论以下内容
- 移动网络调制解调器必须向 Android 框架报告的信息
- Wi-Fi 框架用于计算要规避的 Wi-Fi 信道的算法
- 设备制造商必须为 Wi-Fi 框架提供的配置表
- 与信道规避功能相关的系统 API、配置和 HAL API
- 用于处理信道规避的框架行为
- 用于处理信道规避的芯片供应商行为
- 信道规避的实现详情
- 用于验证信道规避行为的测试
背景
对于采用 LTE、5G NR 和授权辅助接入 (LAA) 等移动网络技术的设备,正在使用的移动网络信道可能会干扰正在使用的 Wi-Fi 信道。当移动网络信道和 Wi-Fi 信道之间的频率间隔较短(相邻信道)或存在谐波和互调干扰时,就会发生这种情况。
当一个天线正在发射,而另一个天线同时正在接收时,这种类型的干扰就会成为问题。在这种情况下,发射天线会淹没接收天线,从而影响其接收质量。
本文档将造成干扰的发射机称为施扰方,将受到干扰的接收机称为受扰方。充当施扰方或受扰方的 Wi-Fi 信道称为不安全信道。
Wi-Fi/移动网络共存信道规避功能为信道规避提供了一致的方法,从而减少了对偏离 Wi-Fi 框架的专有代码的需求。此外,该功能还允许设备制造商配置、启用和停用以及替换该功能。
该功能通过控制 Wi-Fi 信道来执行信道规避。Wi-Fi 信道规避方案可以描述为一系列四个抽象步骤
- 调制解调器报告移动网络频率变化
- 共存规避算法计算不安全的 Wi-Fi 信道
- 共存规避算法通知 Wi-Fi 服务
- 框架或驱动程序执行适当的 Wi-Fi 操作
图 1. 信道规避方案
报告移动网络频率变化
电话服务会报告当前正在使用的移动网络信道。当正在运行的移动网络频率发生变化时,调制解调器会通过 IRadio::PhysicalChannelConfig
将此信息报告给电话服务。此信息包括授权辅助接入 (LAA) 和载波聚合 (CA) 的指示。
从 Android 12 开始,1.6 IRadio::PhysicalChannelConfig
中的以下字段提供共存公式所需的必要信息,调制解调器必须填充这些信息。
struct PhysicalChannelConfig {
/** Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING */
CellConnectionStatus status;
/** The radio technology for this physical channel */
RadioTechnology rat;
/** Downlink Absolute Radio Frequency Channel Number */
int32_t channelNumberDownlink;
/** Uplink Absolute Radio Frequency Channel Number */
int32_t channelNumberUplink;
/** Downlink cell bandwidth, in kHz */
int32_t cellBandwidthDownlink;hte
/** Uplink cell bandwidth, in kHz */
int32_t cellBandwidthUplink;
}
计算不安全的 Wi-Fi 信道
当调制解调器报告移动网络频率变化时,共存信道算法会计算移动网络信道和 Wi-Fi 信道之间的干扰,并确定哪些 Wi-Fi 信道是不安全的。
存在多种类型的干扰,需要不同的公式:相邻干扰和谐波/互调干扰。由于设备之间天线和布局的物理差异,每种设备的相邻干扰和谐波/互调干扰模式都不同。为了解决这个问题,设备制造商必须提供查找表,以便将参数插入到两种类型的干扰的通用公式中。这些参数是按蜂窝频段定义的,并由活动蜂窝信道的频段引用。
可以在查找表中定义最大功率上限。如果定义了最大功率上限,则不安全信道将以提供的功率上限进行发射。如果没有功率上限,则信道将以全功率发射。
通常,信道规避功能采用尽力而为的方法来避免不安全的 Wi-Fi 信道,以优化性能。但在某些情况下(例如,由于运营商要求),某些接口必须避免某些蜂窝频段的不安全信道。在这种情况下,强制性限制表示为一个位掩码,其中包含是否禁止某些信道(如 Wi-Fi Direct (P2P)、SoftAp 和 Wi-Fi Aware (NAN))的值。虽然不安全信道充当针对所有用例使用该信道的建议,但强制性限制标记了针对强制性规避的特定用例。
如果 2.4 GHz 或 5 GHz 频段的每个信道都被标记为不安全,则查找表可以为每个干扰蜂窝频段定义一个默认 2.4 GHz 信道或默认 5 GHz 信道作为最安全的选择。当频段的其余部分被报告为不安全时,这些默认信道不会被报告为不安全信道。
替换列表
当干扰在很大程度上取决于带宽时(因此,具有较大带宽的信道可能不安全,但具有较小带宽的信道可能安全),公式化方法受到限制。在某些情况下,例如 LAA,最好跳过计算并使用指定的不安全信道列表。
为此,您可以在某些条目的查找表中指定不安全信道的替换列表。表条目中的替换列表表示跳过该特定蜂窝信道的计算,并且匹配的蜂窝信道的不安全 Wi-Fi 信道由替换列表指定。
对于带宽敏感的情况,您可以通过在替换列表中指定具有特定带宽的某些信道来有选择地避免某些带宽。这是因为每个 Wi-Fi 信道号对应于指定的带宽。
替换列表由每个 Wi-Fi 频段的信道号列表或预定义的类别关键字表示
2g 类别
all
(整个 2.4 GHz 频段)
5g 类别
all
(整个 5 GHz 频段)20mhz
(5 GHz 20 MHz 信道)40mhz
(5 GHz 40 MHz 信道)80mhz
(5 GHz 80 MHz 信道)160mhz
(5 GHz 160 MHz 信道)
相邻信道干扰
为了确定相邻信道干扰,共存规避算法确保施扰方信道和受扰方信道之间的距离 ΔF 不低于指定的阈值。
图 2. 施扰方信道和受扰方信道之间的距离
阈值由设备的物理配置以及每个干扰频段的查找表条目中提供的阈值确定。被认为是非干扰的频段没有表条目,并且不需要计算不安全信道(这是大多数情况)。
相邻干扰参数
wifiVictimMhz
:Wi-Fi 受扰方(蜂窝上行链路)的 MHz 距离阈值cellVictimMhz
:蜂窝受扰方(蜂窝下行链路)的 MHz 距离阈值
该算法对每个活动的蜂窝信道的行为如下
- 对于信道的频段,尝试查找查找表条目。如果未找到表条目,则返回,且该蜂窝信道没有不安全信道。
- 根据蜂窝频段,识别哪个 Wi-Fi 频段处于风险之中,以及干扰来自频段的哪一侧(例如,较低的 2.4 GHz 信道、较高的 2.4 GHz 信道、较低的 5 GHz 信道)。
如果存在
wifiVictimMhz
且蜂窝信道具有上行链路,并且如果 Wi-Fi 频段的较低部分处于风险之中
- 通过将
wifiVictimMhz
添加到蜂窝上行链路的最高频率,找到不安全信道的上限。 - 找到其下边缘与上限重叠的第一个 20 MHz Wi-Fi 信道。
- 将 Wi-Fi 信道、包含它的每个更大带宽信道(例如,40 MHz、80 MHz)以及同一频段的每个较低信道标记为不安全信道。
- 通过将
如果 Wi-Fi 频段的较高部分处于风险之中
- 通过从蜂窝上行链路的最低频率中减去 wifiVictimMhz,找到不安全信道的下限。
- 找到其上边缘与上限重叠的第一个 Wi-Fi 信道。
- 将 Wi-Fi 信道、包含它的每个更大信道(例如,40 MHz、80 MHz)以及同一频段的每个较高信道标记为不安全信道。
如果存在
cellVictimMhz
且蜂窝信道具有下行链路。- 使用
cellVictimMhz
作为阈值执行步骤 3,并与蜂窝下行链路而不是蜂窝上行链路进行比较。
- 使用
将表条目的功率上限应用于计算出的不安全信道。
图 3. 相邻信道干扰的不安全信道计算
谐波或互调失真
对于谐波或互调失真,共存引擎计算谐波或互调信号的范围,并评估它与潜在的受扰方信道的重叠百分比。如果重叠超过重叠阈值,则该算法认为这是不安全的情况。谐波或互调失真在受扰方信道上的重叠百分比的计算使用以下公式
在谐波失真情况下,该算法考虑蜂窝上行链路信道的谐波失真,该信道会损害 Wi-Fi 信道。然后,它根据蜂窝上行链路频率和谐波次数 $ N $,用谐波值替换失真高值和失真低值。
图 4. 谐波失真的不安全信道计算
在互调情况下,该算法考虑蜂窝上行链路和 Wi-Fi 信道的互调失真,该失真会损害蜂窝下行链路信道。然后,它根据蜂窝上行链路频率、Wi-Fi 频率和两个互调系数 $ M $、$ N $,用互调值替换失真高值和失真低值。
图 5. 互调失真的不安全信道计算
您可以在每个干扰蜂窝频段的查找表中指定 $ M $、$ N $ 和重叠值。如果频段没有干扰,则从该频段条目的表中省略这些值。可以独立定义 Wi-Fi 2.4 GHz 和 5 GHz 频段的两组这些值。
与相邻干扰算法类似,该算法重用每个干扰蜂窝频段定义的相同功率上限值。
该算法对每个活动的蜂窝信道的行为如下
- 对于蜂窝信道的频段,它会尝试查找查找表条目。如果未找到表条目,则返回,且此信道没有不安全信道。
如果定义了参数,则从谐波中查找不安全的 2.4 GHz 信道。
- 查找 2.4 GHz 的谐波次数 N。
- 根据 N 和蜂窝上行链路计算谐波高频和谐波低频。
- 查找从下方谐波下限范围内的第一个 20 MHz Wi-Fi 信道。
- 计算谐波在 Wi-Fi 信道上的重叠,如果重叠超过 2.4 GHz Wi-Fi 重叠阈值,则将该信道标记为不安全。
- 查找从上方谐波上限范围内的第一个 20 MHz Wi-Fi 信道。
- 计算谐波在 Wi-Fi 信道上的重叠,如果重叠超过 2.4 GHz Wi-Fi 重叠阈值,则将该信道标记为不安全。
- 将两者之间的每个 20 MHz 信道标记为不安全信道。
如果定义了参数,则从谐波中查找不安全的 5 GHz 信道。
- 查找 5 GHz 的谐波次数 N。如果 N 为 0,则跳至步骤 5。
- 根据 N 和蜂窝上行链路计算谐波高频和谐波低频。
查找不安全的 20 MHz 信道。
- 查找从下方谐波下限范围内的第一个 20 MHz Wi-Fi 信道。
- 计算谐波在 Wi-Fi 信道上的重叠,如果重叠超过 2.4 GHz Wi-Fi 重叠阈值,则将该信道标记为不安全。
- 查找从上方谐波上限范围内的第一个 20 MHz Wi-Fi 信道。
- 计算谐波在 Wi-Fi 信道上的重叠,如果重叠超过 2.4 GHz Wi-Fi 重叠阈值,则将该信道标记为不安全。
- 将两者之间的每个 20 MHz 信道标记为具有指定功率上限的不安全信道。
查找不安全的 40 MHz、80 MHz、160 MHz 信道
- 重复步骤 3a,但使用 40 MHz、80 MHz、160 MHz。
- 不是计算信道在谐波边缘上的重叠,而是重用来自较小组成信道的计算出的重叠(例如,如果两个 20 MHz 信道构成一个 40 MHz 信道,并且重叠分别为 30% 和 90%,则 40 MHz 信道的平均重叠为 60%)。
如果定义了参数,则从互调中查找不安全的 2.4 GHz 信道。
- 查找 2.4 GHz 的互调系数 N、M。
对于每个 2.4 GHz Wi-Fi 信道
- 根据 N、M、蜂窝上行链路和 Wi-Fi 信道计算互调低频和互调高频。
- 计算互调在蜂窝下行链路上的重叠,如果重叠超过 2.4 GHz 蜂窝重叠阈值,则将该信道标记为不安全。
如果定义了参数,则从互调中查找不安全的 5 GHz 信道。
- 使用 5 GHz Wi-Fi 信道和 5 GHz 蜂窝重叠阈值重复步骤 4。
将表条目的功率上限应用于计算出的不安全信道。
最终结果
在计算出相邻干扰和谐波干扰的两组不安全信道后,通过取两组的并集(如果存在冲突,则选择较低的功率上限)来计算最终集合,并在未应用强制性限制的情况下从集合中删除默认信道。
该算法的行为如下
- 如果每个 2.4 GHz Wi-Fi 信道都被标记为不安全信道,则从集合中删除默认 2.4 GHz Wi-Fi 信道。
- 如果每个 5 GHz Wi-Fi 信道都被标记为不安全信道,则从集合中删除默认 5 GHz Wi-Fi 信道。
- 返回不安全信道的最终集合。
查找表格式
查找表以 XML 文件形式表示,该文件位于可叠加配置字符串 config_wifiCoexTableFilepath
中,并由以下 XSD 定义。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="1.0">
<xsd:element name="table">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="entry" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="entry">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="rat" type="ratType"/>
<xsd:element name="band" type="xsd:int"/>
<xsd:element name="powerCapDbm" type="xsd:int" minOccurs="0"/>
<xsd:choice>
<xsd:element ref="params"/>
<xsd:element ref="override"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="ratType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="LTE"/>
<xsd:enumeration value="NR"/>
</xsd:restriction>
</xsd:simpleType>
<!-- Define coex algorithm parameters -->
<xsd:element name="params">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="neighborThresholds" minOccurs="0"/>
<xsd:element name="harmonicParams2g" type="harmonicParams" minOccurs="0"/>
<xsd:element name="harmonicParams5g" type="harmonicParams" minOccurs="0"/>
<xsd:element name="intermodParams2g" type="intermodParams" minOccurs="0"/>
<xsd:element name="intermodParams5g" type="intermodParams" minOccurs="0"/>
<xsd:element ref="defaultChannels" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="neighborThresholds">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="wifiVictimMhz" type="xsd:int" minOccurs="0"/>
<xsd:element name="cellVictimMhz" type="xsd:int" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="harmonicParams">
<xsd:sequence>
<xsd:element name="N" type="xsd:int"/>
<xsd:element name="overlap" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="intermodParams">
<xsd:sequence>
<xsd:element name="N" type="xsd:int"/>
<xsd:element name="M" type="xsd:int"/>
<xsd:element name="overlap" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="defaultChannels">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="default2g" type="xsd:int" minOccurs="0"/>
<xsd:element name="default5g" type="xsd:int" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- Define algorithm override lists -->
<xsd:element name="override">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="override2g" minOccurs="0"/>
<xsd:element ref="override5g" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="override2g">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="category" type="overrideCategory2g" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="channel" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="override5g">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="category" type="overrideCategory5g" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="channel" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="overrideCategory2g">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="all"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="overrideCategory5g">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="all"/>
<xsd:enumeration value="20Mhz"/>
<xsd:enumeration value="40Mhz"/>
<xsd:enumeration value="80Mhz"/>
<xsd:enumeration value="160Mhz"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
XML 表示例
以下是 XML 查找表示例
<table>
<!-- Entry using algorithm parameters -->
<entry>
<rat>LTE</rat>
<band>40</band>
<powerCapDbm>50</powerCapDbm>
<params>
<neighborThresholds>
<wifiVictimMhz>25</wifiVictimMhz>
<cellVictimMhz>40</cellVictimMhz>
</neighborThresholds>
<harmonicParams2g>
<N>3</N>
<overlap>50</overlap>
</harmonicParams2g>
<harmonicParams5g>
<N>3</N>
<overlap>50</overlap>
</harmonicParams5g>
<intermodParams2g>
<N>-2</N>
<M>1</M>
<overlap>75</overlap>
</intermodParams2g>
<intermodParams5g>
<N>-2</N>
<M>1</M>
<overlap>75</overlap>
</intermodParams5g>
<defaultChannels>
<default2g>6</default2g>
<default5g>36</default5g>
</defaultChannels>
</params>
</entry>
<!-- Entry using the override list -->
<entry>
<rat>LTE</rat>
<band>41</band>
<powerCapDbm>50</powerCapDbm>
<override>
<override2g>
<channel>6</channel>
<channel>11</channel>
...
</override2g>
<override5g>
<category>40Mhz</category>
<channel>34</channel>
...
</override5g>
</override>
</entry>
</table>
载波聚合
对于载波聚合 (CA),每个上行链路或下行链路的谐波或互调范围可能不会产生足够的重叠以独立引起干扰,但组合后可能会产生足够的重叠。该算法独立考虑每个谐波或互调范围,并取返回的不安全信道的并集。对于互调情况,这意味着评估每个 UL 对每个 DL 的互调范围。
该算法不区分 PCELL、PSCELL 或 SCELL,并将它们视为相等。
授权辅助接入
授权辅助接入 (LAA) 被标识为频段 #46。该算法将此频段与其他频段类似地处理。在这种情况下,完整的 5 GHz 信道可以设置为查找表中的替换列表。
根据运营商要求,信道规避算法对整个 5 GHz Wi-Fi 频段的 SoftAP 和 Wi-Fi Direct (P2P) 设置强制性限制。为了让算法处理此用例,必须定义运营商配置值 restrict_5g_softap_wifi_direct_for_laa
。如果蜂窝信道位于 LAA 上,并且 restrict_5g_softap_wifi_direct_for_laa
为 true
,则该算法将返回不安全信道集合,其中包含整个 5 GHz 频段,并为 SoftAP 和 Wi-Fi Direct (P2P) 设置强制性限制标志。
通知 Wi-Fi 服务
在共存信道算法计算出不安全信道后,为了向您的系统应用提供不安全信道及其限制,请使用 Android 框架中定义的以下 @SystemApi 数据结构。
public final class CoexUnsafeChannel {
public static final int POWER_CAP_NONE
public @WifiAnnotations.WifiBandBasic int getBand();
public int getChannel();
// Returns the specified power cap in dBm, or POWER_CAP_NONE if not specified.
public int getPowerCapDbm();
}
当不安全信道发生变化时,使用以下 WifiManager
@SystemApi 方法和回调,以使应用能够获取更新后的值。
public static final int COEX_RESTRICTION_WIFI_DIRECT;
public static final int COEX_RESTRICTION_SOFTAP;
public static final int COEX_RESTRICTION_WIFI_AWARE;
// Register a CoexCallback to listen on onCoexUnsafeChannelsChanged callbacks. The callback will be called whenever the unsafe channels change, as well as immediately after registering to get the current values.
public void registerCoexCallback(Executor executor, CoexCallback callback);
public void unregisterCoexCallback(CoexCallback callback);
public abstract static class CoexCallback {
//Gets called whenever getCoexUnsafeChannels()/getCoexRestrictions() have updated values
public void onCoexUnsafeChannelsChanged(List<CoexUnsafeChannels> unsafeChannels, int restrictions);
}
执行 Wi-Fi 操作
当 Wi-Fi 服务收到有关不安全信道集合的信息时,它会执行适当的操作以确保规避这些信道。本节介绍 Wi-Fi 服务在不同场景中的行为。
通知驱动程序
由于驱动程序在执行信道规避方面发挥着重要作用,因此将不安全信道传递给驱动程序和固件至关重要。为此,请使用以下 IWifiChip
HAL API。
对于 AIDL
void setCoexUnsafeChannels(in CoexUnsafeChannel[] unsafeChannels,
in int restrictions)
对于 HIDL(1.5 或更高版本)
setCoexUnsafeChannels(vec<CoexUnsafeChannel> unsafeChannels,
bitfield<IfaceType> restrictions);
SoftAP
SoftAP 是不安全信道规避的主要用例。以下部分概述了可以应用信道规避的 ACS 的关键 SoftAp 场景。这些场景描述了信道规避算法以及驱动程序或固件的行为。
启用 ACS 的情况下启动 SoftAP(尚无 SoftAP 启动)
如果信道不安全且存在 SoftAP 限制
- 框架从 ACS 列表中删除不安全信道。
- 如果列表为空,则框架停止 SoftAP。
如果信道不安全且没有限制
- 供应商驱动程序或固件将安全信道优先于不安全信道。
SoftAP 已启动并启用 ACS,并且不安全信道已更新
如果 SoftAP 信道不安全且存在 SoftAP 限制
- 框架通过删除不安全信道来更新 ACS 列表。
- 如果列表为空,则框架关闭 SoftAP。
如果 SoftAP 信道不安全且没有限制
- 框架不采取任何操作。供应商驱动程序或固件处理规避不安全信道或在规避不可行时应用功率上限。
Wi-Fi Direct (P2P)
如果存在具有 Wi-Fi Direct (P2P) 限制的不安全信道。
- 框架请求
wpa_supplicant
使用 HAL 方法ISupplicantP2pIface::setDisallowedFrequencies()
来规避不安全信道。
- 框架请求
如果存在没有限制的不安全信道。
- 如果使用了没有 Wi-Fi Direct (P2P) 限制的不安全信道,则供应商驱动程序或固件将应用功率上限。
Wi-Fi Aware (NAN)
框架不参与 Wi-Fi Aware (NAN) 的信道选择,并且不采取任何框架操作。供应商驱动程序或固件负责 Wi-Fi Aware (NAN) 信道规避。
停用算法
如果您想停用默认算法实现并传递您自己的不安全信道列表以进行规避,请配置叠加层 config_wifiDefaultCoexAlgorithmEnabled
。如果叠加层设置为 false,则默认算法将被停用。然后,您可以使用您自己的带外专有算法来生成不安全信道列表,以使用以下系统 API 输送到框架。
public void setCoexUnsafeChannels(Set<CoexUnsafeChannel> coexUnsafeChannels,
int coexRestrictions);
验证实现
要验证 Wi-Fi/移动网络共存信道规避功能的实现,请使用以下测试。
CTS 测试
WifiManagerTest.java
testCoexMethodsShouldFailNoPermission()
testListenOnCoexUnsafeChannels()
ACTS 测试
WifiManagerTest.py
test_set_get_coex_unsafe_channels()
VTS 测试
如果实现了 AIDL:
wifi_chip_aidl_test.cpp
TEST_P(WifiChipAidlTest, SetCoexUnsafeChannels)
如果实现了 HIDL:
wifi_chip_hidl_test.cpp
TEST_P(WifiChipHidlTest, setCoexUnsafeChannels)