1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Constants for Nearby Connection.""" 16 17import dataclasses 18import datetime 19import enum 20 21NEARBY_RESET_WAIT_TIME = datetime.timedelta(seconds=5) 22WIFI_DISCONNECTION_DELAY = datetime.timedelta(seconds=3) 23 24FIRST_DISCOVERY_TIMEOUT = datetime.timedelta(seconds=30) 25FIRST_CONNECTION_INIT_TIMEOUT = datetime.timedelta(seconds=30) 26FIRST_CONNECTION_RESULT_TIMEOUT = datetime.timedelta(seconds=35) 27FILE_1M_PAYLOAD_TRANSFER_TIMEOUT = datetime.timedelta(seconds=110) 28SECOND_DISCOVERY_TIMEOUT = datetime.timedelta(seconds=35) 29SECOND_CONNECTION_INIT_TIMEOUT = datetime.timedelta(seconds=10) 30SECOND_CONNECTION_RESULT_TIMEOUT = datetime.timedelta(seconds=25) 31CONNECTION_BANDWIDTH_CHANGED_TIMEOUT = datetime.timedelta(seconds=25) 32FILE_1G_PAYLOAD_TRANSFER_TIMEOUT = datetime.timedelta(seconds=400) 33WIFI_WLAN_CONNECTING_TIME_OUT = datetime.timedelta(seconds=25) 34DISCONNECTION_TIMEOUT = datetime.timedelta(seconds=15) 35 36BT_TRANSFER_THROUGHPUT_MEDIAN_BENCHMARK_KBPS = 20 # 20KBps 37WIFI_TRANSFER_THROUGHPUT_MEDIAN_BENCHMARK_KBPS = 10240 # 10MBps 38BT_TRANSFER_SUCCESS_RATE_TARGET_PERCENTAGE = 95 # 95% 39WIFI_TRANSFER_SUCCESS_RATE_TARGET_PERCENTAGE = 95 # 95% 40 41KEEP_ALIVE_TIMEOUT_BT_MS = 30000 42KEEP_ALIVE_INTERVAL_BT_MS = 5000 43 44KEEP_ALIVE_TIMEOUT_WIFI_MS = 10000 45KEEP_ALIVE_INTERVAL_WIFI_MS = 3000 46 47PERCENTILE_50_FACTOR = 0.5 48PERCENTILE_95_FACTOR = 0.95 49LATENCY_PRECISION_DIGITS = 1 50SUCCESS_RATE_PRECISION_DIGITS = 1 51 52UNSET_LATENCY = datetime.timedelta.max 53UNSET_THROUGHPUT_KBPS = -1.0 54MAX_NUM_BUG_REPORT = 5 55TARGET_POST_WIFI_CONNECTION_IDLE_TIME_SEC = 0 56 57 58@enum.unique 59class PayloadType(enum.IntEnum): 60 FILE = 2 61 STREAM = 3 62 63 64@enum.unique 65class NearbyMedium(enum.IntEnum): 66 """Medium options for discovery, advertising, connection and upgrade.""" 67 68 AUTO = 0 69 BT_ONLY = 1 70 BLE_ONLY = 2 71 WIFILAN_ONLY = 3 72 WIFIAWARE_ONLY = 4 73 UPGRADE_TO_WEBRTC = 5 74 UPGRADE_TO_WIFIHOTSPOT = 6 75 UPGRADE_TO_WIFIDIRECT = 7 76 BLE_L2CAP_ONLY = 8 77 # including WIFI_WLAN, WIFI_HOTSPOT, WIFI_DIRECT 78 UPGRADE_TO_ALL_WIFI = 9 79 80 81@dataclasses.dataclass(frozen=False) 82class TestParameters: 83 """Test parameters to be customized for Nearby Connection.""" 84 85 test_report_alias_name: str = 'unspecified' 86 fast_fail_on_any_error: bool = False 87 wifi_country_code: str = '' 88 wifi_ssid: str = '' 89 wifi_password: str = '' 90 toggle_airplane_mode_target_side: bool = True 91 reset_wifi_connection: bool = True 92 disconnect_bt_after_test: bool = False 93 disconnect_wifi_after_test: bool = False 94 bt_transfer_throughput_median_benchmark_kbps: float = ( 95 BT_TRANSFER_THROUGHPUT_MEDIAN_BENCHMARK_KBPS 96 ) 97 wifi_transfer_throughput_median_benchmark_kbps: float = ( 98 WIFI_TRANSFER_THROUGHPUT_MEDIAN_BENCHMARK_KBPS 99 ) 100 payload_type: PayloadType = PayloadType.FILE 101 advertising_discovery_medium: int = NearbyMedium.BLE_ONLY 102 connection_medium: int = NearbyMedium.BT_ONLY 103 upgrade_medium: int = NearbyMedium.UPGRADE_TO_ALL_WIFI 104 allow_unrooted_device: bool = False 105 keep_alive_timeout_ms: int = KEEP_ALIVE_TIMEOUT_WIFI_MS 106 keep_alive_interval_ms: int = KEEP_ALIVE_INTERVAL_WIFI_MS 107 target_post_wifi_connection_idle_time_sec: int = ( 108 TARGET_POST_WIFI_CONNECTION_IDLE_TIME_SEC 109 ) 110 111 112@enum.unique 113class NearbyConnectionMedium(enum.IntEnum): 114 """The final connection medium selected, see BandWidthInfo.Medium.""" 115 UNKNOWN = 0 116 # reserved 1, it's Medium.MDNS, not used now 117 BLUETOOTH = 2 118 WIFI_HOTSPOT = 3 119 BLE = 4 120 WIFI_LAN = 5 121 WIFI_AWARE = 6 122 NFC = 7 123 WIFI_DIRECT = 8 124 WEB_RTC = 9 125 # 10 is reserved. 126 USB = 11 127 128 129def is_high_quality_medium(medium: NearbyMedium) -> bool: 130 return medium in { 131 NearbyMedium.WIFILAN_ONLY, 132 NearbyMedium.WIFIAWARE_ONLY, 133 NearbyMedium.UPGRADE_TO_WEBRTC, 134 NearbyMedium.UPGRADE_TO_WIFIHOTSPOT, 135 NearbyMedium.UPGRADE_TO_WIFIDIRECT, 136 NearbyMedium.UPGRADE_TO_ALL_WIFI, 137 } 138 139 140@enum.unique 141class MediumUpgradeType(enum.IntEnum): 142 DEFAULT = 0 143 DISRUPTIVE = 1 144 NON_DISRUPTIVE = 2 145 146 147@dataclasses.dataclass(frozen=True) 148class ConnectionSetupTimeouts: 149 """The timeouts of the nearby connection setup.""" 150 discovery_timeout: datetime.timedelta | None = None 151 connection_init_timeout: datetime.timedelta | None = None 152 connection_result_timeout: datetime.timedelta | None = None 153 154 155@dataclasses.dataclass(frozen=False) 156class ConnectionSetupQualityInfo: 157 """The quality information of the nearby connection setup.""" 158 discovery_latency: datetime.timedelta = UNSET_LATENCY 159 connection_latency: datetime.timedelta = UNSET_LATENCY 160 medium_upgrade_latency: datetime.timedelta = UNSET_LATENCY 161 medium_upgrade_expected: bool = False 162 upgrade_medium: NearbyConnectionMedium | None = None 163 164 def get_dict(self): 165 dict_repr = { 166 'discovery': f'{round(self.discovery_latency.total_seconds(), 1)}s', 167 'connection': f'{round(self.connection_latency.total_seconds(), 1)}s' 168 } 169 if self.medium_upgrade_expected: 170 dict_repr['upgrade'] = ( 171 f'{round(self.medium_upgrade_latency.total_seconds(), 1)}s' 172 ) 173 if self.upgrade_medium: 174 dict_repr['medium'] = self.upgrade_medium.name 175 return dict_repr 176 177 178@dataclasses.dataclass(frozen=False) 179class SingleTestResult: 180 """The test result of a single iteration.""" 181 182 connection_setup_quality_info: ConnectionSetupQualityInfo = ( 183 dataclasses.field(default_factory=ConnectionSetupQualityInfo) 184 ) 185 bt_transfer_throughput_kbps: float = UNSET_THROUGHPUT_KBPS 186 discoverer_wifi_wlan_latency: datetime.timedelta = UNSET_LATENCY 187 second_connection_setup_quality_info: ConnectionSetupQualityInfo = ( 188 dataclasses.field(default_factory=ConnectionSetupQualityInfo) 189 ) 190 wifi_transfer_throughput_kbps: float = UNSET_THROUGHPUT_KBPS 191 advertiser_wifi_wlan_latency: datetime.timedelta = UNSET_LATENCY 192 discoverer_wifi_wlan_expected: bool = False 193 advertiser_wifi_wlan_expected: bool = False 194 195 196@dataclasses.dataclass(frozen=True) 197class LatencyResultStats: 198 average_latency: float 199 percentile_50: float 200 percentile_95: float 201 failure_count: int 202 203 204@dataclasses.dataclass(frozen=True) 205class FailTargetSummary: 206 title: str = '' 207 actual: float = 0.0 208 goal: float = 0.0 209 unit: str = '' 210 211 212@dataclasses.dataclass(frozen=True) 213class ThroughputResultStats: 214 success_rate: float 215 average_kbps: float 216 percentile_50_kbps: float 217 percentile_95_kbps: float 218 success_count: int 219 fail_targets: list[FailTargetSummary] = dataclasses.field( 220 default_factory=list) 221 222 223@dataclasses.dataclass(frozen=False) 224class QuickStartTestMetrics: 225 """Metrics data for quick start test.""" 226 first_discovery_latencies: list[datetime.timedelta] = dataclasses.field( 227 default_factory=list[datetime.timedelta]) 228 first_connection_latencies: list[datetime.timedelta] = dataclasses.field( 229 default_factory=list[datetime.timedelta]) 230 discoverer_wifi_wlan_latencies: list[ 231 datetime.timedelta] = dataclasses.field( 232 default_factory=list[datetime.timedelta]) 233 bt_transfer_throughputs_kbps: list[float] = dataclasses.field( 234 default_factory=list[float]) 235 second_discovery_latencies: list[datetime.timedelta] = dataclasses.field( 236 default_factory=list[datetime.timedelta] 237 ) 238 second_connection_latencies: list[datetime.timedelta] = dataclasses.field( 239 default_factory=list[datetime.timedelta]) 240 medium_upgrade_latencies: list[ 241 datetime.timedelta] = dataclasses.field( 242 default_factory=list[datetime.timedelta]) 243 advertiser_wifi_wlan_latencies: list[ 244 datetime.timedelta] = dataclasses.field( 245 default_factory=list[datetime.timedelta]) 246 wifi_transfer_throughputs_kbps: list[float] = dataclasses.field( 247 default_factory=list[float]) 248 upgraded_wifi_transfer_mediums: list[NearbyConnectionMedium] = ( 249 dataclasses.field(default_factory=list[NearbyConnectionMedium])) 250